Skip to content

Runbook: recover stranded June npm releases by re-running release.yml publish jobs (no repo changes — June 3 window closes TODAY) #4465

Description

@cliffhall

Goal

Get everything that changed for TypeScript in the last two failed release attempts onto npm — without touching the repo (no workflow edits, no new tags, no new versions, no empty catch-up releases). Pure operations: re-run the publish step of the existing release.yml runs.

A re-run of a release.yml run is a release.yml execution in the release environment, so it matches what npm's trusted-publisher config expects the publish to come from. Pipeline rebuild work is tracked separately in #4463 and is deliberately out of scope here.

What's stranded

Run Version npm packages never published PyPI (succeeded)
26882432128 (cron, Jun 3) 2026.6.4 (tag 2026.6.3 everything, memory, filesystem, sequential-thinking fetch, time, git
27626321345 (dispatch, Jun 16) 2026.6.16 everything git

¹ Known quirk: the tag says 2026.6.3 but the packages inside are stamped 2026.6.4 (approval wait crossed midnight UTC between version generation and stamping). Harmless here; fix tracked in #4463.

Root cause of the failures: npm error code E404 on the publish PUT — npm's disguised auth failure. The NPM_TOKEN secret is dead. Everything else (checkout of the tag, build, version guard) passed.

⚠️ Deadline

GitHub's re-run window is 30 days from run creation. For the June 3 run that is TODAY, July 3 (~11:42 UTC). Do step 3 immediately, even before the rest is fully tidy. The June 16 run has until ~July 16.

If the June 3 window has already closed (the re-run option disappears), its four packages cannot be recovered at 2026.6.4 — their changes reach npm with the next real release (see #4463, Option B). The June 16 run still covers everything's newest changes.

Why this works (and the one auth nuance)

  • gh run rerun --failed re-runs only the failed matrix legs (fail-fast: false), checked out at the original version tag — it publishes exactly the tagged code.
  • Partial success is fine and durable. Legs are independent: if the token can publish only some packages, those publish and stay published; a later rerun --failed re-runs only the still-failed legs (each rerun needs a fresh environment approval). ⚠️ But the 30-day rerun clock runs from the original run and is not reset by reruns — for the June 3 run, any re-attempt must also happen before the window closes.
  • Re-runs execute the original workflow snapshot, which authenticates with NODE_AUTH_TOKEN — but secrets are re-read at re-run time. So a refreshed NPM_TOKEN is picked up with zero repo changes.
  • Token auth is the only path these reruns can take. Trusted publishing is client-initiated (npm CLI mints and exchanges an OIDC token), and the old snapshot can't do that: no id-token: write permission and an npm CLI too old for trusted publishing. An expired/insufficient token is simply rejected by the registry (the disguised E404) — it neither falls back to OIDC nor interferes with it. The failed leg stays rerunnable.
  • The npm trusted-publisher (OIDC) config does not block token publishes unless "disallow tokens / require trusted publisher" is enabled in each package's publishing-access settings. Leave that switch off until this recovery is done, then flip it.

Steps

  1. Provision a temporary token. Create a granular npm automation token with publish permission on @modelcontextprotocol/server-everything, server-memory, server-filesystem, server-sequential-thinking. Update the NPM_TOKEN secret wherever it lives (check both repo Settings → Secrets → Actions and the release environment secrets).

  2. Confirm token publishing is still allowed on those four packages (npm package Settings → Publishing access). Don't restrict to trusted-publisher-only yet.

  3. June 3 run — do this first (deadline today, and publishing order keeps latest correct):

    1. Open run 26882432128Review pending deploymentsreject the waiting create-release deployment so the run completes.
    2. gh run rerun 26882432128 --failed --repo modelcontextprotocol/servers
    3. Approve the release environment deployment when the re-run requests it.
    4. Expect: 4 npm legs publish at 2026.6.4; create-release then creates GitHub release 2026.6.3.
  4. June 16 run — same procedure on run 27626321345: reject pending create-releasegh run rerun 27626321345 --failed → approve → expect everything@2026.6.16 + GitHub release 2026.6.16.

    (Ordering matters: publishing 2026.6.4 after 2026.6.16 would move everything's latest dist-tag backwards.)

  5. Verify:

    for p in server-everything server-filesystem server-memory server-sequential-thinking; do
      echo "== $p =="; npm view @modelcontextprotocol/$p dist-tags.latest versions --json | tail -5
    done

    Expected: all four at 2026.6.4; everything at 2026.6.16 with latest = 2026.6.16.

  6. Clean up: revoke the temporary token, delete/rotate the NPM_TOKEN secret, and only then enable trusted-publisher-only publishing on the packages. Future publishes go through OIDC (workflow changes for that: v2 release pipeline, Phase 1: OIDC trusted publishing — ✅ complete (validation release 2026.7.4) #4463).

What NOT to do

Metadata

Metadata

Assignees

Labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions