name: Release on: push: tags: - "v*" jobs: release: runs-on: ubuntu-latest permissions: contents: write steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 22 cache: npm - run: npm ci # The tagged commit is the release: `npm run release` commits the bare # X.Y.Z to it (main otherwise carries a `-develop` suffix). Verify the tag # matches that committed version exactly — this catches tagging the wrong # commit (e.g. a `-develop` one) without rewriting anything. - name: Verify package.json matches the tag env: TAG_NAME: ${{ github.ref_name }} run: | VERSION="${TAG_NAME#v}" PKG="$(node -p 'require("./package.json").version')" if [ "$VERSION" != "$PKG" ]; then echo "Tag $TAG_NAME does not match package.json ($PKG)." >&2 echo "The tagged commit must carry the bare release version ($VERSION)." >&2 echo "Cut releases with: npm run release $VERSION" >&2 exit 1 fi # Release notes come from the CHANGELOG section for this version, which is # written incrementally and reviewed in PRs — never hand-typed at release. - name: Extract release notes from CHANGELOG env: TAG_NAME: ${{ github.ref_name }} run: | VERSION="${TAG_NAME#v}" awk -v ver="$VERSION" ' $0 ~ "^## \\[" ver "\\]" {grab=1; next} /^## \[/ && grab {exit} grab { if (!started && $0 ~ /^[[:space:]]*$/) next; started=1; print } ' CHANGELOG.md > release-notes.md if [ ! -s release-notes.md ]; then echo "No CHANGELOG section found for $VERSION." >&2 exit 1 fi echo "Release notes for $VERSION:" cat release-notes.md - run: npm run build - name: Locate bundled output id: bundle run: | for f in dist/index.js dist/worker.js dist/_worker.js; do if [ -f "$f" ]; then echo "path=$f" >> "$GITHUB_OUTPUT" exit 0 fi done echo "No bundled output found in dist/" >&2 exit 1 - name: Create GitHub Release and upload bundle env: GH_TOKEN: ${{ github.token }} TAG_NAME: ${{ github.ref_name }} BUNDLE_PATH: ${{ steps.bundle.outputs.path }} run: | gh release create "$TAG_NAME" --title "$TAG_NAME" --notes-file release-notes.md --verify-tag || true gh release upload "$TAG_NAME" "$BUNDLE_PATH" --clobber