Skip to content

CI 关键路径 frontend 半:workbench coverage 单点 7m35s = 墙钟 96% #2251

Description

@DeliciousBuding

来源:round-65 主机侧 CI 关键路径实测(operator 明确要求「加速,别把时间浪费在等 PR」)。证据取自两次已完成的真实 run,非估算:

  • Go-only PR:run 33674961074chore/round-64-wave,HEAD=4a7af8c6 前一轮),19:42:55 → 19:51:31 = 8m36s
  • Frontend-only PR:run 33676372418fix/desktop-menu-i18n-forward),19:57:12 → 20:05:07 = 7m55s

仓库 TokenDanceLab/AgentHub = PUBLICgh repo view --json isPrivate = false)⇒ Actions 分钟不计费,用并行度换墙钟时间是纯收益,不需要在「省分钟」和「省等待」之间取舍。

关键路径实测拆解(Go-only PR,8m36s)

阶段 起→止 耗时 是否在关键路径
排队 + Detect changed paths 19:42:55 → 19:43:41 46s ✅(job 自身只跑 6s,其余是 runner 启动/排队)
go-hub-test (2) 19:43:44 → 19:48:35 4m51s
go-hub-test (1) 19:43:44 → 19:46:27 2m43s ❌(早 2m08s 结束,白等)
go-hub(lint+ratchet+coverage merge+gosec+vet+staticcheck+依赖方向门) 19:48:38 → 19:51:23 2m45s ✅(串行挂在 test 之后
backend-required 19:51:27 → 19:51:31 4s

并行侧(同一时刻起跑、都早于关键路径结束):go-edge-test 两 shard ≤2m52s、go-edge 1m34s、windows-go ≤2m45s、backend-integration 3m06s、backend-e2e ≤1m17s、docker 1m59s、govulncheck ≤29s。即:8m36s 里有 5m30s 完全由「hub 测试最慢 shard + hub 串行尾巴」两段决定,其余 20 多个 job 全程在等它俩。

关键路径实测拆解(Frontend-only PR,7m55s)

阶段 耗时
排队 + changes ~40s(job 自身 7s)
Frontend coverage baseline (@agenthub/workbench) 19:57:29 → 20:05:00 7m31s ← 唯一长杆
frontend-desktop (1/2) 3m43s / 3m36s
Native Windows frontend (desktop/web) 4m10s / 3m40s
Frontend (web) / Visual QA / stubbed E2E ≤1m46s
frontend-required 3s

Go 侧全部按 path filter 正确跳过(go-edge/go-hub/windows-go/backend-required 各 2-6s 报绿),说明路径过滤本身是健康的,问题只在两条长杆。

切片 1(收益最大、风险最低):把 go-hub / go-edge 的静态检查从「测试之后」搬到「与测试并行」

现状 checks.yml:270-271 go-hub: needs: [changes, go-hub-test],job 内顺序是:
Lint(golangci --timeout=5m)verify-hub-lint-ratchet.py → ratchet 自测 → download-artifact(shard 覆盖率) → merge-coverprofiles.pyCoverage check (>=40%) → gosec → go vetstaticcheck

其中只有 download/merge/coverage 三步真的需要 shard 产物;lint、ratchet、gosec、vet、staticcheck 一步都不需要,却被 needs 强行排在 4m51s 之后。

修法:拆成

  • go-hub-staticneeds: changes,与 go-hub-test 同时起跑)= checkout + setup-go + Lint + ratchet + ratchet 自测 + gosec + vet + staticcheck;
  • go-hub(保留同名 required checkneeds: [changes, go-hub-test, go-hub-static])= 只做 download-artifact + merge + coverage 门 + 两个 fail-closed/skip 兜底 step,并断言 go-hub-static.result == success

go-edge 同构处理(尾巴 1m34s,含 verify-orchestrator-deps.py + 自测)。

预期:Go PR 关键路径 46s + max(4m51s, ~2m45s) + ~25s ≈ 5m50s净省 ~2m45s(-32%)

切片 2:go-hub-test / go-edge-test 的 shard 轮询不均衡(注释自称 balanced,实测不 balanced)

checks.yml:213-215 注释原文:「packages from go list ./... are split round-robin (NR%2) — balanced and disjoint」。实测 hub:shard2 4m51s vs shard1 2m43s,差 2m08s ⇒ disjoint 成立、balanced 被推翻(与 #2246「注释声称被活代码推翻」同族,此处是被 CI 实测推翻)。

修法(择一,需实测后定):

  1. matrix.shard: [1,2,3] + NR % 3,同步改 merge-coverprofiles.py 调用处的 shard 文件名列表(当前硬编码 shard-1.out shard-2.out,见 checks.yml:334-339);
  2. 或保留 2 shard,但把已知重包显式钉到轻 shard(需要一个可复核的成本表,不接受拍脑袋)。

预期:hub 测试段 4m51s → ~3m20s,叠加切片 1 后 Go PR ≈ 4m30s(-49%)

切片 3:frontend 长杆 @agenthub/workbench coverage baseline 7m31s

它是 frontend PR 的唯一长杆(第二名 3m43s)。需先定位耗时构成(vitest 全量 + coverage 转换 + 是否重复 build),再决定:按 test file 分 shard / 降低 coverage instrument 范围 / 复用已构建产物。本切片要求先出「耗时构成实测」再改,不接受未测量的优化。

验收(不可伪造)

  1. 改动前后各取一次同类型真实 run(Go-only 一次、frontend-only 一次),在 issue 里贴 gh run view <id> --json jobs 的关键路径表(job 名 / startedAt / completedAt),证明 Go-only 总时长从 8m36s 降到 ≤6m00s(只做切片 1)或 ≤5m00s(切片 1+2)。
  2. 7 个 required check 名一字不改validate / go-edge / go-hub / windows-go / windows-frontend / backend-required / frontend-requiredgh api .../branches/master/protection 前后 diff 为空(不需要也不允许动 branch protection)。
  3. 三个兜底语义必须保留并各自有证据:path filter 未选中 → 报绿 no-op;changes job 自身失败 → fail-closed 报红;!cancelled() 让 skip 不阻塞保护。
  4. 门禁全绿:python scripts/verify/verify-doc-ssot.pybash scripts/verify/verify-commit-messages.shgit diff --check;checks.yml 若被 docs/architecture/github-actions-ci-cd-policy.md 引用为 SSOT,同步更新该文档(verify-doc-ssot.py 会抓)。

负向约束

  • enforce_admins: true:一旦 needs 图写错导致某个 required check 永不报结果,所有 PR 都会被永久阻塞且管理员无法绕过。因此本切片只能以 PR 形式验证,禁止直接 push master;PR 上必须先看到 7 个 check 全部报出结果再合并。
  • .github/workflows/checks.yml 会让 changes所有 filter 命中(desktop/web/shell/go/mobile/frontend/design_css 都把该文件列入),⇒ 该 PR 会跑全矩阵(实测两条关键路径并行,预计 ~9-10min,不是叠加)。这是一次性成本,但必须单独成 PR,不要和实现批混在一起,避免把 Go-only 快批拖成全矩阵。
  • 不得为了提速删门(coverage 阈值、ratchet、gosec、staticcheck、Windows 合同、path filter fail-closed 一个都不能少);只允许改执行顺序与并行度
  • 不得改 concurrency 组语义(cancel-in-progress: true 是「连推取消旧 run」的既有节流约定)。

依赖 / 排期

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions