diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index dc427a8..632ae55 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -65,30 +65,38 @@ jobs: - name: Install dependencies run: npm ci - # Skip when this exact version is already on npm. `npm publish` over an + # Skip when this commit did not bump the version. `npm publish` over an # existing version is a hard E403, which turned every unbumped merge — # Dependabot's, and CI-only PRs now that the bump gate exempts them — - # into a red publish run (run 33714086138, 2026-09-02). The package is - # `access: restricted`, so the lookup needs the read-only NPM_TOKEN; - # the publish itself stays on OIDC trusted publishing. - - name: Check if version already published + # into a red publish run (runs 33714086138 and 33715159834, 2026-09-02). + # Compared against HEAD^ in git rather than looked up on npm: the + # package is `access: restricted`, and this repo has no NPM_TOKEN, so an + # unauthenticated `npm view` reports 404 for every version — which is + # exactly what the first attempt at this guard did (#20). Same rule the + # private libraries apply via verify-version-bump's push-side output. + # The checkout above is fetch-depth 2 for this comparison. A manual + # dispatch always attempts the publish (that is what it is for). + - name: Check if this commit bumped the version id: check shell: bash env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + DISPATCHED: ${{ github.event_name == 'workflow_dispatch' }} run: | set -euo pipefail - NAME=$(node -p "require('./package.json').name") - VERSION=$(node -p "require('./package.json').version") - if npm view "${NAME}@${VERSION}" version >/dev/null 2>&1; then - echo "published=true" >> "$GITHUB_OUTPUT" - echo "::notice::${NAME}@${VERSION} already on npm — no version bump on this commit, skipping publish." + read_version() { + node -p "(() => { const s = require('fs').readFileSync(0, 'utf8'); try { return JSON.parse(s).version || '' } catch { return '' } })()" + } + CUR=$(node -p "require('./package.json').version") + PREV=$(git show HEAD^:package.json 2>/dev/null | read_version || true) + if [ "$DISPATCHED" != "true" ] && [ "$CUR" = "$PREV" ]; then + echo "bumped=false" >> "$GITHUB_OUTPUT" + echo "::notice::version unchanged ($CUR) against HEAD^ — nothing to publish." else - echo "published=false" >> "$GITHUB_OUTPUT" - echo "${NAME}@${VERSION} not yet published — will publish." + echo "bumped=true" >> "$GITHUB_OUTPUT" + echo "Version ${PREV:-} -> $CUR; publishing." fi # No build step: this package ships index.js / index.d.ts directly. - name: Publish to npm - if: steps.check.outputs.published != 'true' + if: steps.check.outputs.bumped == 'true' run: npm publish