Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 32 additions & 14 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,21 @@
# Renaming this file silently breaks publishing — npm will refuse the exchange
# because the run no longer matches what was configured.
#
# What that looks like when it goes wrong, since the error names neither OIDC
# nor trusted publishing:
# When it goes wrong the error names neither OIDC nor trusted publishing:
#
# npm error code E404
# npm error 404 Not Found - PUT https://registry.npmjs.org/moshcode
# npm error 404 ... could not be found or you do not have permission
#
# There is no credential at all in that case, and npm reports it as if the
# package did not exist. If you see it, the publisher is not registered, or is
# registered against a different workflow filename.
# That is an unauthenticated PUT, reported as though the package did not exist.
# It has two quite different causes, and it took v0.24.3 to tell them apart:
#
# 1. anything that leaves an empty auth token in an .npmrc, which stops npm
# attempting the exchange at all — see the setup-node note below; or
# 2. no trusted publisher registered for this package, or one registered
# against a different workflow filename.
#
# Check 1 first. It is in this file, and it is the one that looks like 2.
name: publish

on:
Expand All @@ -56,16 +61,27 @@ jobs:
# with ERR_PNPM_BAD_PM_VERSION.
- uses: pnpm/action-setup@v4

# Deliberately no `registry-url`. With it, setup-node always writes
#
# //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}
#
# into an .npmrc — correct for token auth, and quietly fatal here. Under
# trusted publishing there is no NODE_AUTH_TOKEN, so that line resolves to
# an empty token, and npm stops before ever attempting the OIDC exchange:
# it believes it already has credentials. The registry then answers the
# unauthenticated PUT with E404, which names nothing to do with OIDC and
# is what sent us looking at the npmjs.com config instead of at this file.
#
# actions/setup-node#1551. Without registry-url no .npmrc is written and
# npm defaults to registry.npmjs.org anyway, which is where we publish.
- uses: actions/setup-node@v4
with:
node-version: 22
node-version: 24
cache: pnpm
registry-url: https://registry.npmjs.org

# Node 22 bundles npm 10, which predates trusted publishing and would fall
# back to looking for a token that no longer exists — an auth failure that
# reads as a credential problem rather than a version one. 11.5.1 is the
# floor; the check below says so plainly if that ever regresses.
# Node 24 bundles npm 11, but pin the floor anyway rather than depend on
# what a runner image happens to ship: below 11.5.1 there is no trusted
# publishing, and the failure would again look like a credential problem.
- name: Install an npm that understands trusted publishing
run: |
npm install -g npm@latest
Expand Down Expand Up @@ -122,11 +138,13 @@ jobs:
echo "already=false" >> "$GITHUB_OUTPUT"
fi

# No token, and no `--provenance` either: publishing through trusted
# publishing generates and attaches the attestation on its own.
# No token. `--provenance` is passed even though npm documents it as
# automatic under trusted publishing: reports differ on whether it really
# is, and asking for it explicitly costs nothing and cannot produce a
# weaker result. v0.24.2 published with an attestation using this flag.
- name: Publish
if: steps.published.outputs.already == 'false'
run: npm publish --access public
run: npm publish --access public --provenance

- name: Confirm the registry has it
if: steps.published.outputs.already == 'false'
Expand Down
Loading