2020# Renaming this file silently breaks publishing — npm will refuse the exchange
2121# because the run no longer matches what was configured.
2222#
23- # What that looks like when it goes wrong, since the error names neither OIDC
24- # nor trusted publishing:
23+ # When it goes wrong the error names neither OIDC nor trusted publishing:
2524#
2625# npm error code E404
2726# npm error 404 Not Found - PUT https://registry.npmjs.org/moshcode
2827# npm error 404 ... could not be found or you do not have permission
2928#
30- # There is no credential at all in that case, and npm reports it as if the
31- # package did not exist. If you see it, the publisher is not registered, or is
32- # registered against a different workflow filename.
29+ # That is an unauthenticated PUT, reported as though the package did not exist.
30+ # It has two quite different causes, and it took v0.24.3 to tell them apart:
31+ #
32+ # 1. anything that leaves an empty auth token in an .npmrc, which stops npm
33+ # attempting the exchange at all — see the setup-node note below; or
34+ # 2. no trusted publisher registered for this package, or one registered
35+ # against a different workflow filename.
36+ #
37+ # Check 1 first. It is in this file, and it is the one that looks like 2.
3338name : publish
3439
3540on :
@@ -56,16 +61,27 @@ jobs:
5661 # with ERR_PNPM_BAD_PM_VERSION.
5762 - uses : pnpm/action-setup@v4
5863
64+ # Deliberately no `registry-url`. With it, setup-node always writes
65+ #
66+ # //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}
67+ #
68+ # into an .npmrc — correct for token auth, and quietly fatal here. Under
69+ # trusted publishing there is no NODE_AUTH_TOKEN, so that line resolves to
70+ # an empty token, and npm stops before ever attempting the OIDC exchange:
71+ # it believes it already has credentials. The registry then answers the
72+ # unauthenticated PUT with E404, which names nothing to do with OIDC and
73+ # is what sent us looking at the npmjs.com config instead of at this file.
74+ #
75+ # actions/setup-node#1551. Without registry-url no .npmrc is written and
76+ # npm defaults to registry.npmjs.org anyway, which is where we publish.
5977 - uses : actions/setup-node@v4
6078 with :
61- node-version : 22
79+ node-version : 24
6280 cache : pnpm
63- registry-url : https://registry.npmjs.org
6481
65- # Node 22 bundles npm 10, which predates trusted publishing and would fall
66- # back to looking for a token that no longer exists — an auth failure that
67- # reads as a credential problem rather than a version one. 11.5.1 is the
68- # floor; the check below says so plainly if that ever regresses.
82+ # Node 24 bundles npm 11, but pin the floor anyway rather than depend on
83+ # what a runner image happens to ship: below 11.5.1 there is no trusted
84+ # publishing, and the failure would again look like a credential problem.
6985 - name : Install an npm that understands trusted publishing
7086 run : |
7187 npm install -g npm@latest
@@ -122,11 +138,13 @@ jobs:
122138 echo "already=false" >> "$GITHUB_OUTPUT"
123139 fi
124140
125- # No token, and no `--provenance` either: publishing through trusted
126- # publishing generates and attaches the attestation on its own.
141+ # No token. `--provenance` is passed even though npm documents it as
142+ # automatic under trusted publishing: reports differ on whether it really
143+ # is, and asking for it explicitly costs nothing and cannot produce a
144+ # weaker result. v0.24.2 published with an attestation using this flag.
127145 - name : Publish
128146 if : steps.published.outputs.already == 'false'
129- run : npm publish --access public
147+ run : npm publish --access public --provenance
130148
131149 - name : Confirm the registry has it
132150 if : steps.published.outputs.already == 'false'
0 commit comments