AI 写代码时代,如何加速 CI

AI 写代码时代,如何加速 CI

💡 原文英文,约1700词,阅读约需7分钟。
📝

内容提要

AI编码代理导致提交量激增,CI成为瓶颈,需加速GitHub Actions流水线。五种方法:先测量各步骤耗时,区分排队与运行;用稳定键缓存依赖和Docker层;将重任务迁移到更快硬件;用矩阵分片并行测试;通过路径过滤、仅测受影响包和并发组取消过期运行来减少无用工作。建议逐项改动并复测,优先优化高频任务。

🔎

延伸解读

先测量再优化,避免凭感觉调优

文章强调多数团队会猜错瓶颈,比如以为测试慢,实际可能是安装依赖占了大头。建议打开最近十次最慢工作流的运行记录,取各步骤耗时的中位数,并区分排队、准备和运行时间。排队久调测试没用,运行久才需优化步骤。先有数据再动手,能避免把时间花在错误环节。

缓存键要稳定,Docker 分层顺序有讲究

缓存能避免重复下载依赖,但键的设计决定成败。用锁文件哈希生成键,依赖不变则键不变;加上时间戳或提交 SHA 会导致每次都不命中。restore-keys 可在精确键未命中时回退到较旧缓存。Docker 构建应先复制锁文件装依赖,再复制源码,这样代码改动不会重建安装层。注意缓存恢复是网络下载,大缓存可能抵消收益。

并行分片有上限,跳过工作要防卡检查

测试分片能把长套件拆到多个矩阵任务并行,但每个分片都有准备成本,分片过多反而增加开销。路径过滤可跳过无关改动,但若必需检查因过滤从未运行,PR 会卡在等待状态;应让工作流运行并用条件跳过任务。单体仓库可用 Nx、Turborepo 只跑受影响包,但需检出足够 Git 历史。并发组取消过期运行适合普通推送,部署流程则应排队而非取消。

❓

Q&A

AI 编码代理导致提交量激增,为什么 CI 会成为瓶颈?

AI 编码代理能快速生成大量提交,例如 GitHub 每周处理 2.75 亿次提交,GitHub Actions 每周使用 21 亿分钟。当代理在一下午打开十个 PR 时,原本可容忍的 15 分钟流水线会变成队列,导致等待结果和重试的时间抵消了写代码节省的时间。

如何找出 GitHub Actions 工作流中最慢的步骤?

利用 GitHub 显示的每次运行中每个步骤的执行时间。打开最慢工作流的最近十次运行,记录耗时最长的三个步骤,使用中位数而非最差情况,并区分排队时间、设置时间和运行时间,因为它们的优化方法不同。

怎样为 GitHub Actions 配置依赖缓存才能有效命中?

使用 actions/cache,指定路径和基于锁文件哈希的稳定键,例如 key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }},并添加 restore-keys 以在精确键未命中时恢复最近缓存。避免在键中使用时间戳或提交 SHA,否则缓存永远不会重用。

如何优化 Docker 构建以利用缓存?

先复制锁文件并安装依赖,再复制源代码,这样代码变更不会重建安装层。使用 BuildKit 的 cache-from 和 cache-to 设置为 type=gha,将层缓存保存到 GitHub Actions 缓存后端,以便跨运行重用。

有哪些方法可以并行化测试以缩短 CI 时间?

首先移除不必要的 needs 依赖,让独立任务并行。然后使用矩阵策略分片测试,例如 Jest 的 --shard 标志或 Playwright 的 --shard,将测试套件分成多个并行作业。设置 fail-fast: false 以查看所有失败。注意分片有上限,因为每个分片都有设置成本。

如何避免运行不必要的 CI 工作?

使用路径过滤器(paths 和 paths-ignore)仅在相关文件变更时触发工作流;在 monorepo 中使用 Nx、Turborepo 或 Bazel 只运行受影响的测试;使用并发组(concurrency)取消过时的运行,但不要用于部署工作流。

🏷️

标签

➡️

继续阅读