ci(release): npm Trusted Publishing (OIDC), drop NPM_TOKEN - #86
Conversation
…M_TOKEN The publish job already grants id-token: write (used for provenance). Remove the NPM_TOKEN env from the changesets publish step so pnpm authenticates via OIDC trusted publishing instead of a long-lived token. pnpm 11.5.2 (this repo's pinned packageManager) includes the OIDC precedence fix (pnpm#11495): the OIDC-derived token overrides any static _authToken, so leaving NPM_TOKEN set would silently downgrade the publish back to legacy token auth (no trusted-publisher metadata / provenance). Dropping it forces the OIDC path. Each @chimely/* package (client, react) has a trusted publisher registered on npmjs.com for repo dodopayments/chimely + workflow release.yml. Provenance stays visibility-gated (repo is public, so on). Mirrors dodopayments/dualmark#91.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
chimely-docs | 95e4f92 | Commit Preview URL Branch Preview URL |
Aug 24 2026, 08:01 AM |
Greptile SummaryThe PR switches npm releases from a long-lived token to GitHub Actions OIDC trusted publishing.
Confidence Score: 4/5The PR appears safe to merge, with only a non-blocking request to make the new workflow comment concise and invariant-focused. The publish job has the required OIDC permission, uses a compatible pinned pnpm version, and does not configure a competing npm token; the only accepted concern is the repository’s comment-style requirement. Files Needing Attention: .github/workflows/release.yml
|
| Filename | Overview |
|---|---|
| .github/workflows/release.yml | Correctly removes legacy npm-token authentication in favor of the existing OIDC permission, with one non-blocking repository comment-style violation. |
Reviews (1): Last reviewed commit: "ci(release): switch chimely to npm Trust..." | Re-trigger Greptile
| # No NPM_TOKEN: npm Trusted Publishing (OIDC) authenticates the | ||
| # publish via the job's id-token: write. pnpm >= the #11495 fix | ||
| # (this repo pins pnpm 11.5.2) lets the OIDC-derived token override | ||
| # any static _authToken, so a token here would only downgrade the | ||
| # publish back to legacy token auth (no trusted-publisher metadata). | ||
| # Each @chimely/* package has a trusted publisher registered on | ||
| # npmjs.com for repo dodopayments/chimely + workflow release.yml. |
There was a problem hiding this comment.
Keep authentication comment invariant-focused
This block narrates and argues for the implementation rather than documenting the enduring requirement, obscuring the key constraint that NPM_TOKEN must remain unset for OIDC publishing.
| # No NPM_TOKEN: npm Trusted Publishing (OIDC) authenticates the | |
| # publish via the job's id-token: write. pnpm >= the #11495 fix | |
| # (this repo pins pnpm 11.5.2) lets the OIDC-derived token override | |
| # any static _authToken, so a token here would only downgrade the | |
| # publish back to legacy token auth (no trusted-publisher metadata). | |
| # Each @chimely/* package has a trusted publisher registered on | |
| # npmjs.com for repo dodopayments/chimely + workflow release.yml. | |
| # NPM_TOKEN must remain unset so npm Trusted Publishing uses the | |
| # job's OIDC credentials. |
Context Used: CLAUDE.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Verified the change end to end against the actual toolchain versions rather than taking the description at face value. The reasoning holds up. Approving.
What I checked
- Which client actually publishes.
@changesets/cli@2.31.0resolves the publish tool viapreferred-pm, and withpnpm-lock.yamlpresent it spawnspnpm publish, notnpm publish. So pnpm's OIDC implementation is the one that runs and Node 24's bundled npm version is irrelevant here. The premise is right. - pnpm floor. The OIDC-overrides-static-
_authTokenfix (pnpm#11495,90e215f) is first tagged in v11.0.7. The repo pinspnpm@11.5.2inpackageManager, andpnpm/action-setup@v4is used with noversioninput so it reads that field. Comfortably above the floor. - No
_authToken=undefinedpoisoning. This was my main concern, sincechangesets/actionwrites~/.npmrcitself, independently ofsetup-node. Since v1.7.0 (changesets/action#545) that write is guarded byif (process.env.NPM_TOKEN), with an explicit OIDC branch that writes nothing.@v1currently resolves to 1.9.0, so this is fine, and pnpm's override would cover it anyway. Belt and braces. - No
.npmrcplaceholder. Confirmedsetup-nodehas noregistry-urlhere, as stated. - No stale references.
NPM_TOKEN/NODE_AUTH_TOKEN/registry-urlappear nowhere else in workflows, docs, or scripts, so the secret can be deleted from repo settings without collateral damage. - Provenance gate still works. pnpm does
publishOptions.provenance ??= oidc?.provenance, so an explicitNPM_CONFIG_PROVENANCEstill wins over the OIDC-derived default. The existing visibility gate is unaffected. - No auth pre-check in the way. In CI
process.stdin.isTTYis false, so changesets skips its 2FA probe. Nothing needs a token before the publish itself. - Preconditions. Both packages already exist on the registry (0.2.2), which is required to register a trusted publisher at all.
id-token: writeis on thepublishjob only, andversioncorrectly has neither OIDC nor a publish script.
Non-blocking
- Name the concrete pnpm floor. The comment says
pnpm >= the #11495 fix, which sends a future reader to a PR number to work out what "the fix" is.pnpm >= 11.0.7is directly checkable againstpackageManager. Worth saying both. - Duplicated fact. The trusted-publisher registration (repo +
release.yml) is now stated twice, in the header prerequisites and again in the stepenv. Given the repo's "a comment must earn its place" rule, the step comment could drop its last two lines and keep only the non-obvious part, the silent-downgrade failure mode. That is the bit genuinely worth writing down. - The workflow filename is now load-bearing. The trusted publisher is bound to
release.yml, so renaming this file or moving the publish step into a reusable workflow breaks the exchange at release time with no earlier signal. Worth stating as a failure mode in the header, not only as a configuration fact. - Confirm there is no GitHub environment on the npm side. If the trusted publisher entries were registered with an environment name, this job would need a matching
environment:key. Not visible from the diff, but worth double-checking before the next release since the first symptom is a failed publish. - Stale neighbour (pre-existing, in the block this PR is already tidying): the provenance gate comment still says "chimely is private now and public-bound", but the repo is public, so that step now always evaluates to
true. Either fold the cleanup in here or leave it, but the comment is currently wrong. - Follow-up hardening. Trusted publishing scopes the credential to this workflow, not to the actions running inside it, so anything in the
publishjob can still mint a publish token. That is strictly better than a long-livedNPM_TOKEN(no secret at rest to exfiltrate, short-lived credential), but SHA-pinning the publish job's third-party actions is the natural next step. Out of scope here.
Unrelated pre-existing footgun
Noticed while reading changesets/action: the OIDC and publish path only runs in the !hasChangesets && hasPublishScript case. If any .changeset/*.md file happens to be present at the release commit, the publish job takes the version branch instead, opens a PR, and exits 0 without publishing. Not caused by this PR, but a silent no-op release is an unpleasant way to discover it.
What
Switch chimely's
changesets-driven npm publish from a long-livedNPM_TOKENto npm Trusted Publishing over GitHub Actions OIDC.Changes
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}from thePublish to npm(changesets) step. The publish job already grantsid-token: write, sopnpm changeset publishauthenticates via OIDC.Why this works with pnpm + changesets
pnpm@11.5.2(this repo's pinnedpackageManager) includes pnpm#11495, which makes the OIDC-derived token override a static_authToken— matching npm CLI precedence. LeavingNPM_TOKENset would silently downgrade the publish back to legacy token auth (notrustedPublishermetadata, no provenance), so dropping it is what forces the OIDC path.setup-nodehere does not setregistry-url, so there's no.npmrc_authTokenplaceholder to poison the exchange.Prerequisite (done)
Both packages have a trusted publisher registered on npmjs.com — repo
dodopayments/chimely, workflowrelease.yml:@chimely/client@chimely/reactProvenance is already visibility-gated in the workflow (repo is public → provenance on).
Note
This repo wasn't in the original org-wide sweep because it wires the token via changesets'
NPM_TOKENenv, notNODE_AUTH_TOKEN. Completes the org rollout (metabase excepted — its dist-tag workflow can't use OIDC).