chore(ci): publish nodeup-cli to npm via OIDC Trusted Publishing#39
Merged
Conversation
Wires the npm wrapper into the release workflow. After GoReleaser
finishes, a second job runs `npm publish --access public` from
nodeup-npm/ using OIDC Trusted Publishing - no NPM_TOKEN secret,
no rotation, no leak surface. The trust is registered on the
npmjs.com side under "Trusted Publisher", pointing at this
workflow by filename.
Three things had to be right for the OIDC exchange to fire:
1. `permissions: id-token: write` on the publish job. Without it,
the runner won't mint an OIDC token.
2. No `registry-url` on setup-node. With it, setup-node writes
`//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}` to .npmrc,
and an empty-expanded value still counts as "auth configured" -
npm then tries classic auth with empty creds and never
initiates the OIDC exchange (npm/documentation#1960).
3. A clean .npmrc with only the registry URL. Without it, npm
doesn't see the ACTIONS_ID_TOKEN_REQUEST_* env vars and skips
the exchange.
Node 24 is pinned because OIDC trusted publishing needs
npm >= 11.5.1 / Node >= 22.14.0.
Also updates the file's header comment to reflect the new step
and document the npmjs.com trust entry as the first thing to
check if the publish job ever fails with ENEEDAUTH.
Refs #35.
Co-Authored-By: Sonnet 4.6 <noreply@puku.sh>
|
✔️ f20e3f8 - Conventional commits check succeeded. |
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
Wires the npm wrapper into the release workflow via OIDC Trusted
Publishing. After GoReleaser finishes, a second job runs
npm publish --access publicfromnodeup-npm/using the OIDCtoken that the GitHub Actions runner mints automatically. No
NPM_TOKENsecret, no rotation, no leak surface.The trust is already registered on the npmjs.com side under
"Trusted Publisher" — the screenshot you sent shows
dipto0321/nodeup+release.yml+npm publishpermission.This PR wires up the workflow half of that trust.
Why this needed three subtle things to be right
OIDC trusted publishing only fires when npm CLI sees no
_authTokenline in.npmrcfor the target registry. Theactions/setup-node@v4action writes//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}to.npmrcwhen given
registry-url: 'https://registry.npmjs.org', and anempty-expanded value still counts as "auth configured" — npm then
tries classic auth with empty creds and never initiates the OIDC
exchange. (Tracked upstream at
npm/documentation#1960.)
So the publish job has to:
permissions: id-token: writeso the runner mints anOIDC token.
registry-urltosetup-node— otherwise itwrites the
_authTokenline..npmrcwith only the registry URL — guaranteesno
_authTokenline is present even if some future change tothe setup-node action introduces one.
Node 24 is pinned because OIDC trusted publishing requires
npm ≥ 11.5.1andNode ≥ 22.14.0.Linked issues
Refs #35 (tracking issue for the npm-publish step)
Type of change
feat— new feature (MINOR bump)fix— bug fix (PATCH bump)refactor— no behavior changedocs— documentation onlychore— CI/CDci— CI/CD onlybuild— build system onlyChecklist
chore(ci): subject)python3 -c "import yaml; yaml.safe_load(open('.github/workflows/release.yml'))")make cilocally — workflow-only change, Go code untouchedrelease.ymlexplains the trust entry and the troubleshooting pointer)
Scope notes / things reviewers may want to look at
you push a
v0.0.0-testtag (notv1.0.0). The trust entry onnpmjs.com already matches this workflow's filename, so the OIDC
exchange should work. If it doesn't, the first thing to check
is that:
dipto0321/nodeup+release.yml.id-token: write.NODE_AUTH_TOKENorNPM_TOKENenv var is set in theworkflow that would land in
.npmrc.NPM_TOKENsecret is required. This is the whole pointof the OIDC change — once the workflow is merged, you can
delete any
NPM_TOKENrepo/org secret you might have set upduring the planning phase. None was ever created in this repo,
so nothing to clean up.
publishing generates provenance automatically for public
packages from public repos. The
npm publishcommand doesnot include
--provenancefor that reason — adding itmanually would try to mint a second OIDC token and fail.
concurrency: { group: release-${{ github.ref }}, cancel-in-progress: false }applies to the whole workflow, so the publish job inherits the
no-cancel guarantee. A partially-published release is the bad
case we're protecting against.
How to verify
After merge, push a test tag and watch the
publish-npmjob inthe action run. On success the new version appears at
https://www.npmjs.com/package/nodeup-cli?activeTab=versions.