bench: v0.23.0 validation — 5/6 PASS, 6/6 completed #76
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Auto release on version bump | |
| # Fires on merge of ANY PR to master. Exits early unless package.json's | |
| # `version` field differs from the parent commit's — so PRs that don't | |
| # touch version are cheap no-ops (~10s). When the version did change, | |
| # creates the matching `vX.Y.Z` tag + GitHub release AND publishes to | |
| # npm inline — both steps in the same job. | |
| # | |
| # Why inline-publish rather than relying on publish.yml's `release: | |
| # published` trigger: GitHub intentionally doesn't fire other workflows | |
| # for events created by GITHUB_TOKEN (loop protection). So | |
| # `gh release create` here would create the release but NOT kick | |
| # publish.yml — which cost us a manual delete+recreate on v0.3.0 before | |
| # this was fixed. Inlining means the chain is: | |
| # PR merge → this workflow → tag+release+npm publish in one run. | |
| # | |
| # publish.yml stays in place for the *manual* release case (a maintainer | |
| # running `gh release create` locally does trigger publish.yml, since | |
| # that release event isn't from GITHUB_TOKEN). | |
| on: | |
| pull_request: | |
| types: [closed] | |
| branches: [master] | |
| permissions: | |
| contents: write | |
| # id-token: write required for `npm publish --provenance` (SLSA | |
| # attestation). Without this, npm publish would fail or skip provenance. | |
| id-token: write | |
| jobs: | |
| release: | |
| # Guards stacked so a closed-but-not-merged PR or a merge that didn't | |
| # touch package.json never fires a release: | |
| # 1. pull_request event type must be `closed` (implicit from `on:`) | |
| # 2. `merged == true` rules out close-without-merge | |
| # 3. version-changed check (first step) short-circuits the rest | |
| if: github.event.pull_request.merged == true | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout master (post-merge state) | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| ref: master | |
| fetch-depth: 2 # need HEAD^1 for the version-diff check | |
| - name: Check if version actually changed | |
| id: ver | |
| # Compares package.json's `version` field between HEAD and HEAD^1. | |
| # Unchanged → skip. Malformed (non-X.Y.Z) → abort loudly. Bumped | |
| # cleanly → proceed with `version` + `changed=true` as outputs. | |
| run: | | |
| set -eo pipefail | |
| CURRENT=$(node -pe "require('./package.json').version") | |
| PARENT=$(git show HEAD^1:package.json 2>/dev/null \ | |
| | node -pe "JSON.parse(require('fs').readFileSync(0,'utf-8')).version" \ | |
| || echo "") | |
| if [ "$CURRENT" = "$PARENT" ]; then | |
| echo "Version unchanged at $CURRENT — not releasing." | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if ! [[ "$CURRENT" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "Refusing to release — package.json version '$CURRENT' doesn't match X.Y.Z" >&2 | |
| exit 1 | |
| fi | |
| echo "Version bumped: $PARENT → $CURRENT" | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| echo "version=$CURRENT" >> "$GITHUB_OUTPUT" | |
| - name: Ensure tag doesn't already exist | |
| if: steps.ver.outputs.changed == 'true' | |
| run: | | |
| TAG="v${{ steps.ver.outputs.version }}" | |
| if git rev-parse "$TAG" >/dev/null 2>&1; then | |
| echo "Tag $TAG already exists — likely a previous run already released this version. Aborting to avoid tag-overwrite." | |
| exit 1 | |
| fi | |
| # ─── Build + test pipeline (mirrors publish.yml) ────────────── | |
| # We do this BEFORE cutting the GitHub release, so a failing | |
| # build/test aborts everything — no release, no npm publish, no | |
| # half-shipped state. Node 22 matches publish.yml's choice. | |
| - name: Set up Node | |
| if: steps.ver.outputs.changed == 'true' | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: 22 | |
| registry-url: https://registry.npmjs.org | |
| - name: npm ci | |
| if: steps.ver.outputs.changed == 'true' | |
| env: | |
| PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1" | |
| run: npm ci | |
| - name: typecheck | |
| if: steps.ver.outputs.changed == 'true' | |
| run: npm run typecheck | |
| - name: build | |
| if: steps.ver.outputs.changed == 'true' | |
| run: npm run build | |
| - name: test | |
| if: steps.ver.outputs.changed == 'true' | |
| run: npm test | |
| - name: --help smoke | |
| if: steps.ver.outputs.changed == 'true' | |
| run: node dist/cli.js --help | |
| # ─── Release + publish ──────────────────────────────────────── | |
| - name: Extract release notes from CHANGELOG | |
| if: steps.ver.outputs.changed == 'true' | |
| # Pulls the section for this version from CHANGELOG.md so the | |
| # GitHub release body shows what was in the bump, not a generic | |
| # "see changelog" link. Tiny Node one-liner to avoid shell- | |
| # escaping the markdown. | |
| run: | | |
| set -eo pipefail | |
| VERSION="${{ steps.ver.outputs.version }}" | |
| node -e " | |
| const fs = require('fs'); | |
| const md = fs.readFileSync('CHANGELOG.md', 'utf-8'); | |
| const re = new RegExp('^## \\\\[' + '${VERSION}' + '\\\\][^\\\\n]*\\\\n([\\\\s\\\\S]*?)(?=\\\\n## \\\\[|$)', 'm'); | |
| const m = re.exec(md); | |
| process.stdout.write(m ? m[1].trim() : '(no changelog section found for this version)'); | |
| " > release-notes.md | |
| echo "--- release-notes.md ---" | |
| cat release-notes.md | |
| - name: Create GitHub release | |
| if: steps.ver.outputs.changed == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG="v${{ steps.ver.outputs.version }}" | |
| { | |
| echo "Auto-released from merge of [PR #${{ github.event.pull_request.number }}](${{ github.event.pull_request.html_url }})." | |
| echo "" | |
| cat release-notes.md | |
| echo "" | |
| echo "---" | |
| echo "" | |
| echo "Built + tested + npm-published inline by \`auto-release.yml\` on this run. See the workflow log for the provenance-attested publish output." | |
| } > body.md | |
| gh release create "$TAG" --title "$TAG" --notes-file body.md | |
| - name: npm publish | |
| if: steps.ver.outputs.changed == 'true' | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: npm publish --access public --provenance | |
| - name: Post-release summary | |
| if: steps.ver.outputs.changed == 'true' | |
| run: | | |
| echo "✓ Released v${{ steps.ver.outputs.version }}" | |
| echo "✓ Triggered by PR #${{ github.event.pull_request.number }}" | |
| echo "✓ Published to npm (with SLSA provenance)" |