chore(release): v0.3.4 #23
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: Publish to npm | |
| on: | |
| push: | |
| tags: ['v*'] | |
| workflow_dispatch: | |
| inputs: | |
| ref: | |
| description: 'Git ref (tag or SHA) to publish' | |
| required: true | |
| type: string | |
| permissions: | |
| contents: read | |
| jobs: | |
| publish: | |
| runs-on: ubuntu-latest | |
| # id-token: write lets this job mint an OIDC token that npm exchanges | |
| # for a short-lived publish credential via Trusted Publishing. No long- | |
| # lived NPM_TOKEN is stored or needed. contents: write lets the trailing | |
| # `gh release create --draft` step land a release on the repo. | |
| permissions: | |
| contents: write | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| ref: ${{ inputs.ref || github.ref }} | |
| - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| # Node 24 ships npm >= 11.5.1, required for the current OIDC | |
| # handshake — Node 22 / npm 10 silently falls back to anonymous | |
| # and npm responds with a misleading 404 on the PUT. This only | |
| # affects the publish step; CI still tests across 20/22 per the | |
| # package's engines range. | |
| node-version: '24' | |
| cache: 'pnpm' | |
| registry-url: 'https://registry.npmjs.org' | |
| - run: pnpm install --frozen-lockfile | |
| - run: pnpm build | |
| # Full test suite must pass before anything reaches npm. | |
| - run: pnpm vitest run | |
| # Idempotency guard for tag re-pushes (e.g. converting a lightweight | |
| # tag to an annotated one). Without this, a re-trigger dies with | |
| # "cannot publish over previously published versions: X" — harmless | |
| # but cosmetically red on the Actions list. | |
| - name: Check if version already published | |
| id: npm_check | |
| run: | | |
| PKG_NAME=$(node -p "require('./package.json').name") | |
| PKG_VERSION=$(node -p "require('./package.json').version") | |
| if npm view "$PKG_NAME@$PKG_VERSION" version >/dev/null 2>&1; then | |
| echo "Version $PKG_VERSION already on npm — skipping publish." | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| # --access public: scoped packages (@tznthou/*) default to private; | |
| # first publish must opt in explicitly. | |
| # --no-git-checks: pnpm otherwise refuses to publish from a CI | |
| # detached-HEAD checkout. | |
| # --provenance: attach a SLSA provenance attestation derived from | |
| # the OIDC token. Triggers the Trusted Publishing path on npm — | |
| # requires a matching trusted-publisher rule on the package. | |
| - name: Publish to npm | |
| if: steps.npm_check.outputs.skip != 'true' | |
| run: pnpm publish --access public --no-git-checks --provenance | |
| # Auto-create a draft GitHub Release so we never forget one (v0.1.4 was | |
| # published to npm but the GitHub Release was missed for hours). | |
| # Draft, not published — humans polish the auto-generated notes (which | |
| # are derived from commit history) and promote when ready. Only fires | |
| # on tag pushes; workflow_dispatch reruns skip this step to avoid | |
| # "release already exists" errors on re-publishes. | |
| - name: Create draft GitHub Release | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| if gh release view "${{ github.ref_name }}" >/dev/null 2>&1; then | |
| echo "Release ${{ github.ref_name }} already exists — skipping create." | |
| else | |
| gh release create "${{ github.ref_name }}" --draft --generate-notes --title "${{ github.ref_name }}" | |
| fi |