diff --git a/docs/develop-guides/decisions/implemented/2026-09-23-ci-system-tests-build-cache.md b/docs/develop-guides/decisions/implemented/2026-09-23-ci-system-tests-build-cache.md index 4799b6bb7..b3af05a13 100644 --- a/docs/develop-guides/decisions/implemented/2026-09-23-ci-system-tests-build-cache.md +++ b/docs/develop-guides/decisions/implemented/2026-09-23-ci-system-tests-build-cache.md @@ -12,7 +12,7 @@ Runtime System Tests 单次运行约 14m38s:`docker compose up --build` 312s - 在 CI 中用 `docker/setup-buildx-action` 单独预构建 `yuxi-api` 与 `yuxi-sandbox-provisioner` 镜像,启用 `type=gha,mode=max` 层缓存;`docker compose up` 去掉 `--build`。冷运行与原先等价,热运行命中 apt/uv sync/pip 层。 - 镜像名不硬编码,从 `docker compose config --format json` 解析,跟随 `.env.template` 与 docker-compose.yml。 -- CI 环境曾将 `SANDBOX_KEEPALIVE_INTERVAL_SECONDS=5` 写入 .env 并经容器 env 继承 `E2E_RUN_POLL_INTERVAL_SECONDS=1`。首轮 PR CI 中 3 次运行有 2 次在 `test_subagent_worker_enforces_inherited_write_policy[always_trust]` 以相同签名失败(worker 租约心跳仍在、Run 执行停滞 240s 超时),失败点在沙箱相关等待上与保活节奏变化相容但无直接证据。已撤回这两个覆写,e2e 回到默认轮询与保活;重新引入需先有失败根因证据。 +- CI 环境曾将 `SANDBOX_KEEPALIVE_INTERVAL_SECONDS=5` 写入 .env 并经容器 env 继承 `E2E_RUN_POLL_INTERVAL_SECONDS=1`。引入后 2 次运行在 `test_subagent_worker_enforces_inherited_write_policy[always_trust]` 失败,随即撤回。后续证据证明失败与这两个覆写无因果关系:main 在本变更合入前(ade113ec,run 35818088032,旧 workflow)与合入后(run 35828838121)在完全相同用例以相同签名失败,当日 8 次该文件运行约半数失败。撤回是为消除变量,不是缺陷修复。失败签名:父子 subagent 场景下父 Run 240s 无 `first_model_request_at`,worker job 静默执行 241s 后被取消;根因未定位。 - "Verify Durable Task worker path" 从主 job 拆为独立并行 job。该步骤会 stop api/worker 并强制重建 Milvus,与其余步骤互斥,其中 ~75s 是拓扑热身(真实 pytest 仅 ~25s),串在主链路里全部计入关键路径;它也不依赖 replay server 等主链路前置。两个 job 各自持有完整拓扑,共享层缓存,且都持有覆盖冷缓存构建的 timeout 预算。 - 两个 CI 脚本纳入 workflow 的 pull_request/push paths 与合同脚本 required_paths:只改 gate 实现(env 准备、镜像构建)不得绕过 gate。 - `.env` 准备脚本对 sed 替换文本转义 `&`、`\` 与 `/`,避免含特殊字符的密钥写错值。 @@ -24,7 +24,7 @@ Runtime System Tests 单次运行约 14m38s:`docker compose up --build` 312s - 并行化各 pytest 步骤:步骤间共享拓扑且有暂停 worker、强制重建 Milvus 等变更,不能安全拆分;删并步骤会削弱失败归因。 - 缩短 replay 阻塞时间: `time.sleep(60)` 是取消路径的确定性语义,不改。 - Durable Task 留在主链路:可省一套拓扑的 CI 分钟数,但 ~75s 拓扑热身继续占据关键路径。选择拆 job 是因为该步骤与主链路互斥,拆分不降低任何 gate 的归因粒度。 -- 缩短 e2e env:被 CI 失败证据否决(见决策),撤回而非降级保留。 +- 缩短 e2e env:引入后 CI 失败,当时以可能相关为由撤回;后续同签名失败出现在未含该覆写的 main 运行上,证明无因果关系,本记录不将其作为否决依据。 ## 后果 @@ -32,4 +32,4 @@ Runtime System Tests 单次运行约 14m38s:`docker compose up --build` 312s ## 验证 -本地 `docker compose config --format json | jq -r '.services.api.image, .services["sandbox-provisioner"].image'` 解析出 `yuxi-api:0.7.3` 与 `yuxi-sandbox-provisioner:0.7.3`;两个 `docker buildx build --check` 均通过;YAML 解析与两个 job 步骤顺序核对无误;`bash -n` 通过。本地全新 buildx builder 验证 type=local 缓存往返:冷构建 2m36s、热构建 7s 且 20 个步骤 CACHED。CI 实测(run 35823445478):冷运行主 job 14m23s 后按新 key 保存缓存,重跑热缓存构建 90s、主 job 10m15s、Durable job 3m58s,两 job 均 success;`gh run rerun` 前一次失败(e2e env 覆写期间的两次同签名失败见决策)后撤回覆写连续两次 success。合同脚本与发布工作流单测在 paths/预算 fixture 同步后 67 项全部通过。未验证:e2e 在默认 env 下的长期稳定性(失败根因未定位,仅有撤回后恢复的相关性证据);缓存命中依赖 key 涉及文件不变,`backend/uv.lock` 或 Dockerfile 变更会退回冷构建。 +本地 `docker compose config --format json | jq -r '.services.api.image, .services["sandbox-provisioner"].image'` 解析出 `yuxi-api:0.7.3` 与 `yuxi-sandbox-provisioner:0.7.3`;两个 `docker buildx build --check` 均通过;YAML 解析与两个 job 步骤顺序核对无误;`bash -n` 通过。本地全新 buildx builder 验证 type=local 缓存往返:冷构建 2m36s、热构建 7s 且 20 个步骤 CACHED。CI 实测(run 35823445478):冷运行主 job 14m23s 后按新 key 保存缓存,重跑热缓存构建 90s、主 job 10m15s、Durable job 3m58s,两 job 均 success。合同脚本与发布工作流单测在 paths/预算 fixture 同步后 67 项全部通过。缓存命中依赖 key 涉及文件不变,`backend/uv.lock` 或 Dockerfile 变更会退回冷构建。该 e2e 用例的间歇失败先于本变更存在(合入前的 main run 35818088032 同签名失败),本变更不修复也不引入它;根因排查是独立后续工作。