Skip to content

Commit d3e64bd

Browse files
authored
ci: authenticate the npm publish with NPM_TOKEN again (#307)
Revert the publish workflow to a stored NPM_TOKEN. Trusted publishing needs a publisher registered on npmjs.com against the workflow filename, which is web-UI only; until then npm rejects the publish as E404/no-permission, which is how v0.24.1 failed. Restores the missing-secret guard and --provenance.
1 parent 041fe79 commit d3e64bd

1 file changed

Lines changed: 27 additions & 30 deletions

File tree

.github/workflows/publish.yml

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
# that failed on something transient; it is safe because a version already on
1111
# the registry is skipped rather than attempted.
1212
#
13-
# Authenticates by trusted publishing (OIDC) rather than a stored token: npm
14-
# trades the short-lived token GitHub mints for this specific workflow run for
15-
# permission to publish, so there is no long-lived credential in the repository
16-
# to leak, rotate or forget.
13+
# Authenticates with a stored npm automation token, in the repository secret
14+
# `NPM_TOKEN`. Trusted publishing (OIDC) would avoid the stored credential, but
15+
# it needs a trusted publisher registered against this workflow's filename on
16+
# npmjs.com, which can only be done through the web UI — and until that exists
17+
# npm rejects the publish as E404/no-permission, which is how v0.24.1 failed.
1718
#
18-
# The other half of that trust lives on npmjs.com, under the package's Trusted
19-
# Publisher settings, and it is pinned to the *filename* of this workflow.
20-
# Renaming this file silently breaks publishing — npm will refuse the exchange
21-
# because the run no longer matches what was configured.
19+
# Worth knowing when this is next revisited: npm is restricting tokens that
20+
# bypass 2FA for direct publishing, so the token path has a horizon.
21+
# https://gh.io/npm-gat-bypass2fa-deprecation
2222
name: publish
2323

2424
on:
@@ -28,9 +28,9 @@ on:
2828

2929
permissions:
3030
contents: read
31-
# The whole basis of the exchange: this is what lets the run mint the OIDC
32-
# token npm authenticates against. Without it there is no credential at all
33-
# and publishing fails outright.
31+
# Still needed with token auth: provenance is signed with a short-lived OIDC
32+
# token even though the publish itself authenticates with NPM_TOKEN. Without
33+
# it `--provenance` fails.
3434
id-token: write
3535

3636
jobs:
@@ -51,22 +51,6 @@ jobs:
5151
cache: pnpm
5252
registry-url: https://registry.npmjs.org
5353

54-
# Node 22 bundles npm 10, which predates trusted publishing and would fall
55-
# back to looking for a token that no longer exists — an auth failure that
56-
# reads as a credential problem rather than a version one. 11.5.1 is the
57-
# floor; the check below says so plainly if that ever regresses.
58-
- name: Install an npm that understands trusted publishing
59-
run: |
60-
npm install -g npm@latest
61-
VERSION="$(npm --version)"
62-
MINIMUM=11.5.1
63-
echo "npm $VERSION"
64-
# Lowest of the two must be the minimum, or this npm is older than it.
65-
if [ "$(printf '%s\n%s\n' "$MINIMUM" "$VERSION" | sort -V | head -n1)" != "$MINIMUM" ]; then
66-
echo "::error::npm $VERSION cannot use trusted publishing — $MINIMUM or later is required"
67-
exit 1
68-
fi
69-
7054
- run: pnpm install --frozen-lockfile
7155

7256
# Publishing is the one action here that cannot be taken back — npm will
@@ -111,11 +95,24 @@ jobs:
11195
echo "already=false" >> "$GITHUB_OUTPUT"
11296
fi
11397
114-
# No token, and no `--provenance` either: publishing through trusted
115-
# publishing generates and attaches the attestation on its own.
98+
# Said plainly here, rather than as the E404/no-permission npm otherwise
99+
# returns partway through a release — an error that reads as "the package
100+
# does not exist" rather than "there is no credential".
101+
- name: Require an npm token
102+
if: steps.published.outputs.already == 'false'
103+
env:
104+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
105+
run: |
106+
if [ -z "$NPM_TOKEN" ]; then
107+
echo "::error::NPM_TOKEN is not set — add an npm automation token as a repository secret named NPM_TOKEN"
108+
exit 1
109+
fi
110+
116111
- name: Publish
117112
if: steps.published.outputs.already == 'false'
118-
run: npm publish --access public
113+
run: npm publish --access public --provenance
114+
env:
115+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
119116

120117
- name: Confirm the registry has it
121118
if: steps.published.outputs.already == 'false'

0 commit comments

Comments
 (0)