diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dbc263b..c002e65 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,22 +41,3 @@ jobs: - name: Test id: npm-ci-test run: npm run ci-test - - test-action: - name: GitHub Actions Test - runs-on: ubuntu-latest - - steps: - - name: Checkout - id: checkout - uses: actions/checkout@v4 - - - name: Test Local Action - id: test-action - uses: ./ - with: - milliseconds: 2000 - - - name: Print Output - id: output - run: echo "${{ steps.test-action.outputs.time }}" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 6ad7cb6..0000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: CodeQL - -on: - push: - branches: - - main - pull_request: - branches: - - main - schedule: - - cron: '31 7 * * 3' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - - permissions: - actions: read - checks: write - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: - - TypeScript - - steps: - - name: Checkout - id: checkout - uses: actions/checkout@v4 - - - name: Initialize CodeQL - id: initialize - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - source-root: src - - - name: Autobuild - id: autobuild - uses: github/codeql-action/autobuild@v3 - - - name: Perform CodeQL Analysis - id: analyze - uses: github/codeql-action/analyze@v3 diff --git a/CODEOWNERS b/CODEOWNERS deleted file mode 100644 index a9802d7..0000000 --- a/CODEOWNERS +++ /dev/null @@ -1,4 +0,0 @@ -# Repository CODEOWNERS - -* @actions/actions-runtime -* @ncalteen diff --git a/README.md b/README.md index f198d8a..b09d23b 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,29 @@ -# Create a GitHub Action Using TypeScript +# valkyrie-thread-action -[![GitHub Super-Linter](https://github.com/actions/typescript-action/actions/workflows/linter.yml/badge.svg)](https://github.com/super-linter/super-linter) -![CI](https://github.com/actions/typescript-action/actions/workflows/ci.yml/badge.svg) -[![Check dist/](https://github.com/actions/typescript-action/actions/workflows/check-dist.yml/badge.svg)](https://github.com/actions/typescript-action/actions/workflows/check-dist.yml) -[![CodeQL](https://github.com/actions/typescript-action/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/actions/typescript-action/actions/workflows/codeql-analysis.yml) -[![Coverage](./badges/coverage.svg)](./badges/coverage.svg) +This action can be triggered after a release tag is created to start a thread +with the release details. -Use this template to bootstrap the creation of a TypeScript action. :rocket: - -This template includes compilation support, tests, a validation workflow, -publishing, and versioning guidance. - -If you are new, there's also a simpler introduction in the -[Hello world JavaScript action repository](https://github.com/actions/hello-world-javascript-action). - -## Create Your Own Action - -To create your own action, you can use this repository as a template! Just -follow the below instructions: - -1. Click the **Use this template** button at the top of the repository -1. Select **Create a new repository** -1. Select an owner and name for your new repository -1. Click **Create repository** -1. Clone your new repository - -> [!IMPORTANT] -> -> Make sure to remove or update the [`CODEOWNERS`](./CODEOWNERS) file! For -> details on how to use this file, see -> [About code owners](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners). +## Usage -## Initial Setup +```yaml +on: + push: + tags: + - v1.* -After you've cloned the repository to your local machine or codespace, you'll -need to perform some initial setup steps before you can develop your action. +steps: + - name: Example action + id: example-action + uses: thesis/valyrie-thread-action@v1 + with: + threadName: 'v1.0' + channellName: 'release' + message: 'release notes' + webhookUrl: { { secrets.WEBHOOK_URL } } + webhookAuth: { { secrets.WEBHOOK_AUTH } } +``` -> [!NOTE] -> -> You'll need to have a reasonably modern version of -> [Node.js](https://nodejs.org) handy (20.x or later should work!). If you are -> using a version manager like [`nodenv`](https://github.com/nodenv/nodenv) or -> [`nvm`](https://github.com/nvm-sh/nvm), this template has a `.node-version` -> file at the root of the repository that will be used to automatically switch -> to the correct version when you `cd` into the repository. Additionally, this -> `.node-version` file is used by GitHub Actions in any `actions/setup-node` -> actions. +## Initial Local Setup 1. :hammer_and_wrench: Install the dependencies @@ -59,65 +37,8 @@ need to perform some initial setup steps before you can develop your action. npm run bundle ``` -1. :white_check_mark: Run the tests - - ```bash - $ npm test - - PASS ./index.test.js - ✓ throws invalid number (3ms) - ✓ wait 500 ms (504ms) - ✓ test runs (95ms) - - ... - ``` - -## Update the Action Metadata - -The [`action.yml`](action.yml) file defines metadata about your action, such as -input(s) and output(s). For details about this file, see -[Metadata syntax for GitHub Actions](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions). - -When you copy this repository, update `action.yml` with the name, description, -inputs, and outputs for your action. - -## Update the Action Code - -The [`src/`](./src/) directory is the heart of your action! This contains the -source code that will be run when your action is invoked. You can replace the -contents of this directory with your own code. - -There are a few things to keep in mind when writing your action code: - -- Most GitHub Actions toolkit and CI/CD operations are processed asynchronously. - In `main.ts`, you will see that the action is run in an `async` function. - - ```javascript - import * as core from '@actions/core' - //... +## Updating the action - async function run() { - try { - //... - } catch (error) { - core.setFailed(error.message) - } - } - ``` - - For more information about the GitHub Actions toolkit, see the - [documentation](https://github.com/actions/toolkit/blob/master/README.md). - -So, what are you waiting for? Go ahead and start customizing your action! - -1. Create a new branch - - ```bash - git checkout -b releases/v1 - ``` - -1. Replace the contents of `src/` with your action code -1. Add tests to `__tests__/` for your source code 1. Format, test, and build the action ```bash @@ -133,82 +54,6 @@ So, what are you waiting for? Go ahead and start customizing your action! > `ncc`, which will create a license file for all of the production node > modules used in your project. -1. Commit your changes - - ```bash - git add . - git commit -m "My first action is ready!" - ``` - -1. Push them to your repository - - ```bash - git push -u origin releases/v1 - ``` - -1. Create a pull request and get feedback on your action -1. Merge the pull request into the `main` branch - -Your action is now published! :rocket: - -For information about versioning your action, see -[Versioning](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) -in the GitHub Actions toolkit. - -## Validate the Action - -You can now validate the action by referencing it in a workflow file. For -example, [`ci.yml`](./.github/workflows/ci.yml) demonstrates how to reference an -action in the same repository. - -```yaml -steps: - - name: Checkout - id: checkout - uses: actions/checkout@v4 - - - name: Test Local Action - id: test-action - uses: ./ - with: - milliseconds: 1000 - - - name: Print Output - id: output - run: echo "${{ steps.test-action.outputs.time }}" -``` - -For example workflow runs, check out the -[Actions tab](https://github.com/actions/typescript-action/actions)! :rocket: - -## Usage - -After testing, you can create version tag(s) that developers can use to -reference different stable versions of your action. For more information, see -[Versioning](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) -in the GitHub Actions toolkit. - -To include the action in a workflow in another repository, you can use the -`uses` syntax with the `@` symbol to reference a specific branch, tag, or commit -hash. - -```yaml -steps: - - name: Checkout - id: checkout - uses: actions/checkout@v4 - - - name: Test Local Action - id: test-action - uses: actions/typescript-action@v1 # Commit with the `v1` tag - with: - milliseconds: 1000 - - - name: Print Output - id: output - run: echo "${{ steps.test-action.outputs.time }}" -``` - ## Publishing a new release This project includes a helper script designed to streamline the process of diff --git a/__tests__/index.test.ts b/__tests__/index.test.ts index 34a4dfe..ebc5516 100644 --- a/__tests__/index.test.ts +++ b/__tests__/index.test.ts @@ -5,7 +5,7 @@ import * as main from '../src/main' // Mock the action's entrypoint -const runMock = jest.spyOn(main, 'run').mockImplementation() +const runMock = jest.spyOn(main, 'createThread').mockImplementation() describe('index', () => { it('calls run when imported', async () => { diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts deleted file mode 100644 index 30efdfb..0000000 --- a/__tests__/main.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Unit tests for the action's main functionality, src/main.ts - * - * These should be run as if the action was called from a workflow. - * Specifically, the inputs listed in `action.yml` should be set as environment - * variables following the pattern `INPUT_`. - */ - -import * as core from '@actions/core' -import * as main from '../src/main' - -// Mock the action's main function -const runMock = jest.spyOn(main, 'run') - -// Other utilities -const timeRegex = /^\d{2}:\d{2}:\d{2}/ - -// Mock the GitHub Actions core library -let debugMock: jest.SpyInstance -let errorMock: jest.SpyInstance -let getInputMock: jest.SpyInstance -let setFailedMock: jest.SpyInstance -let setOutputMock: jest.SpyInstance - -describe('action', () => { - beforeEach(() => { - jest.clearAllMocks() - - debugMock = jest.spyOn(core, 'debug').mockImplementation() - errorMock = jest.spyOn(core, 'error').mockImplementation() - getInputMock = jest.spyOn(core, 'getInput').mockImplementation() - setFailedMock = jest.spyOn(core, 'setFailed').mockImplementation() - setOutputMock = jest.spyOn(core, 'setOutput').mockImplementation() - }) - - it('sets the time output', async () => { - // Set the action's inputs as return values from core.getInput() - getInputMock.mockImplementation((name: string): string => { - switch (name) { - case 'milliseconds': - return '500' - default: - return '' - } - }) - - await main.run() - expect(runMock).toHaveReturned() - - // Verify that all of the core library functions were called correctly - expect(debugMock).toHaveBeenNthCalledWith(1, 'Waiting 500 milliseconds ...') - expect(debugMock).toHaveBeenNthCalledWith( - 2, - expect.stringMatching(timeRegex) - ) - expect(debugMock).toHaveBeenNthCalledWith( - 3, - expect.stringMatching(timeRegex) - ) - expect(setOutputMock).toHaveBeenNthCalledWith( - 1, - 'time', - expect.stringMatching(timeRegex) - ) - expect(errorMock).not.toHaveBeenCalled() - }) - - it('sets a failed status', async () => { - // Set the action's inputs as return values from core.getInput() - getInputMock.mockImplementation((name: string): string => { - switch (name) { - case 'milliseconds': - return 'this is not a number' - default: - return '' - } - }) - - await main.run() - expect(runMock).toHaveReturned() - - // Verify that all of the core library functions were called correctly - expect(setFailedMock).toHaveBeenNthCalledWith( - 1, - 'milliseconds not a number' - ) - expect(errorMock).not.toHaveBeenCalled() - }) -}) diff --git a/__tests__/wait.test.ts b/__tests__/wait.test.ts deleted file mode 100644 index 1336aaa..0000000 --- a/__tests__/wait.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Unit tests for src/wait.ts - */ - -import { wait } from '../src/wait' -import { expect } from '@jest/globals' - -describe('wait.ts', () => { - it('throws an invalid number', async () => { - const input = parseInt('foo', 10) - expect(isNaN(input)).toBe(true) - - await expect(wait(input)).rejects.toThrow('milliseconds not a number') - }) - - it('waits with a valid number', async () => { - const start = new Date() - await wait(500) - const end = new Date() - - const delta = Math.abs(end.getTime() - start.getTime()) - - expect(delta).toBeGreaterThan(450) - }) -}) diff --git a/action.yml b/action.yml index 101186a..62b12dc 100644 --- a/action.yml +++ b/action.yml @@ -1,23 +1,23 @@ -name: 'The name of your action here' -description: 'Provide a description here' -author: 'Your name or organization here' +name: 'valyrie-thread-action' +description: 'Triggers a thread in a Discord channel.' -# Add your action's branding here. This will appear on the GitHub Marketplace. -branding: - icon: 'heart' - color: 'red' - -# Define your inputs here. inputs: - milliseconds: - description: 'Your input description here' + threadName: + description: 'The name of the thread.' + required: true + default: 'release' + channellName: + description: 'The name of the channel to create the thread in.' + required: true + message: + description: 'The message to send in the thread.' + required: false + default: '.' + webhookUrl: + description: 'The webhook url to send the message to.' + required: true + webhookAuth: required: true - default: '1000' - -# Define your outputs here. -outputs: - time: - description: 'Your output description here' runs: using: node20 diff --git a/badges/coverage.svg b/badges/coverage.svg index 5bb55be..1063f3d 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 100%Coverage100% \ No newline at end of file +Coverage: 36.36%Coverage36.36% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 9bbc394..30b8624 100644 --- a/dist/index.js +++ b/dist/index.js @@ -2751,24 +2751,29 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.run = void 0; +exports.createThread = void 0; const core = __importStar(__nccwpck_require__(186)); -const wait_1 = __nccwpck_require__(259); /** * The main function for the action. * @returns {Promise} Resolves when the action is complete. */ -async function run() { +async function createThread() { try { - const ms = core.getInput('milliseconds'); - // Debug logs are only output if the `ACTIONS_STEP_DEBUG` secret is true - core.debug(`Waiting ${ms} milliseconds ...`); - // Log the current timestamp, wait, then log the new timestamp - core.debug(new Date().toTimeString()); - await (0, wait_1.wait)(parseInt(ms, 10)); - core.debug(new Date().toTimeString()); - // Set outputs for other workflow steps to use - core.setOutput('time', new Date().toTimeString()); + const webhookUrl = core.getInput('webhookUrl'); + const webhookAuth = core.getInput('webhookAuth'); + await fetch(webhookUrl, { + method: 'POST', + headers: { + Accept: 'application/json', + Authorization: webhookAuth + }, + body: JSON.stringify({ + channelName: core.getInput('channelName'), + title: core.getInput('threadName'), + message: core.getInput('message') + }) + }); + core.info('Thread created'); } catch (error) { // Fail the workflow run if an error occurs @@ -2776,32 +2781,7 @@ async function run() { core.setFailed(error.message); } } -exports.run = run; - - -/***/ }), - -/***/ 259: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.wait = void 0; -/** - * Wait for a number of milliseconds. - * @param milliseconds The number of milliseconds to wait. - * @returns {Promise} Resolves with 'done!' after the wait is over. - */ -async function wait(milliseconds) { - return new Promise(resolve => { - if (isNaN(milliseconds)) { - throw new Error('milliseconds not a number'); - } - setTimeout(() => resolve('done!'), milliseconds); - }); -} -exports.wait = wait; +exports.createThread = createThread; /***/ }), @@ -2943,8 +2923,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); * The entrypoint for the action. */ const main_1 = __nccwpck_require__(399); -// eslint-disable-next-line @typescript-eslint/no-floating-promises -(0, main_1.run)(); +(0, main_1.createThread)(); })(); diff --git a/package-lock.json b/package-lock.json index aa22c45..15cb731 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "typescript-action", + "name": "valkyrie-thread-action", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "typescript-action", + "name": "valkyrie-thread-action", "version": "0.0.0", "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index c548558..0ee4c0d 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,9 @@ { - "name": "typescript-action", + "name": "valkyrie-thread-action", "description": "GitHub Actions TypeScript template", "version": "0.0.0", "author": "", "private": true, - "homepage": "https://github.com/actions/typescript-action", - "repository": { - "type": "git", - "url": "git+https://github.com/actions/typescript-action.git" - }, - "bugs": { - "url": "https://github.com/actions/typescript-action/issues" - }, - "keywords": [ - "actions", - "node", - "setup" - ], "exports": { ".": "./dist/index.js" }, diff --git a/src/index.ts b/src/index.ts index b08f970..a65ffae 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,6 @@ /** * The entrypoint for the action. */ -import { run } from './main' +import { createThread } from './main' -// eslint-disable-next-line @typescript-eslint/no-floating-promises -run() +createThread() diff --git a/src/main.ts b/src/main.ts index c804f90..836287c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,24 +1,28 @@ import * as core from '@actions/core' -import { wait } from './wait' /** * The main function for the action. * @returns {Promise} Resolves when the action is complete. */ -export async function run(): Promise { +export async function createThread(): Promise { try { - const ms: string = core.getInput('milliseconds') + const webhookUrl: string = core.getInput('webhookUrl') + const webhookAuth: string = core.getInput('webhookAuth') - // Debug logs are only output if the `ACTIONS_STEP_DEBUG` secret is true - core.debug(`Waiting ${ms} milliseconds ...`) + await fetch(webhookUrl, { + method: 'POST', + headers: { + Accept: 'application/json', + Authorization: webhookAuth + }, + body: JSON.stringify({ + channelName: core.getInput('channelName'), + title: core.getInput('threadName'), + message: core.getInput('message') + }) + }) - // Log the current timestamp, wait, then log the new timestamp - core.debug(new Date().toTimeString()) - await wait(parseInt(ms, 10)) - core.debug(new Date().toTimeString()) - - // Set outputs for other workflow steps to use - core.setOutput('time', new Date().toTimeString()) + core.info('Thread created') } catch (error) { // Fail the workflow run if an error occurs if (error instanceof Error) core.setFailed(error.message) diff --git a/src/wait.ts b/src/wait.ts deleted file mode 100644 index 0ddf692..0000000 --- a/src/wait.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Wait for a number of milliseconds. - * @param milliseconds The number of milliseconds to wait. - * @returns {Promise} Resolves with 'done!' after the wait is over. - */ -export async function wait(milliseconds: number): Promise { - return new Promise(resolve => { - if (isNaN(milliseconds)) { - throw new Error('milliseconds not a number') - } - - setTimeout(() => resolve('done!'), milliseconds) - }) -}