diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..59ba355 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,56 @@ +name: Release + +# Publish to npm + cut a GitHub Release when a version tag is pushed. +# Flow: bump package.json → merge to main → `git tag v0.1.5 && git push --tags`. +# Requires repo secret NPM_TOKEN (a granular/automation token with publish + bypass-2FA). +on: + push: + tags: ['v*.*.*'] + workflow_dispatch: {} + +permissions: + contents: write # cut the GitHub Release + +jobs: + publish: + name: publish to npm + GitHub Release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: ">=1.1" + + - name: Setup Node (registry auth) + uses: actions/setup-node@v4 + with: + node-version: "20" + registry-url: "https://registry.npmjs.org" + + - name: Install + run: bun install --frozen-lockfile + + # Guard: a v0.1.5 tag must match package.json 0.1.5, so a mistagged push + # can never publish the wrong version. + - name: Tag matches package.json version + if: github.event_name == 'push' + run: | + TAG="${GITHUB_REF_NAME#v}" + PKG="$(node -p "require('./package.json').version")" + echo "tag=$TAG package.json=$PKG" + [ "$TAG" = "$PKG" ] || { echo "::error::tag $TAG != package.json $PKG"; exit 1; } + + # `npm publish` runs prepublishOnly (build + tests + gen:check + compat + + # migrations) before uploading, so the gate is enforced here too. + - name: Publish to npm + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Create GitHub Release + if: github.event_name == 'push' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --generate-notes