Skip to content

fix(ci): publish to npm on Node 24 and make a failed publish retryable - #165

Merged
antonbabenko merged 1 commit into
masterfrom
fix/release-npm-publish-node24
Jul 27, 2026
Merged

fix(ci): publish to npm on Node 24 and make a failed publish retryable#165
antonbabenko merged 1 commit into
masterfrom
fix/release-npm-publish-node24

Conversation

@antonbabenko

Copy link
Copy Markdown
Owner

The failure

v3.12.0 tagged and published its GitHub Release, then died on the npm step (run):

npm error notsup Required: {"node":"^22.22.2 || ^24.15.0 || >=26.0.0"}
npm error notsup Actual:   {"npm":"10.8.2","node":"v20.20.2"}

npm install -g npm@latest - which the OIDC trusted-publishing flow needs - now resolves to npm 12, and npm 12 refuses Node 20. npm is still on 3.11.0 while the tag and GitHub Release say 3.12.0.

Why it was stuck

The publish steps were gated on steps.tag.outputs.created == 'true'. The tag was created on the first (failed) attempt, so every retry after that evaluated the gate to false and silently skipped the publish. Re-running the original run does not help either - GitHub replays the workflow file as of that commit, Node 20 pin included.

Changes

  • Node 24 for the publish step. The actual root-cause fix.
  • Gate on npm, not on tag creation. npm view <pkg>@<version> decides whether to publish. The registry is the source of truth for what shipped, and it rejects duplicate versions anyway - so this is both idempotent and self-healing.
  • workflow_dispatch retry hatch taking an existing tag. It checks out that tag and re-drives the publish from the current workflow file. Guarded so the dispatched tag must equal v$(version.json) at that ref.
  • Tag creation keys off the checked-out commit rather than $GITHUB_SHA, which on a dispatch is master HEAD rather than the release tag.

Test plan

  • validate passes
  • After merge, dispatch Tag and Publish Release with tag v3.12.0 to finish the stuck release
  • npm view @antonbabenko/deliberation-mcp version reports 3.12.0
  • Re-dispatching the same tag is a no-op (npm gate reports already published)

The v3.12.0 release tagged and published the GitHub Release, then died on
the npm step:

  npm error notsup Required: {"node":"^22.22.2 || ^24.15.0 || >=26.0.0"}
  npm error notsup Actual:   {"npm":"10.8.2","node":"v20.20.2"}

`npm install -g npm@latest` (needed for OIDC trusted publishing) now
resolves to npm 12, which refuses Node 20. Bump the publish step to Node 24.

That left the release unrecoverable: the publish steps were gated on
`tag.outputs.created == 'true'`, and the tag already existed from the failed
attempt, so every retry skipped the publish. Two changes make it recoverable:

- Gate on whether the version is already on npm. The registry is the real
  source of truth for what shipped, and it rejects duplicate versions anyway.
- Add a workflow_dispatch retry hatch taking an existing tag. Re-running the
  original run cannot work - GitHub replays the workflow file from that
  commit, bugs included. Dispatch checks out the tag and re-drives the
  publish from the current workflow file.

Tag creation now keys off the checked-out commit rather than $GITHUB_SHA,
which on a dispatch is master HEAD rather than the release tag.
@antonbabenko
antonbabenko merged commit 451eea7 into master Jul 27, 2026
1 check passed
@antonbabenko
antonbabenko deleted the fix/release-npm-publish-node24 branch July 27, 2026 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant