Skip to content

ci: use github oidc for npm publishing - #231

Merged
evenstensberg merged 1 commit into
mainfrom
oicd
Oct 13, 2026
Merged

evenstensberg merged 1 commit into
mainfrom
oicd

Conversation

@evenstensberg

@evenstensberg evenstensberg commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Summary

The release workflow declared id-token: write with a comment saying "Required for OIDC", but nothing in it actually published through OIDC, so the permission and the npm PATH shim added in #226 were both unreachable. This wires up npm trusted publishing properly.

Two things were blocking a publish entirely:

  • No publish input on changesets/action. The action computes hasPublishScript = !!core.getInput("publish"), so with it unset every push to main landed in the !hasChangesets && !hasPublishScript branch and logged "Not publishing because no publish script found." The release PR could be opened and merged, but nothing was ever published. Passing publish: npx changeset publish is also what lets the .github/shims/npm rewrite fire, since @changesets/cli spawns npm publish <dir> internally.
  • "access": "restricted" in .changeset/config.json (the changeset init default) is forwarded verbatim as npm publish --access restricted. coffee-loader is unscoped and public, so that is the wrong value; set to public.

The rest makes the OIDC exchange itself work:

  • registry-url on setup-node, so npm can derive the audience — it requests the ID token with audience=npm:<registry hostname>.
  • An explicit npm install -g npm@latest. The token exchange needs npm >= 11.5.1 and npm stage publish needs >= 11.7.0. lts/* currently resolves to Node 24.21 (npm 11.19.0) so this happens to work today, but Node 22 ships npm 10.9.9, which has no OIDC support at all — if lts/* ever moves, the release breaks for a non-obvious reason.
  • permissions moved from the workflow to the job, with permissions: {} at the top. id-token: write mints publish tokens, so it shouldn't be granted file-wide by default to any job added later.
  • environment: npm, to be matched by the environment on the trusted publisher.

No NPM_TOKEN is involved anywhere; changesets/action v1.9.0 detects ACTIONS_ID_TOKEN_REQUEST_{URL,TOKEN} and skips its .npmrc token generation, and npm auto-enables provenance for trusted-publishing claims so no --provenance flag is needed.

Before merging, the trusted publisher has to exist on npm for coffee-loader, with repository webpack/coffee-loader, workflow filename release.yml and environment npm. The claim must match exactly — if the environment field is left blank there while the job declares one, the exchange is rejected. Note the publisher is keyed on the workflow filename, so renaming release.yml later breaks publishing.

What kind of change does this PR introduce?

ci — plus a one-value config fix in .changeset/config.json.

Did you add tests for your changes?

No. This is release pipeline configuration; there is nothing the Jest suite can exercise. prettier, cspell and commitlint pass, and the YAML parses. The OIDC exchange can only really be verified by the first publish after the trusted publisher is configured on the npm side.

Does this PR introduce a breaking change?

No. Nothing in the published package changes — files is dist only, and neither modified file is shipped. No changeset is included for that reason.

If relevant, what needs to be documented once your changes are merged or what have you already documented?

Nothing user-facing. The non-obvious constraints are in comments in the workflow itself: why npm is upgraded, and that environment: npm has to match the trusted publisher. Worth knowing for maintainers: releases no longer depend on an npm token, and the npm-side trusted publisher config is now part of the release path.

Use of AI

Claude Code (Opus 5) was used for this change. It read @changesets/cli, changesets/action and the npm CLI sources to establish the specifics cited above — that the action silently skips publishing without a publish input, that npm stage publish extends Publish and so inherits the OIDC path, and which npm versions ship with each Node LTS line — then drafted the workflow edits. I reviewed the diff and the reasoning behind each change before submitting, and can answer questions about any of it in review.


🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Updated package release settings to support public publishing.
    • Adjusted the release workflow’s permissions and publishing setup. No changes to the product’s user-facing features are included.

Switch the release workflow to npm trusted publishing instead of relying on
an ambient npm credential:

- set registry-url so npm can derive the OIDC audience
- update npm, since the exchange needs >= 11.5.1 and 'npm stage publish'
  needs >= 11.7.0, newer than the npm bundled with some Node LTS lines
- move permissions to the job so id-token: write is not granted file-wide
- declare the npm environment, to be matched on the trusted publisher
- pass a publish script, without which the action never published at all

Also set changesets access to public: it is forwarded as
'npm publish --access restricted', which does not apply to an unscoped
public package.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (18afb21) to head (97a35cc).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #231   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            3         3           
  Lines           18        18           
  Branches         2         2           
=========================================
  Hits            18        18           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@evenstensberg

Copy link
Copy Markdown
Member Author

Important

One thing to settle before merge, which I called out in the PR body: the trusted publisher has to be created on npm for coffee-loader with repository webpack/coffee-loader, workflow release.yml, environment npm. Until that exists the exchange has nothing to match against.

@evenstensberg

Copy link
Copy Markdown
Member Author

I've enabled OIDC at npm, we just need to merge and test ourselves.

@coderabbitai

coderabbitai Bot commented Oct 13, 2026

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 61e8fb3c-076c-48e8-ae92-59b3d953e704
📥 Commits

Reviewing files that changed from the base of the PR and between 18afb21 and 97a35cc.

📒 Files selected for processing: 2
  • .changeset/config.json
  • .github/workflows/release.yml

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

Walkthrough

Changesets package access changes from restricted to public. The release workflow sets workflow-level permissions to empty and grants the release job id-token, contents, and pull-requests write permissions in the npm environment. It configures the npm registry, upgrades npm globally, and runs npx changeset publish. Workflow comments identify npm trusted publishing as the authentication method and state that no NPM_TOKEN is supplied.

Priority: ➖ Normal

Merge Risk: 🟡 Moderate · up to 97a35

Publishing now relies on npm’s trusted-publisher configuration. Confirm it matches the repository, workflow, and environment before merging; otherwise a release may fail to publish.

Pre-merge checks: Passed 5
Passed Passed checks: 5 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the primary change: using GitHub OIDC for npm publishing.
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread .changeset/config.json
"fixed": [],
"linked": [],
"access": "restricted",
"access": "public",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't have any effects on security because we have scoped access on npm which can't be overridden.

@evenstensberg
evenstensberg merged commit 7965995 into main Oct 13, 2026
19 checks passed
@evenstensberg
evenstensberg deleted the oicd branch October 13, 2026 20:30
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