Skip to content

fix(release): keep npm channels monotonic - #3201

Merged
M4n5ter merged 1 commit into
mainfrom
fix/cli-release-channel-tags
Aug 18, 2026
Merged

fix(release): keep npm channels monotonic#3201
M4n5ter merged 1 commit into
mainfrom
fix/cli-release-channel-tags

Conversation

@M4n5ter

@M4n5ter M4n5ter commented Aug 18, 2026

Copy link
Copy Markdown
Member
English

Summary

  • Require npm's next channel to remain at or ahead of latest, while preserving a newer prerelease when one already exists.
  • Give stable-release maintainers an interactive dist-tag command instead of adding a long-lived npm token to Actions.
  • Fix Finalize's npm 406 failure by requesting the full JSON representation from the single-version metadata endpoint.

Verification

  • npm run check:release — 28 tests passed.
  • go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.7 .github/workflows/release-cli-stage.yml .github/workflows/release-cli-finalize.yml
  • Biome and git diff --check passed.
  • The original Stage artifact from run 32123297725 was fetched from the public registry and retained SHA-256 9daa78ced074d00a32fad4d179cb0aa37d6c431bf4b53e188446c14cf29a6ae2.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex implemented the release-channel validation, registry media-type fix, tests, and documentation under human direction and review.

Checklist

  • Tests cover the change and fail without it
  • Lint, format and the affected suites pass locally; typecheck was not run because no TypeScript changed

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No
简体中文

摘要

  • 要求 npm 的 next 不得落后于 latest;如果 next 已指向更新的预发布版本,则保持不变。
  • 稳定版需要推进 next 时,由维护者进行交互式 dist-tag 操作,不向 Actions 添加长期 npm token。
  • 单版本 metadata 改用完整 JSON representation,修复 Finalize 请求 npm 时出现的 406。

验证

  • npm run check:release:28 项测试通过。
  • Actionlint、Biome 和 git diff --check 通过。
  • 使用 Stage run 32123297725 的原始 artifact 完成真实公共 registry 校验,SHA-256 仍为 9daa78ced074d00a32fad4d179cb0aa37d6c431bf4b53e188446c14cf29a6ae2

AI 使用

  • Codex 在人工指导与审核下实现了发布 channel 校验、registry media-type 修复、测试和文档。

Stable publication advances latest but cannot update next through trusted publishing. Require next to remain at or ahead of latest, and document the interactive owner step without adding a registry token to Actions.

Use the full JSON representation for single-version registry metadata so Finalize does not fail with npm's 406 response to the abbreviated packument media type.

Generated-by: Codex
@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 867133df-cdc8-4e03-bc04-7af846803ee5

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

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

@M4n5ter
M4n5ter marked this pull request as ready for review August 18, 2026 10:32
@M4n5ter
M4n5ter merged commit 2722065 into main Aug 18, 2026
12 of 13 checks passed
@M4n5ter
M4n5ter deleted the fix/cli-release-channel-tags branch August 18, 2026 10:32
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Keep npm release channels monotonic and fix metadata fetches

🐞 Bug fix 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Enforce that npm’s next channel never trails latest during release finalization.
• Request full JSON for version metadata to prevent npm registry 406 failures.
• Guide maintainers to advance stable dist-tags interactively without storing npm credentials.
Diagram

graph TD
  STAGE["Stage Workflow"] --> GUIDE["Stable Guidance"] --> OWNER["npm Maintainer"] --> NPM[("npm Registry")]
  OWNER --> FINAL["Finalize Workflow"] --> VERIFY["Release Verifier"] --> GH["GitHub Release"]
  VERIFY --> NPM
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Automate dist-tag mutation in Actions
  • ➕ Eliminates the manual stable-release step.
  • ➕ Could repair channels immediately after publication.
  • ➖ Requires a long-lived npm credential because Trusted Publishing cannot mutate dist-tags.
  • ➖ Expands release workflow permissions and credential exposure.
2. Use a SemVer package
  • ➕ Delegates precedence rules to a mature, widely tested implementation.
  • ➕ Reduces custom comparison code and edge-case risk.
  • ➖ The verifier currently runs without installing repository dependencies.
  • ➖ Adds dependency and supply-chain overhead to a release-critical standalone script.

Recommendation: Keep the PR’s fail-closed validation and interactive dist-tag repair. It preserves least privilege while preventing Finalize from accepting regressed channels; the constrained, dependency-free SemVer comparator also fits the standalone verifier, provided its focused precedence tests remain comprehensive.

Files changed (6) +197 / -32

Bug fix (1) +95 / -23
release-cli-publication.mjsValidate npm channel ordering during finalization +95/-23

