From 37e81a14fe749becf640c15fdea66f667491dc02 Mon Sep 17 00:00:00 2001 From: Michael Turner Date: Wed, 29 Jul 2026 13:55:39 -0500 Subject: [PATCH] switch npm publishing to trusted publishing (OIDC) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Grant the job id-token: write (plus contents: read for the tag guard and release-asset download); npm publish exchanges the GitHub OIDC token for a short-lived per-publish credential and generates provenance attestations automatically. - Drop registry-url from setup-node: it writes an .npmrc authToken line referencing $NODE_AUTH_TOKEN, and npm hard-fails on every command when a referenced env var is unset. - Bump to Node 24 (Node 20 is EOL) and pin npm@12.0.1 alongside the existing semver pin — trusted publishing requires npm >= 11.5.1 and the runner's bundled npm may lag. - Remove NODE_AUTH_TOKEN from the publish step; no registry token is referenced anywhere anymore. --- .github/workflows/npm-publish.yml | 35 +++++++++++++++++++------------ 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 6286640..d20ea13 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -37,6 +37,13 @@ jobs: npm: name: Publish to npm runs-on: ubuntu-latest + permissions: + # Publishing authenticates via npm trusted publishing: the job mints a + # GitHub OIDC token that npm verifies against each package's trusted + # publisher config (this repo + this workflow filename). No registry + # token exists anywhere. + id-token: write + contents: read steps: - name: Require the newest stable vX.Y.Z tag run: | @@ -64,20 +71,24 @@ jobs: with: ref: ${{ env.TAG }} + # No registry-url here: setup-node would write an .npmrc authToken + # line referencing $NODE_AUTH_TOKEN, and npm hard-fails on any command + # when a referenced env var is unset. Trusted publishing needs no + # token; npm publish detects the OIDC environment on its own. - uses: actions/setup-node@v4 with: - node-version: "20" - registry-url: "https://registry.npmjs.org" + node-version: "24" - # Installed up front so a fetch failure is a loud step failure. If the - # publish loop fetched it via npx on demand, a transient network error - # would be indistinguishable from "version not newer" and would - # silently skip publishing a package. Pinned to an exact version: this - # is the only third-party code fetched into the job that holds publish - # rights for the @provablehq packages, and npm versions are immutable, - # so a pin closes off both drift and package-takeover of new releases. - - name: Install semver CLI - run: npm install -g semver@7.8.5 + # npm >= 11.5.1 is required for trusted publishing; the runner's + # bundled npm may lag. Both tools installed up front so a fetch + # failure is a loud step failure (npx-on-demand in the publish loop + # would be indistinguishable from "version not newer" and silently + # skip a package), and pinned to exact versions: this is the only + # third-party code fetched into the job that holds publish rights for + # the @provablehq packages, and npm versions are immutable, so a pin + # closes off both drift and package-takeover of new releases. + - name: Install pinned npm and semver CLI + run: npm install -g npm@12.0.1 semver@7.8.5 - name: Download release assets run: gh release download "$TAG" --pattern '*.zip' --dir artifacts @@ -133,5 +144,3 @@ jobs: publish "./${pkg%/}" done publish ./dist-npm/main - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}