Skip to content

ci: promote over Trusted Publishing, and close the release there - #237

Merged
twk3 merged 2 commits into
mainfrom
claude/adoring-noether-6sagka
Oct 14, 2026
Merged

twk3 merged 2 commits into
mainfrom
claude/adoring-noether-6sagka

Conversation

@twk3

@twk3 twk3 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Promoting 2.7.0 to latest failed with 401 Unauthorized - PUT /-/package/@currents%2fmcp/dist-tags/latest. Promotion was the last workflow still holding an NPM_TOKEN: publishing moved to Trusted Publishing, which never reads that secret, so nothing exercised it until the tag had to move. After this, no workflow in the repo references NPM_TOKEN.

Promote authenticates over OIDC

npm authorizes dist-tag over OIDC from 11.21.0 (npm/cli#10038, merged 2026-09-30). The runner's bundled npm is older, so the job upgrades npm and then asserts the version, failing with a readable message rather than inside the registry call.

This needs a setting on npm that a workflow cannot set. Trusted publishing grants dist-tag separately from publish, and the grant is off by default, including for existing configurations (GitHub changelog) — so the configuration that published the 2.7.0 beta will still refuse the tag until Allow npm dist-tag is enabled on it. That is already done for @currents/mcp. The dist-tag failure path names the setting, so the next person who hits it on another package is not debugging a bare 401.

Promoting closes the release

The Linear-complete and Slack steps only ran from a latest publish. The documented flow is publish beta → test → promote, which never reaches that path, so promoting left the release open in Linear and silent in Slack — as it did for 2.7.0. They now run from promote as well. Both paths keep them: a version reaches latest by one route or the other, never both.

Two latent bugs found while in here

  • Promote checked out github.event.pull_request.head.sha, which is empty on a workflow_dispatch, so it silently took the default branch. Harmless for dist-tag, which reads no tree, but it is copied from publish.yaml where it matters. The npm ci step installed dependencies npm dist-tag does not use, and is dropped.
  • The latest channel guard accepted refs/tags/release/*, which release-it cannot produce — .release-it.json sets tagName: "v${version}". Only the branch arm could ever match, so running Publish from the v2.7.0 tag failed a guard that looked like it should have passed. The guard now names branches only and says why a tag does not match.

Not changed

.github/workflows/*.yaml does not satisfy Prettier today and the repo's format script covers only src and skills, so I left formatting alone rather than mix a reformat into this diff.

Verification

YAML parses and the step list is as intended; the version comparison was checked for equal, higher and lower npm versions. The OIDC exchange itself only exercises on a real dispatch — the first run of promote after this merges is the test.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y4EZAEvxLfXuMeNz5ZgCMz


Generated by Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

Promotion was the last workflow holding an NPM_TOKEN, and it had gone stale
unnoticed: publishing moved to Trusted Publishing, which does not read the
secret, so nothing exercised it until 2.7.0 needed the tag moved and the
registry answered 401.

npm authorizes dist-tag over OIDC from 11.21.0 (npm/cli#10038), so the job now
upgrades npm and asserts the version rather than failing later inside the
registry call. The grant is separate from publish and off by default, so the
dist-tag failure path names the setting to enable.

Linear and Slack ran only from a `latest` publish, which the beta-then-promote
flow never reaches, so promoting left the release open. They run here too.

The checkout read `github.event.pull_request.head.sha`, empty on a dispatch,
and `npm ci` installed dependencies that `npm dist-tag` does not use.

The `latest` guard accepted `refs/tags/release/*`, which release-it cannot
produce: it tags `v${version}`. Only the branch arm could ever match, and the
tag of a release failing the guard reads as a mistake.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y4EZAEvxLfXuMeNz5ZgCMz
@baz-reviewer

baz-reviewer Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Review this PR on Baz

Baz Summary

Promote npm releases through Trusted Publishing with OIDC by upgrading and validating npm, removing the obsolete NPM_TOKEN dependency, and improving dist-tag failure guidance. Complete the release in Linear and announce it in Slack after either promotion or latest-channel publishing, while correcting release-ref validation and documenting the flow.

Topics

TopicDetails
Trusted promotion Authenticate promotion through npm Trusted Publishing, remove unnecessary checkout and dependency installation, and provide actionable errors for missing dist-tag permissions.
Modified files (2)
  • .github/workflows/promote.yaml
  • RELEASE.md
Latest Contributors(2)
UserCommitDate
noreply@anthropic.comci: pin the npm that h...October 14, 2026
gimenez.maxi@gmail.comchore: add slack notif...May 28, 2026
Release completion Complete Linear releases and post Slack announcements after promotion or direct latest publishing, while restricting latest-channel validation to supported release/* branches.
Modified files (3)
  • .github/workflows/promote.yaml
  • .github/workflows/publish.yaml
  • RELEASE.md
Latest Contributors(2)
UserCommitDate
noreply@anthropic.comci: pin the npm that h...October 14, 2026
agoldis@gmail.comci: add skip_deploy in...August 16, 2026

Merger  Activate to get a short verdict whether this PR is good to go or not

Skills  Activate Skill Maintainer to keep your skills up to date

Planner  This PR would have been improved with Baz Planner - Try it now

Comment thread .github/workflows/promote.yaml Outdated
The job that promotes holds `id-token: write`, so anything running in it can
mint an npm credential for this package. `npm install -g npm@latest` resolved
that at release time to whatever the registry served, unreviewed.

Pinned to 12.2.0, which clears the 12.x floor npm/cli#10038 set for dist-tag
over OIDC. `--ignore-scripts` costs nothing today — the npm package declares no
install scripts — and bounds a release that adds one. The version assertion is
gone: it guarded `latest` resolving below the floor, which a pin cannot do.

The Linear and Slack steps move to a job without `id-token`. Neither needs it,
both resolve a mutable tag, and `complete` reads no checkout: the action scans
commits only for `sync`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y4EZAEvxLfXuMeNz5ZgCMz
@twk3
twk3 merged commit 1f2a12f into main Oct 14, 2026
4 checks passed
@twk3
twk3 deleted the claude/adoring-noether-6sagka branch October 14, 2026 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants