diff --git a/.gitattributes b/.gitattributes index 2e2c7b2..af30937 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -dist/** -diff linguist-generated=true \ No newline at end of file +dist/** -diff linguist-generated=true diff --git a/CODEOWNERS b/.github/CODEOWNERS similarity index 81% rename from CODEOWNERS rename to .github/CODEOWNERS index 6ac23c1..a9802d7 100644 --- a/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,4 @@ # Repository CODEOWNERS * @actions/actions-runtime -* @ncalteen \ No newline at end of file +* @ncalteen diff --git a/.github/workflows/check-dist.yml b/.github/workflows/check-dist.yml index 4d7f663..444f1a9 100644 --- a/.github/workflows/check-dist.yml +++ b/.github/workflows/check-dist.yml @@ -12,22 +12,17 @@ on: push: branches: - main - paths-ignore: - - '**.md' pull_request: - paths-ignore: - - '**.md' workflow_dispatch: +permissions: + contents: read + jobs: check-dist: name: Check dist/ runs-on: ubuntu-latest - permissions: - contents: read - statuses: write - steps: - name: Checkout id: checkout @@ -36,7 +31,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 18 + node-version-file: .node-version cache: npm - name: Install Dependencies diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44d8339..1dfab1c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,9 @@ on: - main - 'releases/*' +permissions: + contents: read + jobs: test-typescript: name: TypeScript Tests @@ -21,7 +24,7 @@ jobs: id: setup-node uses: actions/setup-node@v4 with: - node-version: 18 + node-version-file: .node-version cache: npm - name: Install Dependencies diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index bc00bf0..1f1c52c 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -5,19 +5,18 @@ on: branches: - main push: - branches-ignore: + branches: - main +permissions: + contents: read + statuses: write + jobs: lint: name: Lint Code Base runs-on: ubuntu-latest - permissions: - contents: read - packages: read - statuses: write - steps: - name: Checkout id: checkout @@ -27,7 +26,7 @@ jobs: id: setup-node uses: actions/setup-node@v4 with: - node-version: 18 + node-version-file: .node-version cache: npm - name: Install Dependencies diff --git a/.node-version b/.node-version new file mode 100644 index 0000000..1cc433a --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +20.6.0 diff --git a/.prettierignore b/.prettierignore index 64f046d..2d0c064 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,3 @@ dist/ node_modules/ -coverage/ \ No newline at end of file +coverage/ diff --git a/README.md b/README.md index 8aa27aa..ebe33cc 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ -# Create a JavaScript Action Using TypeScript +# Create a GitHub Action Using TypeScript [![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) Use this template to bootstrap the creation of a TypeScript action. :rocket: @@ -30,11 +33,13 @@ need to perform some initial setup steps before you can develop your action. > [!NOTE] > > You'll need to have a reasonably modern version of -> [Node.js](https://nodejs.org) handy. If you are using a version manager like -> [`nodenv`](https://github.com/nodenv/nodenv) or -> [`nvm`](https://github.com/nvm-sh/nvm), you can run `nodenv install` in the -> root of your repository to install the version specified in -> [`package.json`](./package.json). Otherwise, 20.x or later should work! +> [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. 1. :hammer_and_wrench: Install the dependencies @@ -154,7 +159,7 @@ action in the same repository. steps: - name: Checkout id: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Test Local Action id: test-action @@ -185,7 +190,7 @@ hash. steps: - name: Checkout id: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Test Local Action id: test-action @@ -197,3 +202,23 @@ steps: 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 +tagging and pushing new releases for GitHub Actions. + +GitHub Actions allows users to select a specific version of the action to use, +based on release tags. Our script simplifies this process by performing the +following steps: + +1. **Retrieving the latest release tag:** The script starts by fetching the most + recent release tag by looking at the local data available in your repository. +1. **Prompting for a new release tag:** The user is then prompted to enter a new + release tag. To assist with this, the script displays the latest release tag + and provides a regular expression to validate the format of the new tag. +1. **Tagging the new release:** Once a valid new tag is entered, the script tags + the new release. +1. **Pushing the new tag to the remote:** Finally, the script pushes the new tag + to the remote repository. From here, you will need to create a new release in + GitHub and users can easily reference the new tag in their workflows. diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 7a25abc..30efdfb 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -9,21 +9,28 @@ import * as core from '@actions/core' import * as main from '../src/main' -// Mock the GitHub Actions core library -const debugMock = jest.spyOn(core, 'debug') -const getInputMock = jest.spyOn(core, 'getInput') -const setFailedMock = jest.spyOn(core, 'setFailed') -const setOutputMock = jest.spyOn(core, 'setOutput') - // 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 () => { @@ -55,6 +62,7 @@ describe('action', () => { 'time', expect.stringMatching(timeRegex) ) + expect(errorMock).not.toHaveBeenCalled() }) it('sets a failed status', async () => { @@ -76,5 +84,6 @@ describe('action', () => { 1, 'milliseconds not a number' ) + expect(errorMock).not.toHaveBeenCalled() }) }) diff --git a/action.yml b/action.yml index 7f69e47..101186a 100644 --- a/action.yml +++ b/action.yml @@ -2,6 +2,11 @@ name: 'The name of your action here' description: 'Provide a description here' author: 'Your name or organization here' +# Add your action's branding here. This will appear on the GitHub Marketplace. +branding: + icon: 'heart' + color: 'red' + # Define your inputs here. inputs: milliseconds: diff --git a/script/release b/script/release new file mode 100755 index 0000000..0dd6139 --- /dev/null +++ b/script/release @@ -0,0 +1,47 @@ +#!/bin/bash + +# About: +# This is a helper script to tag and push a new release. +# GitHub Actions use release tags to allow users to select a specific version of the action to use. +# This script will do the following: +# 1. Get the latest release tag +# 2. Prompt the user for a new release tag (while displaying the latest release tag, and a regex to validate the new tag) +# 3. Tag the new release +# 4. Push the new tag to the remote + +# Usage: +# script/release + +# COLORS +OFF='\033[0m' +RED='\033[0;31m' +GREEN='\033[0;32m' +BLUE='\033[0;34m' + +latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)") + +# if the latest_tag is empty, then there are no tags - let the user know +if [[ -z "$latest_tag" ]]; then + echo -e "No tags found (yet) - continue to create your first tag and push it" + latest_tag="[unknown]" +fi + +echo -e "The latest release tag is: ${BLUE}${latest_tag}${OFF}" +read -r -p 'New Release Tag (vX.X.X format): ' new_tag + +tag_regex='v[0-9]+\.[0-9]+\.[0-9]+$' +if echo "$new_tag" | grep -q -E "$tag_regex"; then + echo -e "Tag: ${BLUE}$new_tag${OFF} is valid" +else + echo -e "Tag: ${BLUE}$new_tag${OFF} is ${RED}not valid${OFF} (must be in vX.X.X format)" + exit 1 +fi + +git tag -a "$new_tag" -m "$new_tag Release" + +echo -e "${GREEN}OK${OFF} - Tagged: $new_tag" + +git push --tags + +echo -e "${GREEN}OK${OFF} - Tags pushed to remote!" +echo -e "${GREEN}DONE${OFF}"