Skip to content

fix(release): raise prepared package size budget to 112 MiB (#10775) - #10788

Closed
qwen-code-dev-bot wants to merge 1 commit into
mainfrom
autofix/issue-10775
Closed

qwen-code-dev-bot wants to merge 1 commit into
mainfrom
autofix/issue-10775

Conversation

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

What this PR does

Raises the budget that the packaging step enforces on the prepared npm package from 96 MiB to 112 MiB, and moves the test that pins that default along with it. Nothing else changes: no packaging logic, no bundle content, and no workflow is touched.

Why it's needed

The nightly release v0.22.3-nightly.20260902.7df5ac6898 failed with only one red job, the docker integration lane, and the failure was not in any test. The Docker sandbox image's builder stage ends by preparing and packing the distributable package, and that preparation refuses to run once the package exceeds its size budget. The package had grown to 101,897,981 bytes (97.18 MiB) against a 100,663,296-byte (96 MiB) budget, so the image build threw and every docker-sandbox leg on the runner pool failed with it — the release's docker integration job plus all three E2E docker shards, across ten distinct hosts in all three host groups, over five runs and three commits, with the E2E leg's one build retry failing identically.

The growth is legitimate: a single new 1.91 MiB renderer chunk that shipped when the OpenTUI backend was activated behind QWEN_TUI_RENDERER. Without that chunk the package measures 95.27 MiB, under the old budget. No source maps, test files, or dependency trees are in the measured set. Because no host-side lane prepares the package, the breach is invisible until a docker build runs, which is why the same commit had green quality, workspace, and no-sandbox integration lanes. The release's publish step prepares the package too, so that nightly could not have published even if the docker lane had passed.

Raising the budget is the remediation this repository has already used twice for this exact failure, including once with the same symptom during the v0.19.9 release. 112 MiB leaves about 15% headroom over the measured size — comparable to the headroom the previous bump left — while the packed tarball is only 27.0 MB, so no registry limit is near. The guard still trips on an accidental large inclusion, and the separate scan that keeps the removed browser-automation dependencies out of the package is untouched.

Reviewer Test Plan

How to verify

  1. On main before this change, build the bundle (npm run build && npm run bundle) and run node scripts/prepare-package.js. It exits 1 with Error: Prepared package unpacked size 101897981 bytes exceeds 100663296 bytes. This is the exact command the Docker builder stage runs, so it reproduces the release failure without needing a docker daemon.
  2. On this branch, repeat step 1: the command exits 0 and prints the package structure. npm pack inside dist/ then succeeds, reporting package size: 27.0 MB, unpacked size: 101.9 MB, total files: 1023.
  3. Run npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/package-assets.test.js — 34 passed. The budget test now proves both sides of the new default: 111 MiB of content prepares cleanly and 112 MiB is rejected with exceeds 117440512 bytes.
  4. Confirm the guard is still live rather than merely relaxed: set the budget back to 96 MiB and re-run steps 1 and 3. The prepare command fails with the original error and the budget test fails with expected [Function] to not throw an error. Restore 112 MiB and both go green.
  5. The end-to-end confirmation is the next nightly: the docker integration lane and the E2E docker shards should build the sandbox image and run their tests instead of failing before the first test.

Evidence (Before & After)

N/A — no user-visible or TUI surface. The observable change is CI: before, Run Docker Integration Tests failed in 9m13s having never reached a test, and each E2E docker shard logged sandbox image build failed; retrying once before exiting 1; after, the packaging step that the image build ends with completes.

Tested on

OS Status
🍏 macOS ⚠️
🪟 Windows ⚠️
🐧 Linux

Environment (optional)

Linux self-hosted runner checkout of main @ 7df5ac6898 with the repository's own npm ci install; bundle produced by npm run build && npm run bundle. No docker daemon is available in that environment, so the container-only tail of the Dockerfile builder stage was executed directly on the host as the surrogate. npm pack needed a scratch cache directory because the runner's ~/.npm holds root-owned files.

Risk & Scope

  • Main risk or tradeoff: the size budget is a ratchet against accidental bloat, and raising it by 16 MiB widens the window in which an unintended artifact could slip into the published package. The tradeoff is deliberate — the alternative is that ordinary feature growth keeps breaking every docker CI leg and the nightly release until someone bumps the constant, and the forbidden-literal scan that guards the specific historical regression is unaffected.
  • Not validated / out of scope: docker build itself was not run (no daemon available); the surrogate covers the command that threw plus the npm pack that follows it. Also left alone: the budget is enforced only inside the docker build and the publish job, so a future breach will again surface as a pool-wide docker outage rather than a readable host-side failure — running the packaging step in a host-side lane would fix that, and it belongs in a workflow change of its own.
  • Breaking changes / migration notes: none. No published artifact, manifest, CLI surface, or workflow changes; only the internal budget constant and its test.

Linked Issues

Fixes #10775

中文说明

这个 PR 做了什么

将打包步骤对"准备好的 npm 包体"所强制执行的体积预算从 96 MiB 提高到 112 MiB,并同步移动固定该默认值的测试。其他内容一律未动:没有改打包逻辑、没有改 bundle 内容、也没有改任何工作流。

为什么需要

nightly 发布 v0.22.3-nightly.20260902.7df5ac6898 失败时只有一个红 job —— docker 集成通道 —— 而且失败点不在任何测试里。Docker 沙箱镜像的 builder 阶段最后会准备并打包可发布的包体,而一旦包体超过体积预算,这个准备步骤就会拒绝执行。当时包体已增长到 101,897,981 字节(97.18 MiB),而预算是 100,663,296 字节(96 MiB),于是镜像构建抛错,池上所有 docker 沙箱环节随之失败 —— 发布的 docker 集成 job 加上三个 E2E docker 分片,在三个主机组的十台不同主机上、五次运行、三个提交之间反复出现,E2E 环节那一次构建重试也以完全相同的方式失败。

这次增长是合理的:只有一个 1.91 MiB 的渲染器 chunk,是在 OpenTUI 后端通过 QWEN_TUI_RENDERER 开关启用时引入的。去掉这个 chunk,包体为 95.27 MiB,低于旧预算。统计范围内没有 source map、没有测试文件、也没有依赖目录。由于宿主机侧没有任何通道会准备包体,这个越界在 docker 构建运行之前是不可见的 —— 这也是为什么同一个提交的质量检查、workspace 测试和无沙箱集成通道全是绿的。发布的 publish 步骤同样会准备包体,所以即使 docker 通道通过,那次 nightly 也无法发布。

提高预算是本仓库针对这一完全相同故障已经采用过两次的处理方式,其中一次正是在 v0.19.9 发布期间出现相同症状时。112 MiB 相对实测体积留出约 15% 余量 —— 与上一次提高预算留出的余量相当 —— 而打包后的 tarball 只有 27.0 MB,距离任何 registry 限制都很远。该保护在意外混入大体积内容时仍会触发,而用于阻止已移除的浏览器自动化依赖回流的敏感字符串扫描也未被触碰。

审阅者测试计划

如何验证

  1. 在改动前的 main 上,构建 bundle(npm run build && npm run bundle)并运行 node scripts/prepare-package.js。它会以退出码 1 结束,并报 Error: Prepared package unpacked size 101897981 bytes exceeds 100663296 bytes。这正是 Docker builder 阶段执行的命令,因此无需 docker 守护进程即可复现发布失败。
  2. 在本分支上重复第 1 步:该命令以退出码 0 结束并打印包结构。随后在 dist/ 中执行 npm pack 会成功,输出 package size: 27.0 MBunpacked size: 101.9 MBtotal files: 1023
  3. 运行 npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/package-assets.test.js —— 34 个测试通过。预算测试现在同时验证新默认值的两侧:111 MiB 内容可以正常打包,112 MiB 会被拒绝并报 exceeds 117440512 bytes
  4. 确认该保护仍然有效,而不只是被放宽:把预算改回 96 MiB 并重跑第 1 步和第 3 步。准备命令会以原始错误失败,预算测试会以 expected [Function] to not throw an error 失败。改回 112 MiB 后两者重新变绿。
  5. 端到端的确认是下一次 nightly:docker 集成通道和 E2E docker 分片应当能构建出沙箱镜像并运行测试,而不是在第一个测试之前就失败。

前后对比证据

N/A —— 没有用户可见或 TUI 层面的变化。可观察到的变化在 CI:改动前,Run Docker Integration Tests 在 9 分 13 秒后失败且从未跑到任何测试,每个 E2E docker 分片都会先打印 sandbox image build failed; retrying once 再以退出码 1 结束;改动后,镜像构建所依赖的最后一个打包步骤可以正常完成。

测试环境

OS Status
🍏 macOS ⚠️
🪟 Windows ⚠️
🐧 Linux

环境(可选)

Linux 自托管 runner 上 main @ 7df5ac6898 的检出,使用仓库自身的 npm ci 安装;bundle 由 npm run build && npm run bundle 生成。该环境没有可用的 docker 守护进程,因此把 Dockerfile builder 阶段中"仅容器内执行"的尾部命令直接在宿主机上运行作为替代验证。npm pack 需要一个临时缓存目录,因为该 runner 的 ~/.npm 中存在 root 所有的文件。

风险与范围

  • 主要风险或权衡:体积预算是防止意外膨胀的棘轮,提高 16 MiB 会扩大非预期产物混入发布包体的窗口。这个权衡是有意的 —— 另一种选择是:正常的功能增长会持续打断所有 docker CI 环节和 nightly 发布,直到有人来改这个常量;而针对具体历史回归的敏感字符串扫描不受影响。
  • 未验证 / 超出范围:没有实际运行 docker build(环境无守护进程);替代验证覆盖了抛错的那条命令及其后的 npm pack。同样未处理的是:该预算只在 docker 构建和 publish job 内强制执行,所以将来的越界仍会表现为全池 docker 中断,而不是宿主机侧可读的失败 —— 在宿主机侧通道运行打包步骤可以解决这点,那属于一次独立的工作流改动。
  • 破坏性变更 / 迁移说明:无。发布产物、manifest、CLI 接口和工作流都没有变化;只改了内部预算常量和它的测试。

关联 Issue

Fixes #10775

The prepared package now measures 101,897,981 bytes (97.18 MiB), 1.18 MiB
over the 96 MiB budget, so `npm run prepare:package` throws — and because
the Docker sandbox image's builder stage ends with that command, every
docker build failed with it: the release integration_docker job and all
three e2e sandbox:docker shards, on three different pool hosts, the e2e
build retry included. No host-side lane runs prepare:package, so quality,
workspace tests and integration_none stayed green and the breach only
surfaced inside `docker build`; the publish job would have hit the same
gate on the same run.

The growth is the OpenTUI renderer chunk (2,002,450 bytes) that shipped
with the QWEN_TUI_RENDERER activation — without it the package measures
95.27 MiB, under the old budget. Raise the budget to 112 MiB, about 15%
headroom over the measured size (the packed tarball is 27.0 MB), and move
the pinning test with it: the same remediation as #6688 (80 -> 85 MiB) and
#6691 (85 -> 96 MiB), the latter unblocking the identical v0.19.9 docker
sandbox build failure.
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator Author

Autofix E2E report — issue #10775 (Release Failed for v0.22.3-nightly.20260902.7df5ac6898)

What failed

Release run 33594509319 (tag v0.22.3-nightly.20260902.7df5ac6898, head 7df5ac6898) failed in exactly one job: Integration Tests (Docker) (integration_docker), at step 10 Run Docker Integration Tests (05:37:56 → 05:47:09 UTC, runner ecs-qwen-hk4-29). Every other job in the run succeeded — prepare, all five quality lanes, all three workspace test shards, integration_none, and the audio-capture prebuilds — so publish was skipped and notify_failure filed this issue.

The job carries a single generic annotation, Process completed with exit code 1.: none of the step's three ::error:: lock-timeout guards fired (and the step ran 9 minutes, not the 30-minute lock budget), while step 3 Check docker daemon and step 8 Build Bundle both succeeded. So the docker daemon, the runner, and the host toolchain were healthy, and the failure was inside the sandbox image build itself — which is what that step does first (npm run build:sandbox -- -s --no-prune -i "$sandbox_image"), before any test runs.

Root cause (reproduced locally)

The Dockerfile's builder stage ends with:

RUN QWEN_SKIP_PREPARE=1 npm ci \
  && npm run build \
  && npm run bundle \
  && npm run prepare:package \
  && cd dist && npm pack

npm run prepare:package enforces a self-imposed budget on the prepared package (assertPreparedPackageSize, 96 MiB = 100,663,296 bytes). At this commit the prepared package measures 101,897,981 bytes (97.18 MiB)1,234,685 bytes (1.18 MiB) over — so the command throws and docker build fails with it. This sandbox has no docker daemon (command -v docker is empty), so the container-only step was run directly against the real bundle on main @ 7df5ac6898, which reproduces it exactly:

$ node scripts/prepare-package.js
Error: Prepared package unpacked size 101897981 bytes exceeds 100663296 bytes
    at assertPreparedPackageSize (scripts/prepare-package.js:401:9)
exit 1

Why nothing else caught it: no host-side lane runs prepare:package. npm ci, npm run build, npm run bundle, and the whole test suite all pass — the budget is only checked inside the Docker build and in the release publish job. That is exactly the observed shape: integration_none green, all quality lanes green, integration_docker red. The publish job runs the same npm run prepare:package (its "Build Bundle and Prepare Package" step), so this nightly could not have published even if integration_docker had passed.

What pushed it over: dist/chunks/start-opentui-ui-NIRSHD3K.js, 2,002,450 bytes (1.91 MiB), new in 8051bf02bd "feat(opentui): Activate the OpenTUI backend behind QWEN_TUI_RENDERER" (landed 02:55 UTC). Without that one chunk the package measures 99,895,531 bytes (95.27 MiB) — 767,765 bytes under the old budget. The rest of the package is unchanged, expected content: chunks 49.80 MiB, vendor 25.55 MiB (four ripgrep binaries plus tree-sitter wasm), web-shell 18.50 MiB, bundled 1.88 MiB, locales 1.33 MiB. No source maps, no test files, and no node_modules are in the measured set, so this is legitimate feature growth crossing a stale budget, not accidental bloat.

The CI timeline matches the attribution:

Run (UTC) Commit Docker legs Host legs
e2e 33579624662, 02:06–02:59 165a03596a all 3 shards success success
e2e 33585038620 / 33585419625 / 33586489948, 02:55–03:36 8051bf02bdedfdbda89a failed failed everywhere on an unrelated TypeScript break (Type '"output-style"' is not assignable to type 'never'), fixed by ec7caa2399
e2e 33587037818, 03:26 ec7caa2399 all 3 shards failed — hk3-30, hk5-4, hk5-22 all 3 sandbox:none shards + macOS success
e2e 33588890820 / 33590493339, 03:56 & 04:21 b26403154b all docker shards failed success
e2e 33592836087, 04:58 7df5ac6898 shards 1/3 (hk5-26) & 3/3 (hk4-20) failed success
release 33594509319, 05:24 7df5ac6898 integration_docker failed everything else success

Every failing docker leg in e2e.yml carries the annotation sandbox image build failed; retrying once followed by Process completed with exit code 1. — i.e. the build was retried and failed identically. That annotation pair was read directly on five hosts (ecs-qwen-hk3-30, ecs-qwen-hk3-9, ecs-qwen-hk5-2, ecs-qwen-hk5-26, ecs-qwen-hk4-20); across the window from 03:26 to 05:47 UTC every docker leg of five runs on three commits failed, on ten distinct hosts spanning all three host groups including the release job's ecs-qwen-hk4-29. That is a deterministic content-level failure, not pool contention, and release.yml has no build retry, so its single attempt failed the same way.

Precedent: this exact failure mode has been remediated twice before by raising the budget — ebd83f1d2d "fix(release): raise package size budget to 85 MiB (#6688)" (80 → 85 MiB) and bcf5b7bfdd "fix(release): raise prepared package size limit to 96 MB (#6687) (#6691)" (85 → 96 MiB), whose own commit message reads "the current package is 80.58 MB — 597 KB over — causing the Docker sandbox build to fail during the v0.19.9 release". CHANGELOG.md still records it as "Raised prepared npm package size limit from 80 MB to 96 MB to accommodate natural growth and unblock Docker sandbox builds."

The fix

Raise DEFAULT_MAX_NPM_PACKAGE_UNPACKED_BYTES from 96 MiB to 112 MiB (117,440,512 bytes) and move the test that pins the default with it — the same two-file shape as both precedent bumps. 112 MiB leaves 15,542,531 bytes (~15%) of headroom over the measured 97.18 MiB, close to the ~19% headroom the 96 MiB bump left over 80.58 MiB, while the packed tarball is only 27.0 MB, so no registry limit is anywhere near. The guard still fires on an accidental large inclusion, and the separate forbidden-literal scan from #6472 (the actual anti-regression guard for the removed browser-automation dependencies) is untouched.

Verification

Docker itself is unavailable in this sandbox, so the container-only tail of the Dockerfile builder stage (npm run prepare:package then npm pack in dist/) was run directly against the real bundle as the surrogate.

  • node scripts/prepare-package.js (before the fix, cap 96 MiB) — failed, exit 1: Error: Prepared package unpacked size 101897981 bytes exceeds 100663296 bytes — the reproduced root cause
  • node scripts/prepare-package.js (after the fix, cap 112 MiB) — passed, exit 0, package structure printed
  • npm pack inside dist/ (after the fix, --cache /tmp/af-npm-cache because this runner's ~/.npm holds root-owned files) — passed, exit 0: package size: 27.0 MB, unpacked size: 101.9 MB, total files: 1023. The Dockerfile builder stage now completes end to end.
  • Mutation probe (cap temporarily reverted to 96 MiB, both witnesses re-run, then restored):
    • node scripts/prepare-package.jsfailed again with the original 101897981 bytes exceeds 100663296 bytes error
    • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/package-assets.test.jsfailed: × enforces a 112 MiB default unpacked size budget → expected [Function] to not throw an error but 'Error: Prepared package unpacked size…' was thrown (1 failed | 33 passed)
    • cap restored to 112 MiB — both green again, so the changed constant is genuinely witnessed by the committed test
  • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/package-assets.test.js34 passed
  • npm run test:scripts (full scripts suite) — 2070 passed, 16 skipped, with 4–6 files failing on 30 s timeouts under this runner's load. Evidence they are unrelated: none of them imports prepare-package.js (grep -ln "prepare-package\|preparePackage" over the six files returns nothing), and re-running those six files in isolation gives 277 passed (6 files). The failures vary between runs of the same tree (acp-serve-boundary-guard, no-core-root-barrel-config, qwen-autofix-workflow, qwen-fleet-shepherd-workflow, upload-aliyun-oss-assets, vscode-companion-no-webui-config), all timing-sensitive on a saturated shared host.
  • npm run buildpassed, exit 0
  • npm run typecheckpassed, exit 0
  • npm run lintpassed, exit 0

Not validated / notes for maintainers

  • docker build could not be executed here (no daemon in this sandbox). The surrogate covers the exact command that threw; the surrounding npm ci / npm run build / npm run bundle steps all pass on the host in CI at this commit, and npm pack was verified too.
  • Out of scope, not changed here: the budget is enforced only inside the Docker build and the publish job, so a breach costs a pool-wide docker outage (every sandbox:docker e2e shard on every push, plus the nightly release) before anyone reads a clear message. Running npm run prepare:package in a host-side lane would turn the next breach into an immediate failure naming the byte count.
  • Out of scope, observed while tracing: assertPreparedPackageSize does not count dist/node_modules/@qwen-code/audio-capture, which the publish job does pack through bundledDependencies, so the published tarball is slightly larger than the measured figure.
  • Out of scope, observed while tracing: packages/qwen-live/package.json declares @agentclientprotocol/sdk@^0.14.1 but the packages/qwen-live entry in package-lock.json does not list it. npm ci still succeeds because the hoisted root entry satisfies the range, but a lockfile refresh would remove the discrepancy.
中文说明

Autofix E2E 报告 —— issue #10775(v0.22.3-nightly.20260902.7df5ac6898 发布失败)

失败的内容

发布运行 33594509319(标签 v0.22.3-nightly.20260902.7df5ac6898,head 提交 7df5ac6898)只有一个 job 失败:Integration Tests (Docker)(即 integration_docker),失败在第 10 步 Run Docker Integration Tests(UTC 05:37:56 → 05:47:09,runner 为 ecs-qwen-hk4-29)。该运行的其他所有 job 都成功了 —— prepare、五个质量检查通道、三个 workspace 测试分片、integration_none、以及 audio-capture 预构建 —— 因此 publish 被跳过,notify_failure 创建了这个 issue。

该 job 只有一条通用批注 Process completed with exit code 1.:这一步中三个 ::error:: 锁超时保护都没有触发(而且该步骤只运行了 9 分钟,远不到 30 分钟的锁预算),同时第 3 步 Check docker daemon 和第 8 步 Build Bundle 都成功了。所以 docker 守护进程、runner 和宿主机工具链都是健康的,失败发生在沙箱镜像构建内部 —— 也就是该步骤最先执行的动作(npm run build:sandbox -- -s --no-prune -i "$sandbox_image"),此时还没有任何测试开始运行。

根因(已在本地复现)

Dockerfile 的 builder 阶段最后执行:

RUN QWEN_SKIP_PREPARE=1 npm ci \
  && npm run build \
  && npm run bundle \
  && npm run prepare:package \
  && cd dist && npm pack

npm run prepare:package 会对准备好的包体执行一个自定义的体积上限检查(assertPreparedPackageSize,96 MiB = 100,663,296 字节)。在当前提交上,包体实测为 101,897,981 字节(97.18 MiB)超出 1,234,685 字节(1.18 MiB),因此该命令抛错,docker build 随之失败。本沙箱环境没有 docker 守护进程(command -v docker 为空),所以直接在 main @ 7df5ac6898 的真实产物上运行了这个"仅容器内执行"的步骤,可以精确复现:

$ node scripts/prepare-package.js
Error: Prepared package unpacked size 101897981 bytes exceeds 100663296 bytes
    at assertPreparedPackageSize (scripts/prepare-package.js:401:9)
exit 1

为什么其他环节没有发现: 宿主机侧没有任何通道会运行 prepare:packagenpm cinpm run buildnpm run bundle 以及整个测试套件都能通过 —— 这个体积上限只在 Docker 构建内部和发布的 publish job 中检查。这正是观测到的形态:integration_none 绿、所有质量通道绿、integration_docker 红。publish job 运行的是同一个 npm run prepare:package(其 "Build Bundle and Prepare Package" 步骤),所以即使 integration_docker 通过,这次 nightly 也无法发布。

是什么把体积推过上限: dist/chunks/start-opentui-ui-NIRSHD3K.js2,002,450 字节(1.91 MiB),由 8051bf02bd「feat(opentui): Activate the OpenTUI backend behind QWEN_TUI_RENDERER」(UTC 02:55 合入)新增。去掉这一个 chunk,包体为 99,895,531 字节(95.27 MiB)—— 比旧上限 767,765 字节。包体其余部分都是未变化的预期内容:chunks 49.80 MiB、vendor 25.55 MiB(四个 ripgrep 二进制加 tree-sitter wasm)、web-shell 18.50 MiB、bundled 1.88 MiB、locales 1.33 MiB。统计范围内没有 source map、没有测试文件、也没有 node_modules,因此这是正常功能增长越过了一个过期的预算,而不是意外膨胀。

CI 时间线与该归因一致:

运行(UTC) 提交 Docker 环节 宿主机环节
e2e 33579624662,02:06–02:59 165a03596a 3 个分片全部成功 成功
e2e 33585038620 / 33585419625 / 33586489948,02:55–03:36 8051bf02bdedfdbda89a 失败 因一个无关的 TypeScript 错误(Type '"output-style"' is not assignable to type 'never')全面失败,后由 ec7caa2399 修复
e2e 33587037818,03:26 ec7caa2399 3 个分片全部失败 —— hk3-30、hk5-4、hk5-22 3 个 sandbox:none 分片 + macOS 全部成功
e2e 33588890820 / 33590493339,03:56 与 04:21 b26403154b 所有 docker 分片失败 成功
e2e 33592836087,04:58 7df5ac6898 分片 1/3(hk5-26)与 3/3(hk4-20)失败 成功
release 33594509319,05:24 7df5ac6898 integration_docker 失败 其他全部成功

e2e.yml 中每个失败的 docker 环节都带有批注 sandbox image build failed; retrying once,随后是 Process completed with exit code 1. —— 即构建被重试过一次并以完全相同的方式失败。这一对批注是在五台主机上直接读取确认的(ecs-qwen-hk3-30ecs-qwen-hk3-9ecs-qwen-hk5-2ecs-qwen-hk5-26ecs-qwen-hk4-20);在 UTC 03:26 到 05:47 这个窗口内,三次提交上的五次运行中,每一个 docker 环节都失败了,涉及横跨三个主机组的十台不同主机,其中也包括发布 job 所在的 ecs-qwen-hk4-29。这是确定性的内容级失败,不是资源争抢;而 release.yml 没有构建重试,所以它的单次尝试以同样方式失败。

先例: 完全相同的失败模式此前已经通过提高预算处理过两次 —— ebd83f1d2d「fix(release): raise package size budget to 85 MiB (#6688)」(80 → 85 MiB)和 bcf5b7bfdd「fix(release): raise prepared package size limit to 96 MB (#6687) (#6691)」(85 → 96 MiB),后者的提交信息写着*"当前包体为 80.58 MB —— 超出 597 KB —— 导致 v0.19.9 发布期间 Docker 沙箱构建失败"。CHANGELOG.md 中仍记录为"Raised prepared npm package size limit from 80 MB to 96 MB to accommodate natural growth and unblock Docker sandbox builds."*

修复

DEFAULT_MAX_NPM_PACKAGE_UNPACKED_BYTES 从 96 MiB 提高到 112 MiB(117,440,512 字节),并同步移动固定该默认值的测试 —— 与两次先例相同的两文件改动形态。112 MiB 相对实测的 97.18 MiB 留出 15,542,531 字节(约 15%)余量,接近 96 MiB 那次相对 80.58 MiB 留出的约 19% 余量;而打包后的 tarball 只有 27.0 MB,距离任何 registry 限制都很远。该保护仍会在意外混入大体积内容时触发,而 #6472 引入的、真正用于防止已移除的浏览器自动化依赖回流的敏感字符串扫描未被触碰。

验证

本环境无法使用 docker,因此以真实产物直接运行 Dockerfile builder 阶段中"仅容器内执行"的尾部命令(npm run prepare:package,随后在 dist/npm pack)作为替代验证。

  • node scripts/prepare-package.js(修复前,上限 96 MiB)—— 失败,退出码 1:Error: Prepared package unpacked size 101897981 bytes exceeds 100663296 bytes,即复现出的根因
  • node scripts/prepare-package.js(修复后,上限 112 MiB)—— 通过,退出码 0,正常打印包结构
  • dist/ 中执行 npm pack(修复后,因本 runner 的 ~/.npm 存在 root 所有文件而加 --cache /tmp/af-npm-cache)—— 通过,退出码 0:package size: 27.0 MBunpacked size: 101.9 MBtotal files: 1023。Dockerfile builder 阶段现在可以完整走通。
  • 变异探测(把上限临时改回 96 MiB,重跑两个见证,然后恢复):
    • node scripts/prepare-package.js —— 再次失败,报出原始的 101897981 bytes exceeds 100663296 bytes 错误
    • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/package-assets.test.js —— 失败× enforces a 112 MiB default unpacked size budget → expected [Function] to not throw an error but 'Error: Prepared package unpacked size…' was thrown(1 失败 | 33 通过)
    • 上限恢复为 112 MiB 后 —— 两者重新变绿,说明本次改动的常量确实被提交的测试所见证
  • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/package-assets.test.js —— 34 个测试通过
  • npm run test:scripts(scripts 全量套件)—— 2070 通过、16 跳过,另有 4–6 个文件在本 runner 负载下因 30 秒超时失败。它们与本次改动无关的证据是:这六个文件都没有导入 prepare-package.js(对六个文件执行 grep -ln "prepare-package\|preparePackage" 无输出),并且单独重跑这六个文件得到 277 个测试通过(6 个文件)。同一棵代码树的多次运行中失败集合还会变化(acp-serve-boundary-guardno-core-root-barrel-configqwen-autofix-workflowqwen-fleet-shepherd-workflowupload-aliyun-oss-assetsvscode-companion-no-webui-config),全部属于饱和共享主机上的时间敏感型测试。
  • npm run build —— 通过,退出码 0
  • npm run typecheck —— 通过,退出码 0
  • npm run lint —— 通过,退出码 0

未验证 / 给维护者的说明

  • 本环境无法执行 docker build(沙箱内没有守护进程)。替代验证覆盖了真正抛错的那条命令;其外层的 npm ci / npm run build / npm run bundle 在该提交的 CI 宿主机上均通过,npm pack 也已本地验证。
  • 超出范围、本次未改动:该体积预算只在 Docker 构建和 publish job 内强制执行,因此一旦越界,代价是全池 docker 中断(每次 push 的所有 sandbox:docker e2e 分片,外加 nightly 发布),而在此之前没人能看到清晰的报错信息。若在宿主机侧的通道中运行 npm run prepare:package,下次越界会立即失败并直接给出字节数。
  • 超出范围、追踪过程中发现:assertPreparedPackageSize 不统计 dist/node_modules/@qwen-code/audio-capture,而 publish job 会通过 bundledDependencies 把它打进包里,所以实际发布的 tarball 比测得的数字略大。
  • 超出范围、追踪过程中发现:packages/qwen-live/package.json 声明了 @agentclientprotocol/sdk@^0.14.1,但 package-lock.jsonpackages/qwen-live 条目没有列出它。由于根节点提升的条目满足该版本范围,npm ci 仍能成功,但刷新一次 lockfile 可以消除这个不一致。

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

@qwen-code-ci-bot

qwen-code-ci-bot commented Sep 2, 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

The failure this PR targets was already fixed on main — the identical budget bump (96 → 112 MiB) merged in #10781 (commit aa4ae73389) at 07:37 UTC, and this PR was opened eleven minutes later, at 07:48 UTC. Two autofix branches raced on the same root cause: #10781 closed #10774 (the main-CI E2E failure), while this one fixes #10775 (the release-run failure) — the same docker-sandbox image build tripping the same over-budget prepare:package step.

Everything in this diff is already on the default branch: the test change is byte-for-byte identical to what #10781 landed, and the constant change is there too — which is why this PR now shows as conflicting. Applying it to main would change nothing, so closing as a duplicate of #10781. If something here is NOT covered by #10781, say so and this can be reopened.

One loose end for a maintainer: this PR's linked issue #10775 is still open even though its root cause was resolved by that same commit — #10774 and #10775 are two issues for the one failure, so #10775 likely deserves the same treatment.

中文说明

这个 PR 针对的失败已经在 main 上修复了——完全相同的预算调整(96 → 112 MiB)
已于 UTC 07:37 通过 #10781(提交 aa4ae73389)合入,而本 PR 在十一分钟后
(UTC 07:48)才创建。两个 autofix 分支针对同一根因竞争:#10781 关闭了
#10774(主 CI 的 E2E 失败),本 PR 则修复 #10775(发布运行的失败)——两者都是
docker 沙箱镜像构建在同一个超预算的 prepare:package 步骤上失败。

这份 diff 的所有内容都已在默认分支上:测试改动与 #10781 合入的内容逐字节相同,
常量改动也已在 main 上——这正是本 PR 现在显示冲突的原因。将它应用到 main
不会产生任何变化,因此作为 #10781 的重复 PR 关闭。如本 PR 有 #10781 未覆盖的
内容,请说明,可以重新打开。

给维护者的一个遗留事项:本 PR 关联的 issue #10775 仍然处于打开状态,但其根因
已由同一提交解决——#10774#10775 是同一次失败产生的两个 issue,#10775
很可能也应当同样关闭。

Qwen Code · qwen3.8-max

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.22.3-nightly.20260902.7df5ac6898 on 2026-09-02

2 participants