13. CI 的性能优化 2:增量构建、影响面分析与变更集驱动

只跑需要跑的任务:更快、更省、更稳。

本章目标

让 CI 从“每次全跑”升级为“只跑需要跑的”:在不牺牲可信度的前提下,把时间和成本砍下来。

你会掌握

增量构建、影响面分析、变更集驱动(change-set driven)与路径过滤,以及它们的边界与反例。

真实收益

当仓库变大(多模块/monorepo)时,你仍能把 PR 的反馈控制在分钟级,而不是让 CI 变成“半小时彩票”。

CI 优化的第一阶段是“并行 + 缓存”;第二阶段是“只跑该跑的”。
后者更像手术:你要切掉无效工作,但不能切到关键神经。
所以本章不仅讲怎么做,更讲边界:什么时候不能省,什么时候可以大胆省

1) 为什么“只跑需要跑的”这么关键?

当项目规模上来,CI 时间往往不是线性增长,而是指数式爆炸:

如果仍然坚持“每次全跑”,你的 CI 会变成团队的隐形税。

2) 影响面分析:从“改了什么”推导“影响了谁”

影响面分析的核心思路是:

  1. 识别变更集:本次 PR 改了哪些文件/模块?
  2. 沿依赖图传播:哪些模块依赖它?哪些测试覆盖它?
  3. 选择测试集合:只跑“受影响的测试 + 关键兜底测试”。

图 1:影响面传播(动态)

把“全跑”变成“受影响集合 + 兜底集合”。兜底用来防止依赖图不完整导致的漏检。

Changed Module A (modified) 触发影响面 Dependent B depends on A 需要跑相关测试 Dependent C depends on A 需要跑相关测试 Selected Tests Tests(B) + Tests(C) + smoke tests (fallback) 减少漏检风险

实现方式(从简单到高级)

3) 增量构建:让“同样的构建”越来越快

增量构建解决的是:同一项目在相似变更下,重复工作占比很高。

图 2:增量构建缓存链(动态)

把构建视为函数:输入相同 → 输出相同。只要输入指纹正确,就能安全复用结果。

Inputs source + deps + toolchain fingerprint Cache restore / save hit → skip work Outputs build artifacts deterministic
增量构建的底线:输入指纹必须正确。指纹不正确,缓存命中会导致“快但错”。
一条经验:宁可多失效一点,也不要误命中。

4) 变更集驱动(change-set driven):把 CI 做成“路由器”

变更集驱动强调:CI 不是“跑全部任务”,而是根据变更集选择任务图(job graph)。

典型规则:

图 3:变更集驱动流水线(动态)

把流水线当“路由器”:变更从入口进入,按规则分流到不同任务集合,最终汇总成一个可信结论。

Change-set files / modules 输入信号 Router (Rules) path filters / dependency rules 选择任务图 收敛成本 Jobs A unit/lint Jobs B integration

5) 边界与兜底:什么时候不能省?

专业的做法是:在“省”与“稳”之间建立一条硬规则——关键链路永远有兜底 smoke tests

本章小结:从“全跑”到“智能路由”

← 上一章:并行/矩阵/缓存 下一章:质量门禁 1(Lint/SAST)→