Skip to content

Publish on a v* tag alone, and stop the changelog drifting from the version - #147

Merged
ElliotDrel merged 1 commit into
mainfrom
t3code/unblock-tag-triggered-publish
Sep 5, 2026
Merged

Publish on a v* tag alone, and stop the changelog drifting from the version#147
ElliotDrel merged 1 commit into
mainfrom
t3code/unblock-tag-triggered-publish

Conversation

@ElliotDrel

Copy link
Copy Markdown
Collaborator

Closes #50.

Why

main has been at 3.4.4 since 2026-09-03. npm has been on 2.0.0 since July. The release path has been broken the whole time, and it was broken on purpose by a guard I added.

Since 3.3.3 the ungated validate job refused to release unless the npm-publish GitHub environment had a required reviewer configured. That was written as a fail-closed check so a missing approval gate could not silently publish. The environment never got a reviewer, so the check did exactly its job: v3.4.4 was tagged on 2026-09-04 and the run failed ten seconds in.

#50 asked @karthikcsq to tick the required-reviewer box. He'd rather not have the gate at all, which is a fair call, so this PR takes the other branch: drop the approval step and make a v* tag on main sufficient on its own.

What a release looks like now

Same shape as e-stack, where a tag push is the whole release:

npm run release:check      # tag, package.json, and CHANGELOG must agree
git tag vX.Y.Z
git push origin vX.Y.Z

CI takes it from there. Nothing to approve, no environment to configure, no npm token anywhere.

What still stands between a tag and npm

Dropping the approval does not drop the hardening. Everything below is unchanged:

  • Workflow has contents: read and no write access; it cannot push anything back.
  • id-token: write is scoped to the publish job alone, so the ungated validate job cannot mint the OIDC token npm accepts.
  • Both checkouts use persist-credentials: false.
  • Both actions stay pinned to a commit SHA.
  • The tagged commit must be reachable from main. A v* tag pushed from a local or unmerged branch fails validation. A release can only contain code that already went through review.
  • cancel-in-progress: false, so a second tag queues behind a running publish instead of cancelling it mid-npm publish.
  • Full test suite and npm pack --dry-run run before publishing.

What authorizes a release is now who can create a v* tag. RELEASING.md points at the tag ruleset that makes that a real restriction if you want it; the workflow does not depend on it existing.

About environment: npm-publish

It stays on the publish job. Not as a gate: npm's trusted publisher for this package names npm-publish as its environment, so the OIDC claim the job presents has to carry it or the publish is rejected. Removing the line would mean editing the npm side too. Both the workflow comment and RELEASING.md now say plainly that it is doing nothing but satisfying that claim. Adding a required reviewer to the environment later turns a real approval step back on with no code change.

New: scripts/check-release.mjs

CONTRIBUTING.md and CHANGELOG.md both state the same rule — the version at the top of the changelog, the version in package.json, and the tag are always the same number. Nothing enforced it. The workflow compared the tag against package.json only, so a PR that bumped the version but forgot its changelog entry produced a green release with a changelog that never mentioned what shipped.

The script checks all three, plus three failure modes that are invisible once a release is out:

  • a newest entry that is not greater than the one below it (copied and never renumbered, or filed out of order)
  • two entries claiming the same version, which means one of them lost its notes
  • a prerelease version, which this release flow does not handle

Dependency-free on purpose, so validate runs it before npm ci costs anything, and npm run release:check works locally without a network round trip.

Docs

  • RELEASING.md now leads with the three commands a release takes, drops the required-reviewer setup step, states the security argument that actually applies, records why the gate was removed rather than configured, and documents re-running a release whose tag already exists (delete and re-push the tag — a second git push of an existing tag does not re-trigger anything).
  • docs/architecture.md no longer describes publishing as gated on an environment.

Verification

npm run release:check   Release 3.4.5 is consistent with tag v3.4.5
npm run test:ci         Test Suites: 97 passed, 97 total
                        Tests: 2 skipped, 1429 passed, 1431 total
npm pack --dry-run      google-tools-mcp-3.4.5.tgz, 185 files, 396.7 kB

tests/releaseConsistency.test.js adds 10 cases over check-release.mjs, including one that asserts this branch's own package.json and CHANGELOG.md agree. tests/fixtures/mcp-migration-inventory.json is regenerated for the new test file (3 lines).

After merging

v3.4.4 already exists remotely and points at a commit that predates this fix, so it will not retrigger. Tag v3.4.5 on the merge commit and 3.4.5 ships — the first release since 2.0.0.

🤖 Generated with Claude Code

Every release was blocked by a gate nobody configured. The publish job declared
`environment: npm-publish`, and since 3.3.3 the ungated `validate` job refused to
release unless that environment carried a required reviewer. It never got one,
so `v3.4.4` was tagged on 2026-09-04 and the run failed ten seconds in. npm has
been on 2.0.0 while main sat at 3.4.4.

Drop the gate rather than configure it, matching how e-stack publishes: a `v*`
tag whose commit is reachable from main runs start to finish with nothing to
approve. What authorizes a release is who can create the tag. The hardening that
was not in the way stays: no write access, SHA-pinned actions, split ungated
validate job, `cancel-in-progress: false`, test suite and `npm pack --dry-run`
before publish. `environment: npm-publish` stays on the job because npm's
trusted publisher names that environment and the OIDC claim has to match it;
the workflow comment and RELEASING.md both now say that is all it does.

Add scripts/check-release.mjs and `npm run release:check`. CONTRIBUTING.md and
CHANGELOG.md both say the tag, package.json, and the newest changelog entry are
the same number, and nothing enforced it. The workflow compared the tag against
package.json only, so a PR that bumped the version but skipped its changelog
entry shipped green. The script also catches an entry copied from the one below
it and never renumbered, an out-of-order entry, and a duplicated version. It has
no dependencies, so validate rejects a bad tag before `npm ci` costs anything.

Closes #50.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 217682d9-cfd6-46fb-8df4-1c5ef745fb84

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6ba0b9b453

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +72 to +75
# This is NOT an approval gate and is not relied on as one. It is here
# because npm's trusted publisher for this package names `npm-publish` as its
# environment, so the OIDC identity this job presents has to carry that claim
# or the publish is rejected. The environment has no protection rules; what

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Upgrade npm before unblocking trusted publishing

On the first v* tag now allowed past validate, the publish job will still fail authentication: the current Node 24 distribution resolves to Node 24.15.0 with npm 11.4.2, while npm's Trusted Publishers requirements specify “npm CLI version 11.5.1 or later” (npm documentation). actions/setup-node does not upgrade the bundled npm, and this workflow proceeds directly through npm ci to npm publish, so the CLI cannot perform the OIDC exchange and the release remains blocked; install or pin a supported npm version in the publish job.

Useful? React with 👍 / 👎.

@ElliotDrel
ElliotDrel merged commit 0644ff3 into main Sep 5, 2026
3 checks passed
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.

Remove the npm-publish approval gate (superseded: PR #147 drops it instead of configuring it)

1 participant