chore(ci): Drop NPM_TOKEN in favor of npm Trusted Publishing - #9552
Conversation
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Escalating to a maintainer before this goes further — release-publishing auth is one of the areas that needs a human call, and there is also a concrete evidence problem with this PR as it stands.
The diff itself is clean: eight pure deletions removing NODE_AUTH_TOKEN from the publish steps in release.yml, release-sdk.yml, and cd-mobile-mcp.yml, and nothing else touched. The prerequisites check out too — id-token: write and npm publish --provenance are in place on all three workflows at this PR's head.
The problem is the verification. The run this PR cites as its "After" evidence — run 32338170484, dispatched from this branch at this exact head SHA — failed in Publish Release with the same error the PR is meant to fix:
npm error code E404
npm error 404 Not Found - PUT https://registry.npmjs.org/@qwen-code%2faudio-capture - Not found
Provenance signing succeeded in that run, so OIDC token issuance works — the registry rejected the publish PUT itself, exactly like the original nightly failure in #9523. Removing the token demonstrably does not restore publishing: the failure reproduces with and without NPM_TOKEN. Note the audio-capture step fails first, so the remaining packages were never even attempted.
That pattern points at the npm side rather than the workflow: the publishing identity — token or trusted publisher alike — appears to lack publish rights for @qwen-code/audio-capture (e.g. the package may never have been created on npm, or the trusted publisher is not on its allowlist). Not verified: registry state could not be queried from this review environment, so this needs confirmation by someone with npm admin access. Also worth noting that #9532 landed after the failed nightly ran, so the "token stopped working between the two runs" diagnosis in the PR body is not the only explanation consistent with the evidence.
Before merge this needs: the npm-side configuration fixed, a verification run with Publish Release green, and the "Evidence (Before & After)" section updated — it still says the outcome will be added later.
@yiliang114 Flagging for your attention as release infrastructure: the direction (OIDC Trusted Publishing over a long-lived token) is sound, but as evidenced the fix is incomplete.
中文说明
在继续深入之前先转交 maintainer 处理——发布链路的认证属于必须由人来拍板的领域,而且本 PR 目前还有一个具体的证据问题。
diff 本身是干净的:8 行纯删除,移除 release.yml、release-sdk.yml、cd-mobile-mcp.yml 各 publish 步骤中的 NODE_AUTH_TOKEN,没有其他改动。前置条件也已核实——三个 workflow 在本 PR head 上都已具备 id-token: write 和 npm publish --provenance。
问题出在验证上。本 PR 用作 "After" 证据的验证 run——run 32338170484(从本分支在该 head SHA 上 dispatch)——在 Publish Release 阶段以与本 PR 要修复的完全相同的错误失败了:
npm error code E404
npm error 404 Not Found - PUT https://registry.npmjs.org/@qwen-code%2faudio-capture - Not found
该 run 中 provenance 签名成功,说明 OIDC token 签发正常——是 registry 拒绝了 publish PUT 本身,与 #9523 中原始 nightly 的失败完全一致。也就是说,删除 token 并不能恢复发布:带不带 NPM_TOKEN,失败一模一样。另外 audio-capture 是第一个 publish 步骤,它失败后其余包根本没有被执行到。
这个模式指向 npm 侧而非 workflow:发布身份——无论是 token 还是 trusted publisher——看起来对 @qwen-code/audio-capture 都没有发布权限(例如该包可能从未在 npm 上创建,或 trusted publisher 不在其发布白名单中)。未验证:本 review 环境无法查询 registry 状态,需要有 npm 管理员权限的人确认。另外值得注意的是 #9532 是在那次失败的 nightly 之后才合入的,所以 PR 正文中"token 在两次发布之间失效"的判断并不是唯一与证据吻合的解释。
合入前需要:修复 npm 侧配置、跑出一个 Publish Release 全绿的验证 run、并更新正文中的 "Evidence (Before & After)"——目前仍写着"出结果后会更新这一行"。
@yiliang114 由于涉及发布基础设施,提请注意:方向(用 OIDC Trusted Publishing 替代长期 token)是对的,但按现有证据看,这个修复还不完整。
— Qwen Code · qwen3.8-max
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
|
Verified the final head end-to-end with Release run 32343109856:
The SDK and mobile workflows use the same pinned npm setup and are covered by the 12-package repository metadata regression check. I did not create an artificial mobile-mcp release because that workflow would promote a new stable version to |
|
All three items from the first-pass review are addressed at the current head (b414f13):
One correction to the first-pass read of the evidence: the original failing run's publish step env dump shows The intermediate run 32338170484 failure had two concrete causes, both fixed by follow-up commits on this branch: the publish runner used npm 10.9.8, which cannot do OIDC publish (requires npm ≥ 11.5.0, npm/cli#8336) — now pinned to 11.19.0 via the |
|
Re-run: the previous pass stopped at Stage 1c — release-publishing auth needs a human call, and the verification run cited back then (32338170484) had failed with the same E404. Two commits landed since (npm 11 pin, then the test), and the new verification run is green at this exact head. The escalation's concerns are resolved; resuming the full review.
Moving on to code review. 🔍 中文说明Re-run:上一轮在 Stage 1c 停下——发布链路的认证需要人来拍板,且当时引用的验证 run(32338170484)以同样的 E404 失败。此后分支上新增了两个提交(固定 npm 11、补充测试),新的验证 run 在当前 head 上全绿。上次升级提出的问题已解决,恢复完整审查。
进入代码审查。🔍 — Qwen Code · qwen3.8-max Reviewed at |
Code reviewIndependent proposal first, for this problem ("npm publish auth died mid-flight, nightly is broken"): short-term, rotate the token; structurally, move npm publishing to OIDC Trusted Publishing — Reviewed hunk by hunk against that baseline:
No critical blockers, no convention violations. Non-blocking follow-ups (all disclosed in the PR body): the Test evidenceThis is a CI-only change; the behavioral proof is the release workflow itself, which I pulled from the API rather than re-running anything:
The remaining in-progress checks are bot orchestration ( Real-scenario testing: N/A — CI-only change, nothing user-visible to drive in tmux. 中文说明代码审查先写下我的独立方案作为对照("npm 发布认证失效、nightly 已挂"):短期轮换 token;结构性方案是迁移到 OIDC Trusted Publishing—— 逐块对照 diff:
无关键阻塞项,无规范违规。 非阻塞后续(PR 正文均已披露): 测试证据纯 CI 变更,行为证据来自发布 workflow 本身(经 API 拉取,未重跑任何东西):
真实场景测试:N/A——纯 CI 变更,无用户可见行为可在 tmux 中驱动。 — Qwen Code · qwen3.8-max Reviewed at |
|
Confidence: 4/5 — a minimal, proven fix for a real production outage; the remaining nits are disclosed follow-ups, not merge blockers. Stepping back: the previous pass did exactly what the gate should — it refused to take "the run will be green" on faith when the cited run was red, and asked for a The diff matches my independent proposal for this problem exactly, and it is the minimum set: six exhaustive token removals, one npm pin, ten metadata fields, one test pinning the whole arrangement. That test is the part I'd thank the author for in six months — a new package missing its Nits, non-blocking and all disclosed in the PR body: the Approving, pinned to the reviewed commit. The prior run's request-changes review existed to force the evidence above; that condition is now met and verified. 中文说明置信度:4/5 —— 对一次真实生产故障的最小化且已证实的修复;剩余的点都是已披露的后续事项,不构成合入阻塞。 退一步看:上一轮做了门禁该做的事——在引用的 run 还是红色的时候,拒绝轻信"run 会变绿",要求一个真正发布成功的 diff 与我对该问题的独立方案完全一致,且是最小集合:6 处彻底的 token 删除、1 处 npm 固定、10 处元数据字段、1 个把整套约定固定下来的测试。这个测试是半年后会让人感谢作者的部分——新包缺 小问题,非阻塞且 PR 正文均已披露: 批准,固定到本次审查的 commit。上一轮的 request-changes review 是为了逼出上述证据;该条件现已满足并核实。 — Qwen Code · qwen3.8-max Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
|
Released in v0.21.15. |
What this PR does
This PR removes every
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}entry from the npm publish steps inrelease.yml(4 publish steps),release-sdk.yml, andcd-mobile-mcp.yml, pins npm 11.19.0 in those publish jobs, and adds therepositoryfield to the published workspace packages that were missing it. Combined with #9532 (--provenance+id-token: write), all npm publishing now authenticates through GitHub OIDC via npm Trusted Publishing instead of the long-livedNPM_TOKENsecret.✅ Verified end-to-end: the Release workflow dispatched from this branch (run 32343109856) published every package (
@qwen-code/audio-capture,@qwen-code/qwen-code,@qwen-code/channel-base, all channel packages) with tagnightlyusing no token — see+ @qwen-code/audio-capture@0.21.11-nightly.20260820.b414f135faetc. in the Publish Release logs, and thenightlydist-tag on the registry.Why it's needed
The 2026-08-20 nightly release failed on the first publish step with
npm error 404 Not Found - PUT https://registry.npmjs.org/@qwen-code%2faudio-capture(#9523, run 32317194899). A 404 on PUT for a scoped package is npm's response when the presented credentials have no publish permission for that package. The same setup had published nightlies successfully every day through 2026-08-19, and npm status reported no registry incident in that window, so the token auth itself stopped working between the two runs. Dropping token auth in favor of OIDC Trusted Publishing removes this failure mode and eliminates the long-lived secret from the release path entirely.What the investigation found
production-releaseenvironment secretNPM_TOKEN(no repo-levelNPM_TOKENsecret exists), and npm rejected it — the token's publish permission on@qwen-code/*died between 2026-08-19 02:41 UTC and 2026-08-20 01:14 UTC.Install npm 11step pinning 11.19.0), and npm Trusted Publishing requires each package'srepositoryfield to match the trusted publisher's repo (added to audio-capture and all channel packages, covered by the new package-scripts test).NODE_AUTH_TOKEN=XXXXX-...in the publish log is emitted byactions/setup-nodewhen no token is supplied; the successful run proves npm 11's OIDC path publishes fine regardless. Cleaning up that org variable is optional follow-up, not a blocker.Reviewer Test Plan
How to verify
NODE_AUTH_TOKENenv lines and adds the npm 11 pin — no other publish logic changes.npm view @qwen-code/audio-capture dist-tags.nightlyreturns0.21.11-nightly.20260820.b414f135fa(published from this branch without any token).Evidence (Before & After)
@qwen-code/audio-capturewith E404 — failed run 32317194899.0.21.11-nightly.20260820.b414f135fais live on the registry with provenance.Tested on
Environment (optional)
GitHub Actions Release workflow plus focused local workflow tests.
Risk & Scope
@qwen-code/*package; if a future package is added without it (or without therepositoryfield), its publish step will fail — the new package-scripts test pins the repository-field requirement.release-sdk.ymlandcd-mobile-mcp.ymlpublish paths got the same treatment but were not exercised by the verification run. Follow-ups: revoke/remove the now-unusedNPM_TOKENsecrets.Linked Issues
Fixes #9523
Follow-up to #9532
中文说明
这个 PR 做了什么
本 PR 删除了
release.yml(4 个 publish 步骤)、release-sdk.yml和cd-mobile-mcp.yml中所有 publish 步骤里的NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }},在这些 publish job 中固定 npm 11.19.0,并为缺少repository字段的已发布 workspace 包补上该字段。结合 #9532(--provenance+id-token: write),所有 npm 发布改为通过 npm Trusted Publishing 走 GitHub OIDC 认证,不再依赖长期NPM_TOKENsecret。✅ 已端到端验证: 从本分支 dispatch 的 Release workflow(run 32343109856)在没有任何 token 的情况下发布了全部包(
@qwen-code/audio-capture、@qwen-code/qwen-code、@qwen-code/channel-base、所有 channel 包),tag 为nightly——见 Publish Release 日志中的+ @qwen-code/audio-capture@0.21.11-nightly.20260820.b414f135fa等输出,registry 上nightlydist-tag 已指向该版本。为什么需要
2026-08-20 的 nightly 发布在第一个 publish 步骤失败:
npm error 404 Not Found - PUT https://registry.npmjs.org/@qwen-code%2faudio-capture(#9523,run 32317194899)。scoped 包 PUT 返回 404 是 npm 在"凭据没有该包发布权限"时的响应。同样的配置在 2026-08-19 之前每天的 nightly 都成功,npm 状态页该时段也没有事故,因此是 token 认证本身在两次发布之间失效了。改用 OIDC Trusted Publishing 既消除了这个故障模式,也让发布链路不再持有长期 secret。排查发现了什么
production-releaseenvironment secretNPM_TOKEN(仓库级并不存在同名 secret),npm 拒绝了它——该 token 对@qwen-code/*的发布权限在 2026-08-19 02:41 UTC 到 2026-08-20 01:14 UTC 之间失效。Install npm 11步骤固定 11.19.0 解决),以及 npm Trusted Publishing 要求每个包的repository字段与 trusted publisher 的仓库一致(已为 audio-capture 和所有 channel 包补齐,新增的 package-scripts 测试覆盖了这一要求)。NODE_AUTH_TOKEN=XXXXX-...是actions/setup-node在未提供 token 时生成的占位值;成功的 run 证明 npm 11 的 OIDC 路径在这种情况下也能正常发布。清理该 org 变量属于可选的后续动作,不是合入阻塞项。评审验证计划
如何验证
NODE_AUTH_TOKEN环境变量行并新增 npm 11 固定步骤,没有其他发布逻辑变化。npm view @qwen-code/audio-capture dist-tags.nightly返回0.21.11-nightly.20260820.b414f135fa(从本分支无 token 发布)。前后对比证据
@qwen-code/audio-capture处以 E404 失败 —— 失败的 run 32317194899。0.21.11-nightly.20260820.b414f135fa已带 provenance 上线 registry。测试环境
环境说明(可选)
GitHub Actions Release workflow,加聚焦的本地 workflow 测试。
风险与范围
@qwen-code/*包配置的 trusted publisher;未来新增包如果没配置(或缺repository字段),其 publish 步骤会失败——新增的 package-scripts 测试固定了 repository 字段要求。release-sdk.yml和cd-mobile-mcp.yml的发布路径做了同样处理,但未被验证 run 覆盖。后续动作:吊销/删除不再使用的NPM_TOKENsecret。关联 Issue
Fixes #9523
#9532 的后续