From 5f4631634c80e92103bec523a981869a0213bd6c Mon Sep 17 00:00:00 2001 From: Mark Wubben <mark@novemberborn.net> Date: Sat, 7 Jun 2025 15:54:16 +0200 Subject: [PATCH 1/3] Add Release workflow --- .github/workflows/release.yml | 66 +++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..1dea866bb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,66 @@ +name: Release +on: + push: + tags: + - 'v*' + +permissions: + contents: write + id-token: write + +jobs: + release: + name: Release + runs-on: ubuntu-latest + environment: npm + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Verify tag matches package.json version + run: | + PACKAGE_VERSION=$(jq -r '.version' package.json) + TAG_VERSION=${{ github.ref_name }} + TAG_VERSION=${TAG_VERSION#v} + if [ "$PACKAGE_VERSION" != "$TAG_VERSION" ]; then + echo "Package version ($PACKAGE_VERSION) does not match tag version ($TAG_VERSION)" + exit 1 + fi + + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: package.json + cache: npm + registry-url: https://registry.npmjs.org + + - name: Install dependencies + run: npm install --no-audit + + - name: Run tests + run: ./scripts/ci.sh + shell: bash + + - name: Upload code coverage + uses: codecov/codecov-action@v4 + with: + files: coverage/lcov.info + name: release-${{ github.ref_name }} + token: ${{ secrets.CODECOV_TOKEN }} + + - name: Publish to npm with provenance + run: npm publish --provenance + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Create GitHub Release + run: | + gh release create ${{ github.ref_name }} \ + --title "${{ github.ref_name }}" \ + --draft \ + --generate-notes + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 12ac80c7ba2184335ef30af30a79c060c7ecf00f Mon Sep 17 00:00:00 2001 From: Mark Wubben <mark@novemberborn.net> Date: Sat, 7 Jun 2025 15:53:58 +0200 Subject: [PATCH 2/3] Update maintaining.md Reflect actual process. --- maintaining.md | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/maintaining.md b/maintaining.md index eb8347591..d31b2319f 100644 --- a/maintaining.md +++ b/maintaining.md @@ -7,26 +7,28 @@ ## Testing * `npm test`: Lint the code and run the entire test suite with coverage. -* `npx tap test-tap/fork.js --bail`: Run a specific test file and bail on the first failure (useful when hunting bugs). -* `npx test-ava test/{file}.js`: Run self-hosted tests. +* `npx test-ava`: Run self-hosted tests from `test/`. Wraps a stable version of AVA. +* `npx tap`: Run legacy tests from `test-tap/`. + +Note that in CI we only run linting with the Node.js version set in the `package.json` file under the `"volta"` key. ## CI -* Tests sometimes fail on Windows. Review the errors carefully. -* At least one Windows job must pass. -* All other jobs must pass. +We test across Linux, macOS and Windows, across all supported Node.js versions. The occasional failure in a specific environment is to be expected. If jobs fail, review carefully. + +TypeScript jobs should all pass. ## Updating dependencies * Make sure new dependency versions are compatible with our supported Node.js versions. -* Leave the TypeScript dependency as it is, to avoid accidental breakage. +* TypeScript dependency changes require CI changes to ensure backwards compatibility, see below. * Open a PR with the updates and only merge when CI passes (see the previous section). ## Updating TypeScript TypeScript itself does not follow SemVer. Consequently we may have to make changes to the type definition that, technically, are breaking changes for users with an older TypeScript version. That's OK, but we should be aware. -Only update the TypeScript dependency when truly necessary. This helps avoid accidental breakage. For instance we won't accidentally rely on newer TypeScript features. +When updating the TypeScript dependency, *also* add it to the CI workflow. This enables us to do typechecking with previous TypeScript versions and avoid unintentional breakage. For instance we won't accidentally rely on newer TypeScript features. Speaking of, using newer TypeScript features could be considered a breaking change. This needs to be assessed on a case-by-case basis. @@ -34,7 +36,7 @@ Speaking of, using newer TypeScript features could be considered a breaking chan * New features should come with tests and documentation. * Ensure the [contributing guidelines](.github/CONTRIBUTING.md) are followed. -* Squash commits when merging. +* Usually we squash commits when merging. Rebases may sometimes be appropriate. ## Experiments @@ -43,9 +45,12 @@ Speaking of, using newer TypeScript features could be considered a breaking chan ## Release process -* Update dependencies (see the previous section). -* If [necessary](docs/support-statement.md), update the `engines` field in `package.json`. - * Remove unsupported (or soon to be) Node.js versions. - * When doing a major version bump, make sure to require the latest releases of each supported Node.js version. -* Publish a new version using [`np`](https://github.com/sindresorhus/np) with a version number according to [SemVer](https://semver.org). -* Write a [release note](https://github.com/avajs/ava/releases/new) following the style of previous release notes. +Use `npm version` with the correct increment and push the resulting tag and `main` branch. + +Approve the Release workflow within GitHub. The workflow includes npm provenance for enhanced security and supply chain transparency. + +### Setup Requirements + +For the automated workflows to work, the following secrets must be configured in the repository: + +- `NPM_TOKEN`: An npm automation token with publish permissions to the AVA package, within the `npm` environment From ce273af59c3a960f9d36b9997ab956e64bb09df1 Mon Sep 17 00:00:00 2001 From: Mark Wubben <mark@novemberborn.net> Date: Sat, 7 Jun 2025 16:19:06 +0200 Subject: [PATCH 3/3] Attempt to make Release workflow dependent on CI checks, with a manual trigger if necessary --- .github/workflows/ci.yml | 2 ++ .github/workflows/release.yml | 49 ++++++++++++++++++++++------------- maintaining.md | 6 ++--- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e11eaa93b..f04a2ba50 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,8 @@ on: push: branches: - main + tags: + - 'v*' pull_request: paths-ignore: - "*.md" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1dea866bb..0e73a591e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,6 +3,17 @@ on: push: tags: - 'v*' + workflow_dispatch: + inputs: + tag: + description: 'Release tag (e.g., v1.2.3)' + required: true + type: string + skip_ci_check: + description: 'Skip CI status check' + required: false + type: boolean + default: false permissions: contents: write @@ -17,17 +28,32 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: + ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }} fetch-depth: 0 + - name: Check CI status + if: ${{ !inputs.skip_ci_check }} + run: | + # Check if CI has completed successfully for this commit + RESULT=$(gh run list --commit ${{ github.sha }} --status success --json conclusion,workflowName | jq '.[]|select(.workflowName == "Install and test AVA")') + if [ -z "$RESULT" ]; then + echo "CI has not completed successfully for this commit" + exit 1 + fi + echo "All CI checks have passed!" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Verify tag matches package.json version run: | PACKAGE_VERSION=$(jq -r '.version' package.json) - TAG_VERSION=${{ github.ref_name }} - TAG_VERSION=${TAG_VERSION#v} + TAG_VERSION=${RELEASE_TAG#v} if [ "$PACKAGE_VERSION" != "$TAG_VERSION" ]; then echo "Package version ($PACKAGE_VERSION) does not match tag version ($TAG_VERSION)" exit 1 fi + env: + RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }} - name: Setup Node.js @@ -37,20 +63,6 @@ jobs: cache: npm registry-url: https://registry.npmjs.org - - name: Install dependencies - run: npm install --no-audit - - - name: Run tests - run: ./scripts/ci.sh - shell: bash - - - name: Upload code coverage - uses: codecov/codecov-action@v4 - with: - files: coverage/lcov.info - name: release-${{ github.ref_name }} - token: ${{ secrets.CODECOV_TOKEN }} - - name: Publish to npm with provenance run: npm publish --provenance env: @@ -58,9 +70,10 @@ jobs: - name: Create GitHub Release run: | - gh release create ${{ github.ref_name }} \ - --title "${{ github.ref_name }}" \ + gh release create "$RELEASE_TAG" \ + --title "$RELEASE_TAG" \ --draft \ --generate-notes env: + RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/maintaining.md b/maintaining.md index d31b2319f..e7c4d2f57 100644 --- a/maintaining.md +++ b/maintaining.md @@ -45,9 +45,9 @@ Speaking of, using newer TypeScript features could be considered a breaking chan ## Release process -Use `npm version` with the correct increment and push the resulting tag and `main` branch. - -Approve the Release workflow within GitHub. The workflow includes npm provenance for enhanced security and supply chain transparency. +* Use `npm version` with the correct increment and push the resulting tag and `main` branch. +* CI will run against the tag. Wait for this to complete. +* Approve the Release workflow within GitHub. The workflow includes npm provenance for enhanced security and supply chain transparency. ### Setup Requirements