为什么你的持续集成越做越慢?换个思路可能更有效

🔑 关键词:持续集成, CI优化, 反馈式CI, 门禁式CI, 云原生CI

📖 摘要:本文从个人实战出发,对比传统门禁式CI与现代反馈式CI的核心差异,指出CI变慢的常见根源,并提供几个非主流但好用的优化方向。适合正在被流水线拖垮的团队。

为什么你的持续集成越做越慢?换个思路可能更有效

图片

先说个数据:我们团队去年把全量单测从45分钟减到7分钟,不是靠加机器,而是砍掉了接近一半的断言。是的,你没听错,删测试让构建更快了。但这不是在教大家偷懒,而是让我意识到:绝大多数CI系统根本不是被代码量拖慢的,而是被一堆"看起来有用其实没人看"的检查堆满的。传统Jenkins那种串行pipeline,每个stage都要等上一个结束,如果第3步的Sonar扫描锁表,后面全卡住——这种问题我盯了两个通宵才定位到是社区版的并发缺陷。

图片

我见过很多团队把CI当成交警:跑全量测试、静态扫描、覆盖率缩水小限、安全漏洞、镜像扫描、提交信息校验……每增加一个门禁,部署就会往后退一步。结果就是CI变成了那个天天喊狼来了的小孩,大家看到红灯第一反应是"哦,又是那个超时case"然后跳过。说实话,这还算好的,有些项目经理要求"必须全绿才能合入",于是所有人开始给测试加跳过标记,或者干脆把失败测试用注释包起来。一套豪华流水线,最后成了虚拟摆设。

图片

最近两年流行"反馈式CI",核心思路很反直觉:不是跑的越多越好,而是跑得越快越好。GitHub Actions和Buildkite这类云原生工具其实只是把手,真正关键是你要能忍受把测试拆碎,按修改的文件精确跑子集。比如我们改了个支付模块的DTO字段,就只跑那三个服务里相关的测试,而不是全仓900个用例。刚开始老大不信,说这么搞会漏测。但两周后线上出了个事故,正好是改动模块依赖的另一个服务,而那个服务的测试根本没触发——这次事故让我明白,光有反馈式CI还不够,还得有个"变更影响地图",就是把改的东西能影响到的测试范围做成一个动态集合,这需要点代码分析功底,但做到后被省下的时间非常惊人。

图片

最后说个自己的观点:CI应该是一种有节奏的"碎碎念",而不是一锤定音的"终审判决"。理想状态是提交后1分钟内得到关键反馈(编译、那部分单测、lint),再花5分钟得到全量但可读的摘要。别动不动就上k8s做几百个并行job,成本可不是开玩笑的。我们试过用spot实例做动态扩容,费用是原来的4倍,换来的是平均节省2分钟——这笔账怎么算都亏。真正该做的是让开发者学会看日志,把pipeline里所有的warning都清掉,哪怕测试不跑也要看得懂。工具能帮你做并行、缓存、增量化,但没法替你判断"哪些反馈值得等"。这需要团队自己摸索,不要照着网上那些"最佳实践"抄,因为你的业务、你的同事的心态,跟别人完全不一样。

图片