From 1e20882d9b8048601501c5839c5cfc68580c7e02 Mon Sep 17 00:00:00 2001 From: Eric Viana Date: Mon, 27 Jul 2026 11:58:21 -0300 Subject: [PATCH] fix(ci): publish via npm trusted publishing instead of a stale token The publish job has failed on every run since 2026-05-15. The tarball builds fine; only the registry call fails, with: npm error code E404 npm error 404 Not Found - PUT https://registry.npmjs.org/@blindpay%2fcli npm error 404 The requested resource '@blindpay/cli@0.4.0' could not be found or you do not have permission to access it. Cause: the job passed NODE_AUTH_TOKEN from secrets.NPM_TOKEN. setup-node writes that into .npmrc as _authToken, which takes precedence over the OIDC exchange and disables trusted publishing. The token itself was created 2026-03-06 and npm granular tokens expire within 90 days, so it went dead in early June. Every failure from 2026-06-17 onward is a real version bump (0.2.0, 0.3.0, 0.3.1, 0.4.0) rejected on auth, not a version conflict. blindpay-node's publish workflow is byte-identical except that it passes no token, and it publishes successfully with SLSA provenance attestations. This aligns cli with it. A trusted publisher is now configured on npmjs.com for @blindpay/cli pointing at blindpaylabs/blindpay-cli and publish.yml. npm is stuck at 0.1.1 while main is 0.4.0, so merging this ships three releases' worth of accumulated work, including the receivers to customers command rename. Also: - Skip instead of fail when package.json's version is already on the registry. The job runs on every push to main, so an unchanged version was failing the run and burying real failures in noise. - Tag and create a GitHub release on publish. The repo has no tags at all today. - Drop `ref: github.head_ref`, which is empty on a push event. Claude-Session: https://claude.ai/code/session_01F1stiNzuNtJXoXtiW9ZCbs --- .github/workflows/publish.yml | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 013db1e..d2c04fe 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -19,7 +19,6 @@ jobs: - name: Checkout uses: actions/checkout@v5 with: - ref: ${{ github.head_ref }} fetch-depth: 0 - name: Setup Bun @@ -33,13 +32,42 @@ jobs: node-version: 24 registry-url: 'https://registry.npmjs.org' + - name: Resolve version + id: version + run: echo "value=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT" + + # This runs on every push to main, so skip an unchanged version instead of + # failing the run on "cannot publish over the previously published version". + - name: Check whether version is already published + id: published + run: | + if npm view "@blindpay/cli@${{ steps.version.outputs.value }}" version >/dev/null 2>&1; then + echo "value=true" >> "$GITHUB_OUTPUT" + else + echo "value=false" >> "$GITHUB_OUTPUT" + fi + - name: Install dependencies + if: steps.published.outputs.value == 'false' run: bun install --frozen-lockfile - name: Build package + if: steps.published.outputs.value == 'false' run: bun run build + # Auth comes from npm trusted publishing (OIDC), enabled by id-token: write. + # Passing NODE_AUTH_TOKEN here writes an _authToken into .npmrc, which takes + # precedence over the OIDC exchange and fails with E404. - name: Publish package + if: steps.published.outputs.value == 'false' run: npm publish + + - name: Tag and create release + if: steps.published.outputs.value == 'false' env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + TAG="v${{ steps.version.outputs.value }}" + git tag "$TAG" + git push origin "$TAG" + gh release create "$TAG" --title "$TAG" --generate-notes