Skip to content

Switch release workflow to npm trusted publishing (OIDC)#185

Merged
RPate97 merged 1 commit into
mainfrom
fix/release-oidc-trusted-publishing
Jul 5, 2026
Merged

Switch release workflow to npm trusted publishing (OIDC)#185
RPate97 merged 1 commit into
mainfrom
fix/release-oidc-trusted-publishing

Conversation

@RPate97

@RPate97 RPate97 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Problem

The Release packages (prod) workflow has been failing on every push to main since 2026-06-06. All runs die on the Publish to NPM step with:

npm error code E404
npm error 404 Not Found - PUT https://registry.npmjs.org/token.js - Not found
npm error 404  'token.js@0.8.1' is not in this registry.

This is npm's response to an invalid/expired publish credential (it returns 404 rather than 401/403 so it doesn't leak package existence to unauthorized callers). The package itself is fine — latest published is 0.7.1, and 0.8.1 in package.json has never made it to the registry, so every subsequent push retries the same stuck publish and fails identically.

Root cause: the repo's NPM_TOKEN secret was last rotated 2024-07-11 and has since expired.

Fix

Rather than mint and store yet another long-lived token, switch to npm trusted publishing (OIDC) — the approach npm now recommends for CI. GitHub mints a short-lived, workflow-scoped OIDC token that npm exchanges for a one-time publish credential. There's no stored secret to expire, leak, or rotate, and npm auto-generates provenance attestations.

Changes to .github/workflows/release.yml:

  • Add permissions: id-token: write so the runner can mint the OIDC token (kept contents/pull-requests: write for changesets git tags + GitHub releases, since adding an explicit permissions block otherwise drops the default grants).
  • Bump Node 20 → 22 — OIDC requires Node ≥ 22.14.0. Bonus: clears the Node 20 runner-deprecation warning currently on every run.
  • Upgrade the runner's global npm (npm install -g npm@latest) — OIDC requires npm ≥ 11.5.1, and older npm silently falls back to token auth. pnpm changeset publish shells out to npm under the hood, so the global npm version is what matters.
  • Drop the NPM_TOKEN env var.

pnpm changeset publish is unchanged — changesets uses npm's native publish path, so it picks up OIDC automatically without needing pnpm's own (still-in-progress) OIDC support.

⚠️ Required before this can publish

  1. Register the trusted publisher on npmjs.com (package → Settings → Trusted Publisher): org/user token-js, repository token.js, workflow release.yml. The first OIDC publish will 404 until this exists.
  2. Manually publish 0.8.1 once to clear the currently-stuck version.
  3. After a green run, the NPM_TOKEN secret can be deleted.

🤖 Generated with Claude Code

The NPM_TOKEN secret expired (last rotated 2024-07-11), causing every
release since v0.8.1 to fail with `npm error 404 ... PUT
.../token.js - Not found` — npm's response to a bad publish credential.

Switch to OIDC-based trusted publishing so there's no long-lived token
to expire, leak, or rotate:

- Add `id-token: write` permission so the runner can mint the OIDC token
  npm exchanges for a short-lived publish credential (contents/
  pull-requests kept for changesets tags + GitHub releases).
- Bump Node 20 -> 22 (OIDC needs Node >= 22.14.0; also clears the
  Node 20 runner-deprecation warning).
- Upgrade the runner's global npm, which `changeset publish` shells out
  to, since OIDC requires npm >= 11.5.1.
- Drop the NPM_TOKEN env var.

Requires registering the trusted publisher on npmjs.com (repo
token-js/token.js, workflow release.yml) before the first OIDC publish.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@RPate97
RPate97 merged commit e020af4 into main Jul 5, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant