ci: prepare release workflow for npm trusted publishing - #136
Merged
Conversation
Part of #134. This is the repo-side half; the trusted publisher still has to be configured at npmjs.com before it takes effect. Adds an explicit npm CLI upgrade to the release job. Trusted publishing needs npm >= 11.5.1 and Node 22 bundles npm 10.9.8, so without this the publish fails even once OIDC is configured — and it fails in a non-obvious way. @semantic-release/npm 13.1.5 treats a successful OIDC exchange as proof that authentication is handled and returns early from verifyAuth: if (await oidcContextEstablished(registry, pkg, context)) { return; // no token written } await setNpmrcAuth(npmrc, registry, context); await verifyTokenAuth(registry, npmrc, context, pkgRoot); The exchanged token is only used as a boolean probe — it is never forwarded. publish.js then runs `npm publish --userconfig <npmrc>` against an npmrc with no credentials in it, so the npm CLI has to perform its own OIDC exchange. An npm that cannot do that arrives with nothing. NPM_TOKEN is deliberately left in place. The plugin falls back to it when the exchange fails, so it stays as the rollback until a real publish has succeeded over OIDC. Also corrects CLAUDE.md, which described NPM_TOKEN as the required secret "with publish + provenance rights". Provenance was never actually enabled — nothing passes --provenance, there is no publishConfig, and deride@2.2.0 has no attestations. Trusted publishing generates it automatically, so this delivers what that line claimed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #134. This is the repo-side half only — the trusted publisher must be configured at npmjs.com before it takes effect, which needs a login + 2FA and so can't be done from here. Steps below.
Staged publishing vs trusted publishing
Worth naming the distinction, since the two get conflated:
npm stage publish, then a maintainer approves with 2FA before it goes live. It complements trusted publishing and explicitly does not remove the need for a token. It also converts semantic-release from fully automated to human-gated on every release.So staged publishing is a reasonable thing to want, but it's a separate decision and it wouldn't fix the failing release.
What this PR changes
One step, plus a comment explaining why it can't be removed:
Trusted publishing requires npm CLI >= 11.5.1. The release job runs Node 22, which bundles npm 10.9.8 (confirmed against
nodejs.org/dist/index.json). Without this step the publish fails after OIDC is configured, in a way that's hard to diagnose.The reason is specific to how
@semantic-release/npm@13.1.5works.lib/verify-auth.js:The exchanged token is used only as a boolean probe —
oidcContextEstablishedreturns!!tokenand discards it.lib/publish.jsthen runsnpm publish --userconfig <npmrc>against an npmrc containing no credentials, so the npm CLI must perform its own OIDC exchange. An npm that can't do that arrives with nothing at all.id-token: writewas already granted, so no permissions change is needed.What you need to do at npmjs.com
npmjs.com → deride → Settings → Trusted Publisher → GitHub Actions:
guzzlerioderiderelease.ymlnpm publishderidealready exists on the registry (2.2.0 islatest), so the "package must already exist" precondition is met.release.ymllater breaks publishing with a 404 on the exchange. Noted in CLAUDE.md.Suggested rollout
Merging this PR is itself a safe live test.
semantic-releaserunsverifyConditionsbefore analysing commits, so the Release workflow exercises the OIDC exchange on every push tomain— but this is aci:commit, so nothing is releasable and nothing publishes.OIDC token exchange with the npm registry succeeded. No publish happens.NPM_TOKENsecret.NPM_TOKENis deliberately left in place in this PR — the plugin falls back to it when the exchange fails, so it's the rollback until a real publish has gone through. It's currently invalid, so the fallback is a dead end, but removing it now would only change one failure mode for another.Note that until step 1 is done, every push to
mainproduces a red Release run. That's pre-existing (#134), not introduced here.Bonus: provenance
CLAUDE.md described
NPM_TOKENas needing "publish + provenance rights", and the workflow commentedid-token: write # npm provenance. Provenance was never actually enabled — nothing passes--provenance, there's nopublishConfig, andderide@2.2.0has no attestations. Trusted publishing generates provenance automatically for GitHub Actions, so this finally delivers what that line claimed. CLAUDE.md corrected.🤖 Generated with Claude Code