Validate npm channel ordering during finalization

• Adds SemVer-aware validation ensuring the release tag targets the expected version and 'next' never trails 'latest'. Requests full JSON from the single-version endpoint to avoid npm 406 responses while retaining abbreviated metadata for package-level queries.

scripts/release-cli-publication.mjs

Tests (2) +50 / -3
release-cli-publication.test.mjsTest channel monotonicity and registry media types +47/-3

Test channel monotonicity and registry media types

• Covers stable, prerelease, missing, lagging, and newer 'next' channel cases. Registry fixtures now verify endpoint-specific Accept headers and preserve request options through tarball test wrappers.

scripts/release-cli-publication.test.mjs

release-cli-workflow-policy.test.mjsRequire stable dist-tag guidance in Stage policy tests +3/-0

Require stable dist-tag guidance in Stage policy tests

• Asserts that the Stage summary conditionally detects stable releases and includes the interactive 'npm dist-tag add' command.

scripts/release-cli-workflow-policy.test.mjs

Documentation (2) +45 / -6
cli-npm-release.mdDocument monotonic npm channel requirements +23/-3

Document monotonic npm channel requirements

• Defines the invariant that 'next' cannot trail 'latest'. Documents the manual stable dist-tag procedure, its credential rationale, and Finalize’s new channel validation.

docs/cli-npm-release.md

cli-npm-release.zh-CN.mdTranslate monotonic channel release guidance +22/-3

Translate monotonic channel release guidance

• Adds the Chinese documentation for channel ordering, interactive stable dist-tag advancement, and Finalize verification behavior.

docs/cli-npm-release.zh-CN.md

Other (1) +7 / -0
release-cli-stage.ymlAdd stable-release dist-tag guidance to Stage summaries +7/-0

Add stable-release dist-tag guidance to Stage summaries

• Passes the selected release dist-tag into the summary step. Stable releases now instruct maintainers to inspect npm channels and interactively advance 'next' before Finalize when required.

.github/workflows/release-cli-stage.yml

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Missing next tag omitted 🐞 Bug ≡ Correctness
Description
Fix-now: The Stage summary tells maintainers to advance next only when it is older than latest,
omitting the absent-tag case that deterministically causes Finalize to fail. This contradicts both
the validator and the newly added runbook instructions.
Code

.github/workflows/release-cli-stage.yml[114]

+              echo "Before finalizing this stable release, inspect npm dist-tags. If \`next\` is older than \`latest\`, authenticate interactively with npm and run:"
Relevance

●●● Strong

Accepted workflow guidance should match validator and runbooks; absent next deterministically
fails Finalize.

PR-#3192

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Finalize rejects stable releases when next is not a string, while both runbooks explicitly
instruct maintainers to repair an absent or older next; only the workflow-generated guidance
narrows the condition to “older.”

scripts/release-cli-publication.mjs[42-50]
docs/cli-npm-release.md[123-135]
docs/cli-npm-release.zh-CN.md[118-130]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The generated stable-release guidance only instructs maintainers to update `next` when it is older than `latest`. Finalize also rejects a missing `next` tag, so the workflow summary must cover both conditions.

## Issue Context
The English and Chinese runbooks already use the correct “absent or older” wording. Reuse that wording rather than introducing new behavior, state, or configuration.

## Fix Focus Areas
- .github/workflows/release-cli-stage.yml[112-116]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
Review mode: ⚖️ Balanced: This changes release-channel invariants, registry validation and SemVer comparison, workflow guidance, and Finalize HTTP behavior across runtime and CI paths; it carries genuine release-contract risk, but not enough independently broad logic to justify redundant extended passes.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

echo "- version: \`$RELEASE_VERSION\`"
if [[ "$RELEASE_DIST_TAG" == "latest" ]]; then
echo
echo "Before finalizing this stable release, inspect npm dist-tags. If \`next\` is older than \`latest\`, authenticate interactively with npm and run:"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Missing next tag omitted 🐞 Bug ≡ Correctness

Fix-now: The Stage summary tells maintainers to advance next only when it is older than latest,
omitting the absent-tag case that deterministically causes Finalize to fail. This contradicts both
the validator and the newly added runbook instructions.
Agent Prompt
## Issue description
The generated stable-release guidance only instructs maintainers to update `next` when it is older than `latest`. Finalize also rejects a missing `next` tag, so the workflow summary must cover both conditions.

## Issue Context
The English and Chinese runbooks already use the correct “absent or older” wording. Reuse that wording rather than introducing new behavior, state, or configuration.

## Fix Focus Areas
- .github/workflows/release-cli-stage.yml[112-116]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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