ci(release): split publish into three steps to force trusted publishing#11496
Merged
Conversation
The previous "Publish Packages" step ran `pn release` after writing NPM_TOKEN into pnpm's config. With a static `_authToken` configured, `pnpm publish` bails out of OIDC entirely (see #11495 for the longer- term fix), so every package — including `pnpm` and `@pnpm/exe` — was silently being published with the legacy token instead of using npm's trusted publishing. The result: published metadata showed `_npmUser: pnpmuser` and no provenance attestation. Until #11495 ships, work around the precedence bug by structuring the job so the packages we *want* trusted publishing for never see a static token at all: 1. `@pnpm/exe` — published in a step with no NPM_TOKEN. pnpm has no token to short-circuit on, performs OIDC, gets a `trustedPublisher` entry on npm. 2. Internal workspace packages — these don't have trusted publishing configured on npm, so they still need the static token. The token is written, the publish runs, then `pn config delete` removes the token before the next step. 3. `pnpm` — published in a step with no NPM_TOKEN, same rationale as step 1. CI-only change; no changeset needed.
|
Caution Review failedFailed to post review comments 📝 WalkthroughWalkthroughThe release workflow now publishes three distinct packages in separate steps using either trusted publishing or static tokens, replacing the previous combined publish step with added explanatory comments clarifying the authentication strategy. ChangesRelease Workflow Publishing
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
zkochan
added a commit
that referenced
this pull request
May 6, 2026
…ng (#11496) The previous "Publish Packages" step ran `pn release` after writing NPM_TOKEN into pnpm's config. With a static `_authToken` configured, `pnpm publish` bails out of OIDC entirely (see #11495 for the longer- term fix), so every package — including `pnpm` and `@pnpm/exe` — was silently being published with the legacy token instead of using npm's trusted publishing. The result: published metadata showed `_npmUser: pnpmuser` and no provenance attestation. Until #11495 ships, work around the precedence bug by structuring the job so the packages we *want* trusted publishing for never see a static token at all: 1. `@pnpm/exe` — published in a step with no NPM_TOKEN. pnpm has no token to short-circuit on, performs OIDC, gets a `trustedPublisher` entry on npm. 2. Internal workspace packages — these don't have trusted publishing configured on npm, so they still need the static token. The token is written, the publish runs, then `pn config delete` removes the token before the next step. 3. `pnpm` — published in a step with no NPM_TOKEN, same rationale as step 1. CI-only change; no changeset needed.
3 tasks
2 tasks
This was referenced Jun 23, 2026
2 tasks
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.
Summary
Splits the single
Publish Packagesstep inrelease.ymlinto three sequential publish steps, isolating the packages we want to ship via npm's trusted publishing (pnpmand@pnpm/exe) into steps that don't haveNPM_TOKENset.Why
pnpm publishcurrently bails out of OIDC as soon as a static_authTokenis configured (see #11495 for the longer-term fix). Our release workflow writesNPM_TOKENinto pnpm's config beforepn release, so OIDC is never attempted — even for packages where npm's trusted-publishing config would issue a token. The result is visible in the registry metadata for recent releases:pnpm@11.0.6shows_npmUser: pnpmuserand noattestations.provenance, while the manually-publishedpnpm@11.0.0-alpha.5shows_npmUser.trustedPublisherand a SLSA provenance block.#11495 will fix the precedence rule properly, but until then we need a way to ship
pnpmand@pnpm/exevia trusted publishing on the next release. The workaround: don't put a static token in their environment at all.Changes
.github/workflows/release.yml— replace thePublish Packagesstep with three:Publish @pnpm/exe (trusted publishing)— noNPM_TOKEN. Builds the exe artifacts and publishes@pnpm/exe. With no token configured,pnpm publishreaches its OIDC code path and exchanges the GitHub Actions ID token at npm's trusted-publishing endpoint.Publish internal workspace packages (static token)—NPM_TOKENis set, written into pnpm config, the publish runs, thenpn config deleteremoves the token. The workspace's internal packages don't have trusted publishing configured on npm yet, so they still need the static token.Publish pnpm CLI (trusted publishing)— noNPM_TOKEN. Same rationale as step 1. Must come after step 2 because step 2'spn config deleteis what guarantees pnpm doesn't see a stale_authTokenhere.pn releasescript in rootpackage.jsonis left in place — unused after this change but harmless. Removing it is a separable cleanup.Caveats
pnpmand@pnpm/exe(mapped to this repo + thereleaseGitHub environment + this workflow file name). If either isn't set up, that step's OIDC exchange will return a 4xx and the publish will fail. Worth verifying before tagging the next release.pn config deleteruns after the publish; if the publish itself fails the delete won't run, but the step then fails and the workflow stops, so the stale token can't leak.Test plan
pnpmand@pnpm/exe._npmUser.trustedPublisherand anattestations.provenanceblock for bothpnpmand@pnpm/exe. The internal workspace packages should continue to show_npmUser: pnpmuser(no change there until they're onboarded to trusted publishing too).Written by an agent (Claude Code, claude-opus-4-7).
Summary by CodeRabbit