Skip to content

fix(release): stop cancelling a slow-but-live workspace test shard (#10891) - #10901

Closed
qwen-code-dev-bot wants to merge 2 commits into
mainfrom
autofix/issue-10891
Closed

fix(release): stop cancelling a slow-but-live workspace test shard (#10891)#10901
qwen-code-dev-bot wants to merge 2 commits into
mainfrom
autofix/issue-10891

Conversation

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

What this PR does

Raises the job budget the release lane gives each workspace test shard, from 45 minutes to 90, and updates the test that pins the release job budgets so the new number has a witness.

Why it's needed

The v0.23.0 release run failed its quality gate four times across four and a half hours and never published. One of those attempts died with both test shards still running when the job cap cancelled them — GitHub's own annotation for each reads "The job has exceeded the maximum execution time of 45m0s". The cap had become smaller than the work it bounds: in the same run, a shard that passed spent 41m32s in its test step out of the roughly 42 minutes the cap left after setup, so a healthy shard consumes almost the whole budget and any extra host slowness turns a live run into a cancellation instead of a verdict.

The lane also retries every failed test twice, which adds time on top of an already slow shard. The main CI lane had its equivalent cap resized for exactly this arithmetic — its comment records that a cap "has to clear the slowest honest run, not the healthy one" and that "a failing run adds its retries on top" — but the release shard cap kept the value it had before retries were added to that lane.

Release validation is pinned to one host whose CPUs are shared with PR CI, which the workflow already documents. Until infra makes that host release-only (tracked separately), the shard budget has to fit the contended reality rather than an idle one.

Reviewer Test Plan

How to verify

The change is a CI budget, so the observable behaviour is in the workflow file and its pinning test rather than in the CLI.

  1. Read the workspace_tests job in the release workflow and confirm the cap is now 90 minutes and that the comment states the measurement it was sized from.
  2. Run the release workflow test suite and confirm the budget map pins 90 for that job:
    npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/release-workflow.test.js — expect 46 passed.
  3. Confirm the pin is load-bearing rather than decorative: set the job's cap back to 45 in the workflow, re-run that suite, and expect bounds shared-pool jobs and skips redundant remote npm caches to fail on the workspace_tests entry. Restore 90 and expect green again. This was done for this PR and the results are in the verification report.
  4. The end-to-end confirmation is the next scheduled release: a shard that runs long should now finish and report a verdict rather than being cancelled at 45 minutes.

Evidence (Before & After)

N/A — CI workflow budget change with no user-visible surface.

Before: workspace_tests job cap timeout-minutes: 45; a shard whose test step needed 43m15s was cancelled mid-run with the annotation "The job has exceeded the maximum execution time of 45m0s".

After: workspace_tests job cap timeout-minutes: 90; the measured worst honest shard (43m15s, still live when killed) plus its --retry=2 re-runs fits inside the budget.

Tested on

OS Status
🍏 macOS ⚠️ not tested
🪟 Windows ⚠️ not tested
🐧 Linux ✅ tested

Environment (optional)

N/A — workflow YAML and its unit test only; no CLI runtime involved.

Risk & Scope

  • Main risk or tradeoff: a genuinely hung shard now occupies the release lane for up to 90 minutes instead of 45 before it is cancelled, so a real hang takes longer to surface. Healthy runs and fast failures are unaffected — the cap only bounds the worst case, it does not add work.
  • Not validated / out of scope: the release workflow cannot be re-run from a fix branch, so the definitive confirmation is the next release run. Also out of scope: the host contention that makes a third of the suite take 40+ minutes (tracked separately as an infra issue), and the two flaky tests responsible for this run's other three attempts, both of which were already fixed on main before this branch and are verified green here.
  • Breaking changes / migration notes: none. Operators who want a different budget can still bound the lane through the existing repository variables; this only changes the default ceiling.

Linked Issues

Fixes #10891

The same failing run also opened #10875, #10876 and #10881 for its earlier attempts; they are duplicates of this one and can be closed when this lands.

Related, not closed by this PR: #10879 (the release host still carries the shared pool label, which is why shards run long), #10868 (sized the main CI unit lane's cap with the same reasoning), #10842 (added the retry this cap now has to absorb).

中文说明

这个 PR 做了什么

把发布流水线给每个 workspace 测试分片的作业预算从 45 分钟提高到 90 分钟,并同步更新那个固定发布作业预算的测试,让新数值有测试作为见证。

为什么需要

v0.23.0 的发布运行在四个半小时里连续四次未通过质量门禁,最终没有发布。其中一次尝试是在两个测试分片仍在运行时被作业上限取消的——GitHub 对每个分片给出的注解都是 "The job has exceeded the maximum execution time of 45m0s"。这个上限已经小于它要约束的实际工作量:在同一次运行里,一个通过的分片,其测试步骤耗时 41 分 32 秒,而扣除环境准备后上限只留给它约 42 分钟。也就是说健康的分片几乎用尽全部预算,主机稍微更慢一点,就会把一个仍在正常执行的运行变成"被取消",而不是给出结论。

该流水线还会对每个失败用例重试两次,这会在本已很慢的分片上继续叠加时间。主 CI 流水线已经按完全相同的算法调整过它的对应上限——其注释明确写着上限"必须容纳最慢的正常运行,而不是健康的运行",并且"失败的运行会把重试时间叠加上去"——但发布分片的上限仍停留在该流水线引入重试之前的数值。

发布验证被固定在单台主机上,而这台主机的 CPU 与 PR CI 共享,工作流里对此已有说明。在基础设施把该主机改为发布专用之前(另有 issue 跟踪),分片预算必须适配真实的资源竞争状况,而不是空闲状态下的状况。

审阅测试计划

如何验证

这是一个 CI 预算改动,因此可观察的行为体现在工作流文件和它的固定测试里,而不是 CLI 上。

  1. 阅读发布工作流中的 workspace_tests 作业,确认上限现在是 90 分钟,且注释写明了该数值依据的实测数据。
  2. 运行发布工作流测试套件,确认预算映射把该作业固定为 90:
    npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/release-workflow.test.js —— 预期 46 个测试通过。
  3. 确认这个固定值是真的起作用、而不是装饰性的:把工作流里该作业的上限改回 45,重新运行该套件,预期 bounds shared-pool jobs and skips redundant remote npm caches 会在 workspace_tests 这一项上失败;改回 90 后预期重新全绿。本 PR 已实际执行过这一变异验证,结果记录在验证报告中。
  4. 端到端的确认来自下一次定时发布:一个运行较久的分片现在应当跑完并给出结论,而不是在 45 分钟时被取消。

证据(改动前后)

N/A —— 这是 CI 工作流预算改动,没有用户可见界面。

改动前:workspace_tests 作业上限为 timeout-minutes: 45;一个测试步骤需要 43 分 15 秒的分片在运行中被取消,注解为 "The job has exceeded the maximum execution time of 45m0s"。

改动后:workspace_tests 作业上限为 timeout-minutes: 90;实测最慢的正常分片(43 分 15 秒,被杀掉时仍在运行)加上它的 --retry=2 重试,都能容纳在这个预算之内。

测试环境

操作系统 状态
🍏 macOS ⚠️ 未测试
🪟 Windows ⚠️ 未测试
🐧 Linux ✅ 已测试

环境(可选)

N/A —— 只涉及工作流 YAML 及其单元测试,不涉及 CLI 运行时。

风险与范围

  • 主要风险或取舍:真正卡死的分片现在会占用发布流水线最多 90 分钟而不是 45 分钟才被取消,因此真实的挂起需要更长时间才会暴露。健康的运行和快速失败不受影响——上限只约束最坏情况,并不会增加任何工作量。
  • 未验证 / 范围之外:修复分支无法重新触发发布工作流,因此最终确认要看下一次发布运行。同样在范围之外:导致三分之一测试套件耗时 40 分钟以上的主机资源竞争(已作为基础设施 issue 单独跟踪),以及导致该运行另外三次尝试失败的两个不稳定测试——它们在本分支创建前就已在 main 上修复,并已在此处验证为通过。
  • 破坏性变更 / 迁移说明:无。如果运维希望使用不同的预算,仍可通过现有的仓库变量来约束该流水线;本次改动只调整默认上限。

关联 Issue

Fixes #10891

同一次失败的运行还为它更早的几次尝试开了 #10875#10876#10881;它们是本 issue 的重复项,本 PR 合并后可以关闭。

相关但不被本 PR 关闭:#10879(发布主机仍带有共享池标签,这正是分片运行缓慢的原因)、#10868(用相同的推理调整了主 CI 单元流水线的上限)、#10842(引入了本上限现在必须容纳的重试)。

…10891)

Release run 33713579913 failed its quality gate four times in four and a
half hours and never published. Attempt 3 lost both workspace test shards
to the job cap: each carries the annotation "The job has exceeded the
maximum execution time of 45m0s" and their steps had run 43m05s and
43m15s, still live. The cap had become smaller than the work it bounds —
in the same run a shard that passed spent 41m32s in its test step out of
the ~42m the cap left after setup.

The lane also retries every failed test twice (#10842), which adds time
on top of an already slow shard. #10868 resized the CI unit lane's step
cap for exactly that arithmetic, recording that a cap "has to clear the
slowest honest run, not the healthy one"; the release shard cap kept its
pre-retry value. 90 is about twice the measured worst honest step, leaves
room for those retries, and matches the publish job's existing ceiling.

The other three attempts failed on tests rather than the cap. Both causes
were already fixed on main before this branch and are verified green
here: ledger entries stamped at collection time (0e3094e, whose own
message names this run) and the exhaustive UTF-16 byte-estimate sweep
(19182d0). Neither fix could reach attempts 2-4, because the lane
validates the SHA prepare pinned when the run started.
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator Author

Autofix report — issue #10891 (Release Failed for v0.23.0)

What the issue reported

Release workflow run 33713579913 for tag v0.23.0 failed and the notification named one job: quality. That job is only an aggregator — it fails closed when any of its five components does not report success, so the name in the issue does not identify the real failure.

Job logs are not readable without repository admin rights (the log endpoint returns HTTP 403 Must have admin rights to Repository.), so the diagnosis below was built from the public jobs and check-run annotations APIs, the repository's own commit history, and local reproduction.

What actually failed, per attempt

All four attempts validated the same pinned SHA (035418958d), because the release lane checks out the SHA prepare resolved when the run started — so fixes landing on main afterwards could never reach a re-run.

Attempt Window (UTC) Result
1 04:34–05:20 Workspace Tests (3/3) failure; test step ran 41m28s, exit code 1. Shards 1/3 and 2/3 cancelled when the attempt was superseded.
2 05:23–06:08 Workspace Tests (3/3) failure; step 40m09s, exit 1. Shard 1/3 success with a step of 41m32s. Shard 2/3 cancelled.
3 06:27–07:13 Both shards 2/3 and 3/3 cancelled. Annotation on each: The job has exceeded the maximum execution time of 45m0s + The operation was canceled. Their steps had run 43m05s / 43m15s and were still live.
4 07:54–08:38 Shards 2/3 and 3/3 failure, steps ~40m, exit 1. This attempt filed #10891.

Quality Checks (Static), (Build), (Typecheck), (Scripts) and both integration suites were green throughout.

Three distinct causes, and their status at HEAD

1. Shard 3/3 exit 1 (attempts 1, 2, 4) — already fixed on main.
The failing test is packages/cli/src/commands/review/lib/run-ledger.test.ts, confirmed locally to fall in packages/cli shard 3/3. Its ledger entries were stamped from a Date.now() evaluated in the describe body — at collection — while beforeEach writes the plan file at execution; entries are fenced against that file's mtime with 2s of slack, so a long collection makes the stamps stale and the fence drops them. Commit 0e3094ebf6 fixed this, and its own message names this exact run: "the same 1/0/0 the three attempts of release run 33713579913 read after collecting for 2260s". Verified green here: 72/72.

2. Shard 2/3 exit 1 (attempt 4) — already fixed on main.
packages/acp-bridge/src/json-string-bytes.test.ts, confirmed locally to fall in acp-bridge shard 2/3. Commit 19182d08ab deflaked its 65,536-iteration sweep, which "spent almost all of its wall time in per-iteration expect() overhead, which made it flaky under runner contention". Verified green here: acp-bridge shard 2/3, 12 files, 394/394.

3. Attempt 3 — the 45-minute job cap killed two shards that were still running. Still open at HEAD. This is what the PR fixes.
The cap had become smaller than the work it bounds: a shard that passed consumed 41m32s of the roughly 42 minutes left after setup, so a healthy shard used ~98% of its budget and any extra host slowness turned a live run into a cancellation rather than a verdict. The lane also retries every failed test twice (--retry=2, added by #10842), which adds time on top. #10868 — the very commit this release was cut from — resized the main CI lane's equivalent cap from 90 to 110 minutes for exactly this arithmetic, recording that a cap "has to clear the slowest honest run, not the healthy one" and that "a failing run adds its retries on top"; the release shard cap kept its pre-retry value.

The change

workspace_tests.timeout-minutes goes from 45 to 90, with a comment recording the measurement it was sized from, and the pinned budget map in scripts/tests/release-workflow.test.js is updated with the same reason so the number has a witness.

90 is roughly twice the measured worst honest step (43m15s, killed while still live) which leaves room for the retries, and it matches the ceiling the publish job in the same workflow already uses. No sibling budget changes.

Not addressed (out of scope)

Verification

  • npm run build — passed (exit 0)
  • npm run typecheck — passed (exit 0)
  • npm run lint — passed (exit 0)
  • npx prettier --check .github/workflows/release.yml scripts/tests/release-workflow.test.js — passed ("All matched files use Prettier code style!")
  • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/release-workflow.test.js — 46 passed (46), re-run on the final tree
  • Mutation probe (confirms the new pin is load-bearing): reverted the cap to 45 in the workflow → release-workflow.test.js failed, 1 failed | 45 passed, on bounds shared-pool jobs and skips redundant remote npm caches with diff - "workspace_tests": 90 / + "workspace_tests": 45; restored 90 → 46 passed.
  • YAML re-parsed after the edit: workspace_tests=90; siblings unchanged (quality_build=45, quality_typecheck=30, quality_scripts=30, quality=5, publish=90, integration_none=120).
  • Already-fixed causes re-verified green at HEAD: packages/cli run-ledger.test.ts — 72 passed; packages/acp-bridge shard 2/3 — 394 passed.
  • npm run test:scripts (full scripts suite) — 6 failed | 2100 passed | 16 skipped on this runner, and the same totals on base with my change stashed (6 failed | 2100 passed | 16 skipped), with a partly different set of tests each time, every one failing at ~31–40s against this suite's 30s testTimeout. This host has 64 cores and the scripts vitest config deliberately scales workers to host cores, so these subprocess-driving tests oversubscribe and time out; the failing set changes run to run. The release lane's own Quality Checks (Scripts) job was success in all four attempts of run 33713579913, so the suite is green in CI. Not caused by this change — proven by the identical base run.
  • An earlier unbounded local run of workspace shard 3/3 reported 17 failures; re-running the four affected files under release-equivalent settings (RUNNER_NAME=ecs-qwen-*, VITEST_MAX_THREADS=4) gave 161 passed, confirming those were parallelism artifacts of this box rather than defects. One further failure, verify-capture.test.js > renders 256-colour and truecolor via the default-grey fallback, is a host-specific rendering flake: on an identical tree it passed once and failed twice, and it passed on base. It has no code path to either changed file.
  • Not applicable: the bundled-CLI integration suites. The change is a CI job budget in a workflow file; no CLI behaviour is exercised through the bundle or the integration harness, so npm run bundle plus an integration run could not cover it.
  • Not run: the release workflow itself. It cannot be triggered from a fix branch, so the end-to-end confirmation is the next scheduled release — a long shard should now finish and report a verdict instead of being cancelled at 45 minutes.
中文说明

Autofix 报告 —— issue #10891(v0.23.0 发布失败)

issue 报告的内容

发布工作流运行 33713579913(标签 v0.23.0)失败,通知里只写了一个作业名:quality。这个作业只是聚合器——当它的五个组成作业中有任何一个不是 success 时它就 fail closed,所以 issue 里的这个名字并没有指出真正的失败点。

作业日志在没有仓库管理员权限时无法读取(日志接口返回 HTTP 403 Must have admin rights to Repository.),因此下面的诊断是通过公开的 jobs / check-run annotations 接口、仓库自身的提交历史,以及本地复现得出的。

每次尝试实际失败的情况

四次尝试校验的都是同一个固定的 SHA(035418958d),因为发布流水线 checkout 的是 prepare 在运行开始时解析出的 SHA——所以之后合并到 main 上的修复永远无法到达重跑的尝试。

尝试 时间窗口(UTC) 结果
1 04:34–05:20 Workspace Tests (3/3) failure;测试步骤运行 41 分 28 秒,退出码 1。分片 1/3 与 2/3 在本次尝试被取代时取消。
2 05:23–06:08 Workspace Tests (3/3) failure;步骤 40 分 09 秒,退出码 1。分片 1/3 成功,其步骤耗时 41 分 32 秒。分片 2/3 取消。
3 06:27–07:13 分片 2/3 与 3/3 双双被取消。两者的注解都是:The job has exceeded the maximum execution time of 45m0s + The operation was canceled.,而它们的步骤已经运行了 43 分 05 秒 / 43 分 15 秒,且仍在执行中。
4 07:54–08:38 分片 2/3 与 3/3 failure,步骤约 40 分钟,退出码 1。本次尝试创建了 #10891

Quality Checks (Static)(Build)(Typecheck)(Scripts) 以及两个集成测试套件全程为绿。

三个不同的成因,以及它们在当前 HEAD 上的状态

1. 分片 3/3 退出码 1(尝试 1、2、4)—— 已在 main 上修复。
失败的测试是 packages/cli/src/commands/review/lib/run-ledger.test.ts,本地已确认它落在 packages/cli 的 3/3 分片里。它的账目条目是在 describe 体里(也就是收集阶段)用 Date.now() 打的时间戳,而 beforeEach 是在执行阶段才写入 plan 文件;条目会以该文件的 mtime 为界、只留 2 秒余量,因此收集耗时一长,时间戳就过期,围栏会把这些条目当作上一次运行的而丢弃。提交 0e3094ebf6 修复了它,而且该提交的说明正是点名了这次运行:"the same 1/0/0 the three attempts of release run 33713579913 read after collecting for 2260s"。此处已验证通过:72/72。

2. 分片 2/3 退出码 1(尝试 4)—— 已在 main 上修复。
packages/acp-bridge/src/json-string-bytes.test.ts,本地已确认它落在 acp-bridge 的 2/3 分片里。提交 19182d08ab 修复了它那个 65,536 次迭代的全量扫描,原因是*"几乎全部墙上时间都花在每次迭代的 expect() 开销上,这使它在 runner 资源竞争下变得不稳定"*。此处已验证通过:acp-bridge 2/3 分片,12 个文件,394/394。

3. 尝试 3 —— 45 分钟的作业上限杀掉了两个仍在运行的分片。在当前 HEAD 上仍未解决,这正是本 PR 修复的内容。
这个上限已经小于它要约束的工作量:一个通过的分片,在扣除环境准备后剩下的约 42 分钟里用掉了 41 分 32 秒,也就是说健康的分片消耗了约 98% 的预算,主机再慢一点,就会把一个仍在正常执行的运行变成"被取消",而不是给出结论。该流水线还会对每个失败用例重试两次(--retry=2,由 #10842 引入),这会在此之上继续叠加时间。#10868——也就是本次发布所基于的那个提交——已经按完全相同的算法把主 CI 流水线的对应上限从 90 分钟调整到 110 分钟,并在注释中写明上限*"必须容纳最慢的正常运行,而不是健康的运行""失败的运行会把重试时间叠加上去"*;而发布分片的上限仍停留在引入重试之前的数值。

本次改动

workspace_tests.timeout-minutes 从 45 提升到 90,并附上记录该数值实测依据的注释;同时更新 scripts/tests/release-workflow.test.js 中固定的预算映射表,并写明同样的理由,使这个数字有测试作为见证。

90 大约是实测最慢正常运行步骤(43 分 15 秒,被杀掉时仍在运行)的两倍,为重试留出了空间,也与同一工作流里 publish 作业已使用的上限一致。其他作业的预算都没有改动。

未处理(范围之外)

验证

  • npm run build —— 通过(退出码 0)
  • npm run typecheck —— 通过(退出码 0)
  • npm run lint —— 通过(退出码 0)
  • npx prettier --check .github/workflows/release.yml scripts/tests/release-workflow.test.js —— 通过("All matched files use Prettier code style!")
  • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/release-workflow.test.js —— 46 个测试通过(46),已在最终代码树上重跑
  • 变异验证(确认新增的固定值真的起作用):把工作流里的上限改回 45 → release-workflow.test.js 失败1 failed | 45 passed,失败用例为 bounds shared-pool jobs and skips redundant remote npm caches,差异为 - "workspace_tests": 90 / + "workspace_tests": 45;改回 90 → 46 个通过。
  • 编辑后重新解析 YAML:workspace_tests=90;同级作业未变(quality_build=45quality_typecheck=30quality_scripts=30quality=5publish=90integration_none=120)。
  • 已修复的成因在当前 HEAD 上重新验证为通过:packages/clirun-ledger.test.ts —— 72 个通过;packages/acp-bridge 2/3 分片 —— 394 个通过。
  • npm run test:scripts(完整 scripts 套件)—— 在本机为 6 failed | 2100 passed | 16 skipped,而把我的改动 stash 掉后在 base 上运行结果完全相同(6 failed | 2100 passed | 16 skipped),且每次失败的用例集合部分不同,每个失败都发生在约 31–40 秒、正好撞上该套件的 30 秒 testTimeout。本机有 64 核,而 scripts 的 vitest 配置刻意让 worker 数随主机核数伸缩,因此这些会派生子进程的测试超额占用 CPU 并超时;失败集合每次运行都在变。发布流水线自己的 Quality Checks (Scripts) 作业在运行 33713579913 的全部四次尝试中都是 success,说明该套件在 CI 中是绿的。这不是本次改动造成的——已通过在 base 上运行相同命令证明。
  • 更早一次未限制并发度的本地 workspace 3/3 分片运行报告了 17 个失败;用与发布流水线等价的设置(RUNNER_NAME=ecs-qwen-*VITEST_MAX_THREADS=4)重跑其中受影响的四个文件后为 161 个通过,确认那些是本机并发度造成的假象而非缺陷。另有一个失败 verify-capture.test.js > renders 256-colour and truecolor via the default-grey fallback 属于本机特有的渲染不稳定:在完全相同的代码树上它通过一次、失败两次,并且在 base 上通过。它与两个被改动的文件之间不存在任何代码路径关联。
  • 不适用:打包后 CLI 的集成测试套件。本次改动是工作流文件里的一个 CI 作业预算,没有任何 CLI 行为会通过打包产物或集成测试框架被执行,因此 npm run bundle 加集成测试也无法覆盖它。
  • 未运行:发布工作流本身。修复分支无法触发它,因此端到端的确认要看下一次定时发布——一个运行较久的分片现在应当跑完并给出结论,而不是在 45 分钟时被取消。

🧠 Handled by Qwen Code · model/模型 qwen3.8-max-2026-09-02

@qwen-code-ci-bot

qwen-code-ci-bot commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Qwen Triage finishedview run. See the stage comments in this thread for the result.

Qwen Triage 已完成 —— 查看运行。结果见本线程中的各阶段评论。

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

Problem: observed, not theoretical. The v0.23.0 release run (33713579913) failed four attempts across four and a half hours; GitHub's annotation on the cancelled shards reads "The job has exceeded the maximum execution time of 45m0s", and in the same run a passing shard's test step spent 41m32s of the ~42m the cap left after setup. Linked issue #10891 documents it. The problem is real.

Direction: aligned. The release lane's job cap had become smaller than the work it bounds, and the main CI lane's equivalent cap was resized for exactly this arithmetic in #10868. This is release-infrastructure plumbing with clear precedent, not a product-direction question.

Size: not applicable — no core paths. 8 lines of workflow YAML plus 5 lines in its pinning test.

Approach: minimal and focused — raise the cap from 45 to 90 and update the test that pins the release budgets, with the sizing measurement recorded in comments next to both values. No drive-by changes.

One substantial caveat before we go deeper: main has moved past this branch. #10870 (merged today ~09:50 UTC, after this branch was cut) already reworks this exact line — the cap is now vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES || '45', a repository variable currently set to 75, pinned by a dedicated test that asserts the tunable form ("lets an operator retune the workspace shard timeout without a PR"). GitHub already reports this PR as CONFLICTING. So the question this review has to answer is not "is 90 right?" but "what, if anything, survives a rebase onto the tunable design?"

Risk: no elevated risk signals (no high-risk path match; the change is CI config and its test).

Moving on to code review, with the staleness front and center. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题:已观测到的真实问题,不是理论性加固。v0.23.0 的发布运行(33713579913)在四个半小时里四次尝试均失败;GitHub 对被取消分片的注解是 "The job has exceeded the maximum execution time of 45m0s",且同一次运行中一个通过的分片,其测试步骤用掉了上限扣除环境准备后约 42 分钟里的 41 分 32 秒。关联 issue #10891 有完整记录。

方向:对齐。发布流水线的作业上限已经小于它要约束的工作量,主 CI 流水线的对应上限已在 #10868 按完全相同的算法调整过。这是有明确先例的发布基础设施调整,不是产品方向问题。

规模:不适用——未触及核心路径。共 8 行工作流 YAML 和 5 行固定测试。

方案:最小且聚焦——把上限从 45 提到 90,同步更新固定发布预算的测试,并在两处数值旁记录了定标依据的实测数据。没有夹带无关改动。

但在深入之前有一个重要情况:main 已经走到了这个分支前面。 #10870(今天约 09:50 UTC 合并,晚于本分支切出)已经重写了同一行——上限现在是 vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES || '45',即一个当前设为 75 的仓库变量,并有专门测试固定这个可调形式("lets an operator retune the workspace shard timeout without a PR")。GitHub 已把本 PR 标记为 CONFLICTING。因此这次 review 要回答的问题不是"90 对不对",而是"rebase 到可调设计之后,这个 PR 还剩下什么"。

风险:无升级风险信号(未命中高风险路径;改动为 CI 配置及其测试)。

进入代码审查,重点看分支过期的问题。🔍

Qwen Code · qwen3.8-max

Reviewed at 3f77db62580782631c7878278ad003e8fbb67882 · re-run with @qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Code review

Read against the stated problem (release lane cancelling slow-but-live shards at the 45-minute cap), my own proposal would have been exactly what this PR does: raise the job cap to clear the worst observed shard plus its --retry=2 re-runs, update the test that pins the budget map, and record the measurement beside both values. As far as it goes, the diff is clean — two hunks, no churn, comments that carry the sizing arithmetic (run 33713579913, the 41m32s passing shard, the retry stacking), consistent with how #10868 documented the same change on the CI lane. No correctness or security concerns in isolation.

The problem is the base, not the code. Both hunks collide with #10870, which merged to main after this branch was cut:

  • .github/workflows/release.yml — main now reads timeout-minutes: "${{ fromJSON(vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES || '45') }}". This PR edits a literal timeout-minutes: 45 that no longer exists. Resolving the conflict in this PR's favor would delete the operator-tunable knob and its fail-fallback default — i.e. revert test: stop millisecond budgets from measuring the shared pool #10870's design.
  • scripts/tests/release-workflow.test.js — main's budget map now pins the fromJSON expression for workspace_tests ("The one bound an operator can retune without a PR"), and a dedicated test pins the same tunable form. The PR's workspace_tests: 90 conflicts with both pins.

GitHub reports the PR as CONFLICTING, which matches the reading above. The reuse-before-new-code question answers itself: the mechanism this PR needs already exists on main — the QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES variable, currently set to 75.

Testing

Evidence for this section comes from the PR's own CI via the API; per review rules I do not run PR code myself.

Check Conclusion
assign success
label success
triage in progress
review-pr in progress

There are no pull_request-event CI runs on this commit — no unit, lint, or build signal exists on this head. Every check present is a pull_request_target orchestration job (assign/label succeeded; triage and review-pr are this review itself). Whether that's workflow-approval gating or the bot push not triggering CI, a rebase onto current main would surface the full suite.

Not verified: the pinning suite (scripts/tests/release-workflow.test.js) — static review only; CI rules prohibit running PR code. Also not verifiable from any lane: the end-to-end claim (a long shard finishing instead of being cancelled) — the release workflow cannot be re-run from a fix branch, as the PR itself notes. This is CI-workflow configuration, not a product behaviour change, so no sandbox lane (/verify / /tmux) would settle it; the next scheduled release run is the only real confirmation.

中文说明

代码审查

对照所声明的问题(发布流水线在 45 分钟上限处取消"慢但仍存活"的分片),我自己的方案与这个 PR 完全一致:提高作业上限以容纳实测最慢分片加上 --retry=2 的重试,更新固定预算映射的测试,并在两处数值旁记录实测数据。就改动本身而言是干净的——两个 hunk、无杂项改动,注释写明了定标算术(run 33713579913、通过的 41 分 32 秒分片、重试叠加),与 #10868 在主 CI 流水线上的注释风格一致。孤立地看没有正确性或安全问题。

问题在基线,不在代码。两个 hunk 都与 #10870 冲突——该 PR 在本分支切出之后已合并进 main:

  • .github/workflows/release.yml——main 上这一行现在是 timeout-minutes: "${{ fromJSON(vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES || '45') }}"。本 PR 修改的 timeout-minutes: 45 字面量已不存在;若按本 PR 的方向解决冲突,会删掉这个运维可调旋钮及其默认回退——即回退 test: stop millisecond budgets from measuring the shared pool #10870 的设计。
  • scripts/tests/release-workflow.test.js——main 的预算映射现在把 workspace_tests 固定为 fromJSON 表达式("唯一一个运维无需 PR 即可调整的约束"),且另有专门测试固定同一可调形式。本 PR 的 workspace_tests: 90 与这两处固定都冲突。

GitHub 已将本 PR 标记为 CONFLICTING,与上述判断一致。"先复用再新写"的问题也有了答案:本 PR 需要的机制 main 上已经存在——QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES 变量,当前值为 75。

测试

本节证据来自 PR 自身的 CI(通过 API 获取);按审查规则,我不运行 PR 代码。

该提交上没有任何 pull_request 事件的 CI 运行——此 head 上不存在单元、lint 或构建信号。现存的所有检查都是 pull_request_target 编排作业(assign/label 成功;triage 与 review-pr 即本次审查本身)。无论原因是工作流等待批准,还是机器人推送未触发 CI,rebase 到当前 main 后完整套件才会出现。

未验证:固定测试套件(scripts/tests/release-workflow.test.js)——仅静态审查;CI 规则禁止运行 PR 代码。同样无法在任何通道验证:端到端结论(长分片跑完而不是被取消)——发布工作流无法从修复分支重跑,PR 本身也承认这一点。这是 CI 工作流配置而非产品行为变更,沙箱通道(/verify / /tmux)无法定论;下一次定时发布运行才是唯一真实确认。

Qwen Code · qwen3.8-max

Reviewed at 3f77db62580782631c7878278ad003e8fbb67882 · re-run with @qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Confidence: 2/5 — the change is well-crafted and the problem was real, but it has been overtaken: main already fixes the same cancellation with a better mechanism, and this PR now conflicts with it.

Stepping back: my independent proposal for this bug was exactly what this PR does — raise the cap to clear the worst observed shard plus its retries, and pin the number. But #10870, which landed on main shortly before this PR was opened, goes one step further: the cap is now a repository variable (QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES, currently 75), precisely because shard runtime tracks how busy the shared release host is — 6.7 minutes quiet, 36 contended, in the same third — and a hardcoded literal costs a review every time the fleet moves. The merged test even names the intent: "lets an operator retune the workspace shard timeout without a PR".

Rebasing would not reduce this PR to a delta — both hunks argue against the shipped design, and resolving them in this PR's favor would revert the tunable knob, its fail-fallback default, and its two test pins. So there is nothing to merge: the problem (#10891) is addressed by #10870, and the one remaining question — whether the cap should be 90 rather than 75 — is by design a variable tweak, not a code change. If the next release run still dies at the cap, bump QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES; that is the shipped escape hatch, and it takes effect without waiting on a PR. The earlier attempts' issues mentioned in the description (#10875, #10876, #10881) are likely closable for the same reason.

Requesting changes: please rebase onto current main; if nothing of this diff survives the rebase — as expected — close in favor of #10870. @qwen-code-dev-bot

中文说明

置信度:2/5 —— 改动本身写得很好,问题也确实存在,但它已被抢先:main 已经用更好的机制修复了同样的取消问题,而本 PR 现在与之冲突。

退一步看:我对这个 bug 的独立方案与本 PR 完全一致——提高上限以容纳最慢的正常运行分片加重试,并固定该数值。但在本 PR 提交前不久合入 main 的 #10870 更进一步:上限现在是一个仓库变量(QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES,当前值 75)——原因正是分片运行时长跟随共享发布主机的繁忙程度(同一个三分之一分片在空闲时 6.7 分钟、资源竞争时 36 分钟),而硬编码的字面量每次主机状况变化都要消耗一次 review。合并的测试甚至直接命名了这个意图:"lets an operator retune the workspace shard timeout without a PR"。

rebase 也不会让本 PR 缩减出增量——两个 hunk 都与已落地的设计相抵触;若按本 PR 的方向解决冲突,会回退可调旋钮、其默认回退以及两处测试固定。因此没有可合并的内容:问题(#10891)已由 #10870 解决,唯一遗留的问题——上限该是 90 还是 75——按设计是调整变量,不是代码改动。如果下一次发布仍然在上限处被取消,调高 QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES 即可:这是已落地的应急通道,无需等一个 PR。描述中提到的更早几次尝试的 issue(#10875#10876#10881)大概率也可以据此关闭。

请求修改:请 rebase 到当前 main;如果 rebase 后本 diff 没有剩余内容(预期如此),请关闭并让位给 #10870@qwen-code-dev-bot

Qwen Code · qwen3.8-max

Reviewed at 3f77db62580782631c7878278ad003e8fbb67882 · re-run with @qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Superseded: #10870 (merged) already made this cap an operator-tunable repository variable (QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES, currently 75), and this PR conflicts with main on exactly those lines. Please rebase onto current main; if nothing of the diff survives — as expected — close in favor of #10870. See my notes above. 🙏

已被取代:#10870(已合并)已把该上限改为运维可调的仓库变量(QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES,当前值 75),本 PR 与 main 在这几行上冲突。请 rebase 到当前 main;若 rebase 后无剩余内容(预期如此),请关闭并让位给 #10870。详见上方审查记录。🙏

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No issues found. LGTM! ✅

Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/release.yml: actionlint embedded-shell source mapping is not yet supported — not linted.

中文说明

未发现问题。LGTM!✅

未检查(工具限制,非阻断):the executable-script lint — .github/workflows/release.yml: actionlint embedded-shell source mapping is not yet supported — not linted。

— qwen3.8-max via Qwen Code /review (v0.22.3)

@wenshao

wenshao commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

@qwen-code /resolve

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator Author

🐑 Merge conflict with main detected — dispatched the autofix loop to resolve it. / 检测到与 main 的合并冲突,已触发 autofix 处理。

@qwen-code-dev-bot

qwen-code-dev-bot commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

AutoFix round 1 finishedview run. See this round's report below.

中文说明

AutoFix 第 1 轮已完成 —— 查看运行。本轮报告见下方。

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator Author

Qwen Code resolved the merge conflicts and pushed the branch update.

Merge conflict resolution — PR #10901

Root cause. Both sides react to the same incident (release run 33713579913, workspace shards cancelled while still live). This PR bumped workspace_tests.timeout-minutes in .github/workflows/release.yml from 45 to a hard-coded 90. On main, 5e367dad15 (#10805) rewrote the same line into an operator-retunable knob: "${{ fromJSON(vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES || '45') }}", plus tests pinning that literal. Both changed the same line — a semantic conflict, not adjacency.

Resolution. Keep main's mechanism, carry this PR's bump into its fallback default:

timeout-minutes: "${{ fromJSON(vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES || '90') }}"

The '45''90' change appears in three places: the workflow line above, the timeout map in scripts/tests/release-workflow.test.js (bounds shared-pool jobs…), and — one non-conflicted hunk inside that same conflicted file — the toContain literal in the test lets an operator retune the workspace shard timeout without a PR, which asserts the exact raw workflow line and would otherwise have failed against its own merge. Both comments were merged: main's "why a variable" plus this PR's "why 90" arithmetic (41m32s worst measured step + --retry=2).

What is load-bearing.

  1. The default lives inside fromJSON(... || '90'); timeout-minutes needs a number and an unset var must fall back, so the fromJSON wrapper and the double-quoted YAML string must stay exactly as-is (main's pinning test checks both).
  2. Three sites must agree on the default: the workflow line, the toContain literal (~line 633), and the bounds-map value (~line 1445). A future retune that edits one without the others breaks the release-workflow test suite.
  3. The '90' fallback is exactly this PR's cap: if an operator sets QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES, that value wins — intended, since retuning without a PR is why main introduced the knob.

Verification done / not done. No build or tests run (per this flow; deps not installed). Verified instead: YAML parses and jobs.workspace_tests.timeout-minutes equals the expected expression string; the pinning-test literal matches the raw workflow line byte-for-byte; no conflict markers remain; only the two conflicted files differ from an auto-merge. Grep across the merged tree shows no other file references this knob, so no non-conflicted caller depends on the value.

中文说明

根因:两边都在处理同一事故(release 运行 33713579913,分片仍存活却被取消)。本 PR 把 release.ymlworkspace_tests.timeout-minutes 从 45 硬编码提高到 90;而 main 上的 5e367dad15#10805)把同一行改成了可由运维调整的变量 "${{ fromJSON(vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES || '45') }}",并新增了钉住该字面量的测试。这是语义冲突,不是相邻改动。

解决方式:保留 main 的变量机制,把本 PR 的 90 分钟上限放进默认值:... || '90''45''90' 共改三处:工作流该行、测试文件中超时上限映射表,以及同一冲突文件里一处非冲突断言(toContain 逐字钉住工作流原始行的测试,若保留 '45' 会与合并结果自相矛盾)。双方注释均已合并保留。

关键点:默认值必须保持在 fromJSON(... || '90') 内且外层为双引号 YAML 字符串(timeout-minutes 需要数字,变量未设置时必须有回退);三处 '90' 必须一致,未来调整若只改其一会导致 release-workflow 测试失败;运维设置该变量时以变量为准,这正是 main 引入此开关的本意。

验证情况:未运行构建或测试(本流程不运行、依赖未安装)。已通过 YAML 解析、字面量逐字比对、冲突标记清零检查确认一致性;全仓 grep 确认无其他文件引用该变量。

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No issues found. LGTM! ✅

Not explored to full depth (tool budget reached): "agent 1a": none.** Nothing was cut short. One caveat on method rather than budget: the test run itself could not be executed because the shared review worktree has no nod….

Not linted (tool limitation, not a blocker): .github/workflows/release.yml — actionlint embedded-shell source mapping is not yet supported.

中文说明

未发现问题。LGTM!✅

未探索到全部深度(达到工具调用预算):"agent 1a"none.** Nothing was cut short. One caveat on method rather than budget: the test run itself could not be executed because the shared review worktree has no nod…

未检查(工具限制,非阻断):.github/workflows/release.yml——actionlint 对 workflow 内嵌 shell 的源映射尚未支持。

— qwen3.8-max via Qwen Code /review (v0.22.3)

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator Author

🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下:

Autofix round — no code change; one item needs a maintainer's decision

This round had exactly one feedback item: review rv:5100979810
(CHANGES_REQUESTED, submitted 2026-09-03T10:53:48Z against commit
3f77db6258 — the head before main was merged). No inline comments, no
failed checks.

I made no code change and no commit. Two of the review's three asks are
already satisfied or factually moot, and the third is a scope call that is not
mine to settle. Measurements below.

1. "Please rebase onto current main" — already done

Commit 23a73d2ae1 merged main and resolved the conflict the review was
written against. At the current head:

  • git merge-tree --write-tree origin/main HEAD → clean, no conflict
    (the workflow's own --conflict false agrees).

  • No conflict markers in either touched file.

  • Main's operator-tunable mechanism is preserved verbatimfromJSON(...),
    the double-quoted YAML string, and both test pins are intact. The only
    difference from main is the fallback literal:

    jobs.workspace_tests.timeout-minutes
    origin/main "${{ fromJSON(vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES || '45') }}"
    this branch "${{ fromJSON(vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES || '90') }}"
  • The pinning suite passes: scripts/tests/release-workflow.test.js48/48,
    including lets an operator retune the workspace shard timeout without a PR.
    All three sites that must agree (workflow line, toContain literal, bounds
    map) do agree.

So the concern "resolving this in the PR's favour would revert the tunable knob"
no longer describes the branch — the knob survived the merge.

2. "If nothing of the diff survives — as expected — close in favor of #10870"

The condition is false: something did survive. What survives is narrower
than the original PR but not empty — the unset-variable fallback '45'
'90', plus the two test literals that pin it (14 lines across 2 files).

Closing the PR is not something this flow can do: it has no GitHub credentials
and performs no writes. Abandoning a PR that was opened for a real release
incident, and that a maintainer already ran /resolve on rather than closing,
is also a scope decision rather than a code fix.

3. Correction: the knob came from #10805, not #10870

This matters because "close in favor of #10870" sends a maintainer to the wrong
merged PR.

  • git show --stat 93e1597b7e -- .github/workflows/release.ymlempty.
    test: stop millisecond budgets from measuring the shared pool #10870 ("test: stop millisecond budgets from measuring the shared pool") never
    touched release.yml; it is the unit-test latency-budget change.
  • git log -S'QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES' origin/main -- .github/workflows/release.yml
    5e367dad15fix(release): report a workspace test run that fails with nothing failing (#10805), merged 2026-09-03T08:49Z.

The substance of the review is unaffected — main does already have the
operator knob — but the PR to credit (or to close in favor of) is #10805.

4. The real question the review raises

The review's substantive point survives the correction, and it is the reason I
am not treating this round as clean:

The surviving diff can only change the fallback, and the fallback is
evaluated only when vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES is unset.

While that repository variable is set (the review reports 75; repository
variables are not readable from this checkout, so I could not verify the value),
this diff cannot change the effective cap in QwenLM/qwen-code at all — so it
does not by itself remediate #10891. The operator variable does.

Worth adding, because it cuts against the surviving diff: in the one place the
fallback genuinely applies — a repo that is not QwenLM/qwen-code, where
runs-on resolves to ubuntu-latest instead of the reserved host — the
host-contention measurement that motivated 90 does not hold. Main's own comment
records the same third running "6.7 min quiet and 36 contended"; on an
uncontended hosted runner 45 is already generous, so raising the fallback to 90
mainly doubles how long a hung shard can hold a runner, which is the other
thing that cap bounds.

The decision, and my recommendation

Two defensible directions, and the branch has already been through both: the
/resolve round chose B, the CHANGES_REQUESTED asks for A.

  • A — close this PR. The cap is the shipped operator knob (fix(release): report a workspace test run that fails with nothing failing #10805). If a
    longer cap is wanted, set or bump QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES,
    which takes effect without a PR and without a review. Nothing of this diff is
    needed.
  • B — keep the current diff. The fallback becomes a safe value wherever the
    knob is unset, including the case where the variable is deleted in
    QwenLM/qwen-code and the contended reserved host makes 45 demonstrably too
    small (run 33713579913, attempt 3: both shards cancelled at "maximum
    execution time of 45m0s" while still live at 43m05s / 43m15s).

I recommend A, on the review's reasoning plus the runs-on observation
above: the fallback bump buys little in the environment where the fallback is
actually used, weakens the hang bound there, and has no effect on the reported
failure while the variable is set. AGENTS.md's Simplicity First argues the
same way against keeping a .github/ diff whose effect on #10891 is nil.

I did not implement A myself. Emptying the branch would be choosing the
contested direction unilaterally and would leave an unmergeable empty PR that I
cannot close; the previous round's conflict resolution was deliberate, and a
maintainer may well prefer B. I also did not treat the review as answered by the
round-2 APPROVED at 12:24:33Z — that pass reviewed code quality at
23a73d2ae1 and did not address supersession. The review is left unresolved.

Either way, #10891's remediation is operator-side

I could not distinguish these from the checkout; it needs someone with access to
the repository variables.

Verification

No source change and no commit this round, so the build/typecheck/lint gates
have nothing new to check; the commands I actually ran were:

  • git diff origin/main...HEAD — 2 files, +14 / −5 (release.yml, release-workflow.test.js).
  • git merge-tree --write-tree origin/main HEAD — clean, no conflict.
  • conflict-marker grep over both touched files — none.
  • git show --stat 93e1597b7e -- .github/workflows/release.yml — empty (test: stop millisecond budgets from measuring the shared pool #10870 never touched the file).
  • git log -S'QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES' origin/main -- .github/workflows/release.yml5e367dad15 (fix(release): report a workspace test run that fails with nothing failing #10805).
  • blob comparison origin/main vs HEAD for scripts/create-standalone-package.js and scripts/tests/install-script.test.js — identical.
  • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/release-workflow.test.js48 passed.
  • npm run test:scripts2107 passed, 1 failed, 16 skipped. The one failure is
    install-script.test.js > standalone release packaging > does not package audio-capture test artifacts,
    failing with ENOENT: no such file or directory, stat '.../packages/audio-capture/dist'.
    That is a gitignored build artifact (.gitignore:72 dist) absent from this checkout;
    the test shells out to the real packaging script, which stats it. Both the test and the
    script are byte-identical to origin/main, and CI's Test (ubuntu-latest, Node 22.x)
    on this same head is SUCCESS, so it does not reproduce where the build runs first.
    Not caused by this branch and not related to the workspace shard timeout.
  • CI on this head (checks.json, 45 entries): all SUCCESS or SKIPPED, none failing.
中文说明

Autofix 本轮 —— 未改动代码;有一项需要维护者决定

本轮只有一条反馈:review rv:5100979810CHANGES_REQUESTED,提交于
2026-09-03T10:53:48Z,针对的是 3f77db6258 —— 也就是合并 main 之前的那个
head)。没有 inline 评论,没有失败的检查。

没有改动任何代码,也没有提交。该 review 的三项要求中,两项已经满足或在事实上
已不成立,第三项是范围决策,不该由我来定。以下是实测数据。

1. "请 rebase 到当前 main" —— 已完成

提交 23a73d2ae1 已经合并了 main,并解决了该 review 所针对的冲突。在当前 head 上:

  • git merge-tree --write-tree origin/main HEAD → 干净,无冲突(workflow 传入的
    --conflict false 也一致)。

  • 两个被改动的文件里都没有冲突标记。

  • main 的运维可调机制原样保留 —— fromJSON(...)、双引号 YAML 字符串、以及两处
    测试固定都完好。与 main 的唯一差别是回退字面量:

    jobs.workspace_tests.timeout-minutes
    origin/main "${{ fromJSON(vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES || '45') }}"
    本分支 "${{ fromJSON(vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES || '90') }}"
  • 固定测试通过:scripts/tests/release-workflow.test.js48/48,其中包含
    lets an operator retune the workspace shard timeout without a PR。必须一致的三处
    (workflow 行、toContain 字面量、bounds 映射)确实一致。

所以"按本 PR 方向解决冲突会回退掉可调旋钮"这个担忧,已经不再描述当前分支 —— 旋钮在
合并中存活了下来。

2. "若 rebase 后无剩余内容(预期如此),请关闭并让位给 #10870"

这个前提是不成立的:确实有内容存活下来。存活的范围比原 PR 窄,但并非为空 ——
变量未设置时的回退默认值 '45''90',加上固定它的两处测试字面量
(2 个文件共 14 行)。

关闭 PR 不是本流程能做的事:它没有 GitHub 凭据,也不执行任何写操作。而且,放弃一个
为真实发布事故而开、且维护者已经对其执行 /resolve(而非关闭)的 PR,属于范围决策,
不是代码修复。

3. 更正:该旋钮来自 #10805,不是 #10870

这一点很重要,因为"让位给 #10870"会把维护者引向错误的已合并 PR。

  • git show --stat 93e1597b7e -- .github/workflows/release.yml
    test: stop millisecond budgets from measuring the shared pool #10870("test: stop millisecond budgets from measuring the shared pool")从未改动
    release.yml;它是单元测试耗时预算的改动。
  • git log -S'QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES' origin/main -- .github/workflows/release.yml
    5e367dad15 —— fix(release): report a workspace test run that fails with nothing failing (#10805),合并于 2026-09-03T08:49Z

review 的实质内容不受此更正影响 —— main 上确实已经有运维旋钮 —— 但应当归功于
(或应当让位于)的 PR 是 #10805

4. review 真正提出的问题

review 的实质论点在更正之后依然成立,这也是我不把本轮视为"干净"的原因:

存活的 diff 只能改变回退默认值,而回退默认值只在
vars.QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES 未设置时才会被求值。
只要该仓库变量
已被设置(review 称当前为 75;仓库变量无法从本次 checkout 读取,所以我无法核实
这个数值),本 diff 就完全无法改变 QwenLM/qwen-code 中的有效上限 —— 因此它本身并不
能修复 #10891。能修复它的是那个运维变量。

再补充一点,因为这一点对存活的 diff 不利:回退默认值真正生效的唯一场景 —— 仓库不是
QwenLM/qwen-code 时,runs-on 会解析为 ubuntu-latest 而非那台专用主机 —— 恰恰是
推动 90 这个数值的主机竞争实测不成立的场景。main 自己的注释就记录了同一个三分之一分片
"空闲时 6.7 分钟、资源竞争时 36 分钟";在没有竞争的托管 runner 上,45 已经相当宽裕,
因此把回退值提到 90 主要是把卡死的分片占用 runner 的时长翻倍 —— 而这正是该上限
所要约束的另一件事。

决策,以及我的建议

两个都说得通的方向,而本分支已经先后走过这两条路:/resolve 那一轮选择了 B
CHANGES_REQUESTED 要求的是 A

  • A —— 关闭本 PR。 上限就是已落地的运维旋钮(fix(release): report a workspace test run that fails with nothing failing #10805)。如果想要更长的上限,设置
    或调高 QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES 即可,无需 PR、无需 review 就能生效。
    本 diff 的任何内容都不是必需的。
  • B —— 保留当前 diff。 这样在旋钮未设置的任何场景下,回退值都是安全的 —— 包括
    QwenLM/qwen-code 中该变量被删除、而那台竞争激烈的专用主机使 45 明显过小的情况
    (run 33713579913 第 3 次尝试:两个分片在 43m05s / 43m15s 仍然存活时被以
    "maximum execution time of 45m0s" 取消)。

我建议选 A,理由是该 review 的论证加上上面关于 runs-on 的观察:回退值的这次上调
在回退值真正生效的环境里收益很小,却在那里削弱了对卡死的约束,而在变量已设置时对上报
的故障毫无影响。AGENTS.md 的 Simplicity First 也同样不支持保留一个对 #10891 毫无作用
.github/ diff。

没有自行实施 A。清空分支等于单方面选定这个有争议的方向,并且会留下一个我无法关闭
的、无法合并的空 PR;上一轮的冲突解决是经过慎重考虑的,维护者也完全可能更倾向 B。我也
没有把 12:24:33Z 那一轮 APPROVED 当作对该 review 的回应 —— 那一次审查的是
23a73d2ae1 的代码质量,并未处理"已被取代"这个问题。该 review 保持未解决状态。

无论选哪个,#10891 的补救都在运维侧

我无法从 checkout 中区分这两种情况;这需要有仓库变量访问权限的人来确认。

验证(Verification)

本轮没有源码改动、没有提交,因此 build/typecheck/lint 这些门禁没有新内容可检查;我实际
运行过的命令是:

  • git diff origin/main...HEAD —— 2 个文件,+14 / −5(release.ymlrelease-workflow.test.js)。
  • git merge-tree --write-tree origin/main HEAD —— 干净,无冲突。
  • 对两个被改动文件做冲突标记 grep —— 无。
  • git show --stat 93e1597b7e -- .github/workflows/release.yml —— 空(test: stop millisecond budgets from measuring the shared pool #10870 从未改动该文件)。
  • git log -S'QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES' origin/main -- .github/workflows/release.yml —— 5e367dad15fix(release): report a workspace test run that fails with nothing failing #10805)。
  • scripts/create-standalone-package.jsscripts/tests/install-script.test.jsorigin/mainHEAD 的 blob 比对 —— 完全一致。
  • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/release-workflow.test.js —— 48 通过
  • npm run test:scripts —— 2107 通过,1 失败,16 跳过。唯一失败项是
    install-script.test.js > standalone release packaging > does not package audio-capture test artifacts
    报错为 ENOENT: no such file or directory, stat '.../packages/audio-capture/dist'
    那是一个被 gitignore 的构建产物(.gitignore:72 dist),在本次 checkout 中不存在;该测试会
    调用真实的打包脚本,而脚本要 stat 这个目录。测试与脚本都与 origin/main 逐字节一致,且同一
    head 上 CI 的 Test (ubuntu-latest, Node 22.x)SUCCESS,说明在会先执行构建的环境里它
    并不复现。该失败与本分支无关,也与 workspace 分片超时无关。
  • 本 head 上的 CI(checks.json,45 条):全部为 SUCCESSSKIPPED,无失败。

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。


🧠 Handled by Qwen Code · model/模型 qwen3.8-max-2026-09-02

@wenshao wenshao closed this Sep 3, 2026
@yiliang114

Copy link
Copy Markdown
Collaborator

Closing — the mechanism this PR hardcodes is already on main in a tunable form. Since 5e367da, workspace_tests reads its cap from the repo variable QWEN_RELEASE_WORKSPACE_TIMEOUT_MINUTES (default 45), retunable without a PR. If the boundary cancellations come back, we'll bump that variable instead of re-hardcoding a ceiling.

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.

Release Failed for v0.23.0 on 2026-09-03

4 participants