fix(npm): migrate npm publish to OIDC trusted publishing#7607
Conversation
npm classic tokens were revoked on December 9, 2025. This migrates the npm-publish workflow to use OIDC trusted publishing which eliminates the need for long-lived tokens. Changes: - Add id-token: write permission for OIDC - Remove NODE_AUTH_TOKEN secret requirement - Add --provenance flag to npm publish for attestation - Remove || true error swallowing so failures are reported - Add version input to workflow_dispatch for testing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR migrates the npm publishing workflow from classic token authentication to OIDC trusted publishing, eliminating the need for stored secrets and adding provenance attestation for better supply chain security.
Key changes:
- Removes classic token authentication and replaces it with OIDC permissions
- Adds
--provenanceflag to npm publish commands for attestation - Removes error-swallowing
|| truesuffixes to properly surface publish failures - Adds
versioninput parameter to workflow for manual testing
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| scripts/release-npm.sh | Removes NODE_AUTH_TOKEN validation, adds --provenance flag, removes error swallowing, fixes DRY_RUN variable handling |
| .github/workflows/npm-publish.yml | Adds OIDC permissions, removes NODE_AUTH_TOKEN secret, adds version input, simplifies DRY_RUN logic |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| env: | ||
| DRY_RUN: ${{ github.event_name == 'release' && '0' || (github.event_name == 'workflow_dispatch' && (github.event.inputs.dry_run && '1' || '0')) || '1' }} | ||
| DRY_RUN: ${{ github.event_name == 'release' && '0' || (inputs.dry_run && '1' || '0') }} |
There was a problem hiding this comment.
The DRY_RUN logic has a bug: when inputs.dry_run is false (not just absent), the expression evaluates to '0' || '0' which results in '0', meaning dry run will be disabled. The correct logic should check if inputs.dry_run equals the string 'true': inputs.dry_run == 'true' && '1' || '0'.
| DRY_RUN: ${{ github.event_name == 'release' && '0' || (inputs.dry_run && '1' || '0') }} | |
| DRY_RUN: ${{ github.event_name == 'release' && '0' || (inputs.dry_run == 'true' && '1' || '0') }} |
Prevents accidental publishing if script is run manually without DRY_RUN being set. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Musl variants were trying to publish to the same package names as glibc variants, causing failures. Since musl packages never existed on npm, just remove them from the list. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Allows the script to skip versions that were already published (useful for retries) while still failing on actual errors. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.1.1 x -- echo |
19.9 ± 0.4 | 19.1 | 22.9 | 1.00 |
mise x -- echo |
20.4 ± 0.5 | 19.7 | 25.0 | 1.03 ± 0.03 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.1.1 env |
19.5 ± 0.6 | 18.6 | 23.9 | 1.00 |
mise env |
19.9 ± 0.4 | 18.9 | 22.0 | 1.02 ± 0.04 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.1.1 hook-env |
19.8 ± 0.4 | 19.0 | 21.5 | 1.00 |
mise hook-env |
20.6 ± 0.6 | 19.2 | 23.3 | 1.04 ± 0.04 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.1.1 ls |
17.7 ± 0.3 | 17.0 | 19.1 | 1.00 |
mise ls |
18.3 ± 0.5 | 17.3 | 21.0 | 1.03 ± 0.03 |
xtasks/test/perf
| Command | mise-2026.1.1 | mise | Variance |
|---|---|---|---|
| install (cached) | 111ms | 113ms | -1% |
| ls (cached) | 69ms | 69ms | +0% |
| bin-paths (cached) | 73ms | 73ms | +0% |
| task-ls (cached) | 282ms | 283ms | +0% |
### 🐛 Bug Fixes - **(backend)** filter pre-release versions with latest + install_before by @koh-sh in [#7631](#7631) - **(docs)** formatting in configuration hierarchy section by @jonathanagustin in [#7638](#7638) - **(npm)** migrate npm publish to OIDC trusted publishing by @jdx in [#7607](#7607) - **(registry)** correct checkmake version test pattern by @jdx in [#7632](#7632) - **(release)** handle empty grep result in aqua-registry changelog by @jdx in [f45b4c6](f45b4c6) - **(self-update)** self-update fails across year boundary due to semver mismatch by @jdx in [#7611](#7611) - **(tasks)** fix tool inheritance from intermediate parents by @chadxz in [#7637](#7637) - add `-test` to VERSION_REGEX prerelease filter by @belgio99 in [#7647](#7647) ### 📚 Documentation - **(tasks)** remove documentation for unimplemented features by @turbocrime in [#7599](#7599) - update `mise aliases` references to `mise tool-alias` by @muzimuzhi in [#7615](#7615) - use call operator in PowerShell profile example by @shina1024 in [#7639](#7639) - replace ASCII .pub key with binary .gpg for signed-by on Ubuntu/Debian by @gmalinowski in [#7649](#7649) ### 🛡️ Security - **(security)** prevent code execution from untrusted fork in registry-comment workflow by @jdx in [4a2441e](4a2441e) ###◀️ Revert - Revert "fix(release): handle empty grep result in aqua-registry changelog" by @jdx in [522ffdc](522ffdc) - Revert "chore(release): include manually updated aqua-registry entries in the changelog " by @jdx in [1ebb943](1ebb943) ### 📦️ Dependency Updates - update ghcr.io/jdx/mise:alpine docker digest to fbfffcf by @renovate[bot] in [#7619](#7619) - lock file maintenance by @renovate[bot] in [#7646](#7646) ### 📦 Registry - add hatoo/oha tool by @jylenhof in [#7633](#7633) ### Chore - **(registry)** fix registry comment workflow by @risu729 in [#7554](#7554) - **(release)** include manually updated aqua-registry entries in the changelog by @risu729 in [#7603](#7603) ### New Contributors - @belgio99 made their first contribution in [#7647](#7647) - @gmalinowski made their first contribution in [#7649](#7649) - @chadxz made their first contribution in [#7637](#7637) - @shina1024 made their first contribution in [#7639](#7639) - @jonathanagustin made their first contribution in [#7638](#7638) - @turbocrime made their first contribution in [#7599](#7599) ## 📦 Aqua Registry Updates #### New Packages (3) - [`ampcode/zvelte-check`](https://github.com/ampcode/zvelte-check) - [`nickel-lang/nickel`](https://github.com/nickel-lang/nickel) - [`openshift/rosa`](https://github.com/openshift/rosa)
Summary
|| trueerror swallowing so publish failures are reported--provenanceflag for attestationversioninput to workflow_dispatch for testing specific releasesRequired Setup
Before merging, trusted publishers must be configured on npmjs.com for:
@jdxcode/mise@jdxcode/mise-linux-x64@jdxcode/mise-linux-arm64@jdxcode/mise-linux-armv7@jdxcode/mise-macos-x64@jdxcode/mise-macos-arm64For each package: Settings → Trusted Publishers → Add
jdx/miserepo with workflownpm-publish.ymlTest plan
dry_run: falseandversion: v2026.1.1🤖 Generated with Claude Code
Note
Migrates npm publish to OIDC trusted publishing with improved controls and safety.
id-tokenand removingNODE_AUTH_TOKENusage;--provenanceadded tonpm publishinputs.versiontoworkflow_dispatchand uses it for artifact download andMISE_VERSIONDRY_RUNhandling in workflow and script (default-safe) and logs intended commands|| true, captures publish output, and skips when version already existsreleases/<version>and copy toreleases/for compatibilitylinux-*-muslvariants)Written by Cursor Bugbot for commit 1c8ed6a. This will update automatically on new commits. Configure here.