diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..03ef47a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,63 @@ +# Release on every push to master (i.e. a merged PR) whose package.json version +# has no GitHub release yet. Bump "version" in the PR to cut a release; pushes +# that keep the version (benchmark refreshes, docs) are no-ops. An existing +# vX.Y.Z tag is reused as-is, otherwise the tag is created on the pushed commit. +name: release + +on: + push: + branches: [master] + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: release + cancel-in-progress: false + +jobs: + release: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Resolve version + id: version + env: + GH_TOKEN: ${{ github.token }} + run: | + version=$(node -p 'require("./package.json").version') + tag="v${version}" + echo "tag=${tag}" >> "$GITHUB_OUTPUT" + if gh release view "$tag" >/dev/null 2>&1; then + echo "Release $tag already exists; nothing to do." + echo "skip=true" >> "$GITHUB_OUTPUT" + else + echo "skip=false" >> "$GITHUB_OUTPUT" + fi + + - uses: actions/setup-node@v4 + if: steps.version.outputs.skip == 'false' + with: + node-version: 24 + cache: npm + + - name: Test + if: steps.version.outputs.skip == 'false' + run: | + npm ci + npm test + npm run lint + npm run knip + + - name: Create release + if: steps.version.outputs.skip == 'false' + env: + GH_TOKEN: ${{ github.token }} + TAG: ${{ steps.version.outputs.tag }} + run: | + gh release create "$TAG" --target "$GITHUB_SHA" --title "$TAG" --generate-notes --latest