Skip to content

fix(CI): upgrade @semantic-release/npm to 13.x for OIDC trusted publishing#148

Merged
emmclaughlin merged 2 commits intomainfrom
cursor/fix-oidc-trusted-publishing-1cce
Apr 30, 2026
Merged

fix(CI): upgrade @semantic-release/npm to 13.x for OIDC trusted publishing#148
emmclaughlin merged 2 commits intomainfrom
cursor/fix-oidc-trusted-publishing-1cce

Conversation

@emmclaughlin
Copy link
Copy Markdown
Collaborator

@emmclaughlin emmclaughlin commented Apr 30, 2026

Summary

Upgrade @semantic-release/npm from the v12 line (transitively pinned by semantic-release@24) to ^13.1.5, and @semantic-release/github to ^12.0.6. Both are added as direct devDependencies and pinned via yarn resolutions so the copies nested inside semantic-release get overridden too. Bump CI/CD workflows to Node 22 to match the new engine requirement.

Why This Change Is Needed

The NPM Trusted Publisher for @faire/mjml-react is configured correctly (Faire/mjml-react, workflow filename CD_release_npm.yml, no environment), and the workflow already has id-token: write and an npm CLI new enough to do the OIDC handshake. Despite all of that, every release run still fails with:

[@semantic-release/npm] › ℹ  Verify authentication for registry https://registry.npmjs.org/
[semantic-release] › ✘  Failed step "verifyConditions" of plugin "@semantic-release/npm"
ENONPMTOKEN No npm token specified.

(see run 22227142052)

The reason is that OIDC trusted-publishing support — the bit that performs the GitHub OIDC → npm token exchange and skips the NPM_TOKEN requirement — was only added to @semantic-release/npm in v13.1.0. semantic-release@24 declares @semantic-release/npm: ^12.0.2, so yarn was installing v12.0.2 nested under node_modules/semantic-release/, and that's the copy actually loaded at release time. v12 doesn't know about OIDC, so it falls straight through to the legacy set-npmrc-auth.js path that requires NPM_TOKEN.

Just adding v13 as a top-level devDependency isn't enough because the nested v12 inside semantic-release@24 still wins. Yarn resolutions are required to dedupe to a single v13.1.5 copy, which is what semantic-release will then load. After this change, find node_modules -path '*@semantic-release/npm/package.json' returns only 13.1.5 (no nested v12 left).

@semantic-release/github is bumped to ^12.0.6 while we're here. The previous (v11.x) version was also throwing Variable $owner of type String! was provided invalid value from its GraphQL "fail" reporter when a publish failed, which obscured the underlying error in the action logs. v12.x fixes that.

Node 22 bump

@semantic-release/npm@13.x and @semantic-release/github@12.x both declare engines.node: ^22.14.0 || >= 24.10.0. The first PR push failed CI with error @semantic-release/npm@13.1.5: The engine "node" is incompatible with this module. Got "20.20.2". Two corresponding workflow updates:

  • .github/workflows/CD_release_npm.yml: bump from Node 20.17.0 to Node 22 so semantic-release can install and run.
  • .github/workflows/CI_PR_merge_checks.yml: drop 20.x from the matrix and keep 22.x only.

The runtime package itself has no engines field and its peer deps still allow React 16+, so consumers' Node version requirements are unchanged. Only the dev/CI tooling now requires Node 22+.

Verification

  • yarn install produces a single resolved version of each plugin (@semantic-release/npm@13.1.5, @semantic-release/github@12.0.6); no nested duplicates remain.
  • yarn build-dist, yarn test, yarn lint, and yarn prettier --check . all pass on Node 22 locally.
  • End-to-end OIDC behavior can only be confirmed once this lands on main and a conventional-commit fix:/feat: push triggers semantic-release. Expected log line on success: [@semantic-release/npm] › ℹ Publishing with provenance.

Related

Open in Web Open in Cursor 

…shing

@semantic-release/npm only learned how to perform the OIDC token
exchange with the npm registry in v13.1.0. semantic-release@24 still
pins it to ^12.0.2, which falls back to looking for an NPM_TOKEN even
when a Trusted Publisher is configured on npm and the workflow grants
id-token: write. That is why the publish step keeps failing with
ENONPMTOKEN despite the trusted publisher being set up correctly.

- Add @semantic-release/npm@^13.1.5 and @semantic-release/github@^12.0.6
  as direct devDependencies.
- Pin both via yarn 'resolutions' so the copies nested inside
  semantic-release@24 are also overridden (otherwise the v12 copy is the
  one actually loaded at release time).
- @semantic-release/github bump also picks up the fix for the
  'Variable $owner of type String!' GraphQL error from the failure
  reporter that was masking publish errors in run logs.
@emmclaughlin emmclaughlin marked this pull request as ready for review April 30, 2026 13:08
@semantic-release/npm@13.x and @semantic-release/github@12.x both
declare engines.node ^22.14.0 || >= 24.10.0, so 'yarn install' fails
on Node 20 with 'incompatible with this module'. Drop Node 20 from the
PR matrix and bump the release workflow to Node 22.

The runtime package itself has no engines field and its peer deps still
allow React 16+, so consumers are unaffected; only the dev/CI tooling
now requires Node 22+.
@emmclaughlin emmclaughlin merged commit 44a28ea into main Apr 30, 2026
2 checks passed
@emmclaughlin emmclaughlin deleted the cursor/fix-oidc-trusted-publishing-1cce branch April 30, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants