Skip to content

ci: publish through npm OIDC trusted publishing - #10

Merged
owjs3901 merged 1 commit into
mainfrom
owjs3901/npm-oidc-trusted-publishing
Sep 10, 2026
Merged

owjs3901 merged 1 commit into
mainfrom
owjs3901/npm-oidc-trusted-publishing

Conversation

@owjs3901

Copy link
Copy Markdown
Contributor

Problem

Run 34445643571 failed on publish:

404 Not Found: https://registry.npmjs.org/bun-test-env-dom
 - 'bun-test-env-dom@1.0.4' does not exist in this registry

The package does exist on npm (latest is 1.0.3), and the dry-run in the same job succeeded. 404 is npm's mask for an unauthorized publish — the NPM_TOKEN no longer authenticates.

Why the fix is not just id-token: write

bun publish cannot perform the npm OIDC token exchange (oven-sh/bun#22423, #15601); the implementation PR was closed unmerged. Bun's own release pipeline publishes its npm package with npm publish for this reason. Adding the permission alone would still fail, because changepacks resolves the publish command from the lockfile and bun.lock selects bun publish.

Changes

.changepacks/config.json — override the node publish command. This key takes precedence over lockfile detection, so changepacks stops calling bun publish without changing how the repo installs or builds. Same shape as devup-ui: bun packs the tarball, so the packed manifest is byte-identical to what shipped before, then npm publishes that tarball over OIDC.

"publish": {
  "node": "bun pm pack --quiet --filename .changepacks/publish.tgz && npm publish .changepacks/publish.tgz"
},
"publishDryRun": {
  "node": "bun pm pack --quiet --filename .changepacks/publish.tgz && npm publish .changepacks/publish.tgz --dry-run"
}

.github/workflows/publish.yml

  • id-token: write — lets npm exchange GitHub's short-lived OIDC token.
  • actions/setup-node@v7 (Node 24, registry-url) + npm install -g npm@latest — trusted publishing requires npm >= 11.5.1, above what the runner image ships.
  • NPM_CONFIG_TOKEN removed. An empty token still counts as a value to npm and suppresses the OIDC exchange, so the variable has to be gone, not blank.
  • actions/checkout@v4 -> @v7, clearing the Node 20 deprecation annotation on this run.

.changepacks/publish.tgz is already covered by the *.tgz entry in .gitignore.

Required before merge

bun-test-env-dom must be registered as a Trusted Publisher at npmjs.com/package/bun-test-env-dom/accesswithout this the publish fails with the same 404.

Field Value
Organization dev-five-git
Repository bun-test-env-dom
Workflow filename publish.yml (filename only, not a path)
Environment leave empty

npm matches these exactly and case-sensitively; a mismatch surfaces as the same 404, which is indistinguishable from the current failure.

Verification

Ran locally against this branch:

  • bun pm pack --quiet --filename .changepacks/publish.tgz -> 7106 bytes, matching the 7.11 kB bun packed in the failing run.
  • npm publish .changepacks/publish.tgz --dry-run -> same 6 files, 7.1 kB packed / 18.6 kB unpacked as the previous bun output.
  • bun test (28 pass, 100% coverage) and bun lint pass via the pre-commit hook.
  • Workflow YAML parses; setup-node and the npm upgrade both precede changepacks/action.

The same pattern is already publishing in this org — @changepacks/cli@0.3.6 shipped through it, and devup-ui and csstype-extra use it.

Release 1.0.4 is still pending as a draft with its tag pushed, so merging this picks that release back up rather than needing a new version.

npm rejected the 1.0.4 publish with 404 Not Found, npm's mask for an unauthorized publish - the NPM_TOKEN no longer authenticates.

bun publish cannot perform the npm OIDC token exchange (oven-sh/bun#22423), so trusted publishing needs the publish command itself to be npm. changepacks selects that command from .changepacks/config.json, which overrides the bun.lock-derived default, matching how devup-ui publishes: bun packs the tarball so the packed manifest is unchanged, then npm publishes that tarball over OIDC.

The workflow grants id-token: write, installs Node 24 with npm >= 11.5.1 (the trusted publishing floor), and drops NPM_CONFIG_TOKEN entirely - an empty token still counts as a value to npm and suppresses the OIDC exchange.
@owjs3901
owjs3901 merged commit bb122d4 into main Sep 10, 2026
1 check 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