Linear CI 优化:解决 AI 驱动的开发瓶颈
AI 驱动的编码代理极大地提高了代码交付速度,但验证流水线却未能跟上步伐。在 Linear,这种差异使得持续集成(CI)成为主要瓶颈,增加了基础设施成本,并延迟了开发者和代理的反馈。通过实施多层次的优化策略,Linear 将拉取请求的等待时间从 6 分多钟缩短至 5 分多钟,尽管自今年年初以来其测试套件规模几乎翻了两番。
基础设施和工具升级
升级底层硬件和编译器工具链可以立即带来性能提升,而无需更改 CI 流水线逻辑。
- 第三方运行器: 将工作负载从 GitHub Actions 迁移到具有更快 CPU、更高性能存储和更优缓存基础设施的第三方运行器,使各作业的平均速度提升了 34%,其中
tsc(TypeScript 编译器)等工作负载提升了 52%。 - 原生编译: 切换到原生 TypeScript 编译器
tsgo,使tsc检查的每周中位数降低了 73%,有效消除了类型检查这一瓶颈。 - 基于 AST 的代码检查: Linear 重写了自定义代码检查规则,使用基于抽象语法树(AST)的静态分析,而非依赖 TypeScript 类型信息。这使得 ESLint 无需完整类型图即可运行,将 API 代码检查时间减少了 68%,全仓库代码检查时间减少了 55%。
- Oxlint 集成: 迁移到 Oxlint 进一步减少了用于代码检查的总运行器分钟数,因为它在处理基于语法的规则时效率更高。
优化门禁作业
位于关键路径上的作业——即必须完成才能开始其他任何工作的作业——对 CI 总时长有着不成比例的影响。
高效的变更检测
Linear 优化了根据 PR 差异确定要运行哪些测试的初始作业:
- 限制获取深度: 通过限制变更检测作业的获取深度,最慢的门禁从 94 秒降至 20 秒。
- 移除工作树: 对于不需要完整工作树的作业,完全移除了检出步骤,将执行时间从 27 秒降至 7 秒。
- 稀疏检出: 对于提交推送和合并队列事件,使用具有有限历史的稀疏、无 blob 检出,额外节省了 11 秒。
这些更改将变更检测作业的中位持续时间从 26 秒降至 8 秒。
韧性和路径最小化
为了应对第三方运行器与 GitHub 之间的网络不稳定,Linear 用自定义复合操作替换了 actions/checkout,该操作实现了带退避的重试,并设置了 GIT_HTTP_LOW_SPEED_LIMIT 和 GIT_HTTP_LOW_SPEED_TIME 以防止挂起。此外,他们将非必要任务(如写入缓存标记)移出关键合并路径,为每个 API 拉取请求节省了 42 秒。
减少重复的设置开销
设置成本——启动运行器、安装包和配置依赖项——在短期作业中往往比实际测试消耗更多时间。
- 自定义 CI 镜像: Linear 将共享依赖项(例如 Postgres 客户端)移入基础 CI 镜像。这消除了每个分片 7-8 秒的
apt安装时间,并防止了原生构建头文件下载期间偶尔出现的挂起。 - 过滤依赖安装: 在他们的 pnpm monorepo 中,API 测试工作流被更改为仅安装 API 包及其依赖项,而不是整个工作区。这将
pnpm install时间从 44-73 秒降至 16-18 秒。 - 重建与缓存: 测试表明,通过过滤安装重建
node_modules(7.5 秒)比从缓存恢复(28 秒)更快,因此 Linear 放弃了node_modules缓存。 - 模式快照: API 容器现在加载生成的模式快照和引导文件,而不是在每次运行时重放完整的数据库迁移历史,将数据库设置从 12 秒降至 1-2 秒。
- 作业批处理: 七个独立的短检查被合并为两个并发运行任务的作业。这降低了设置开销的频率,每月节省约 87,000 个运行器分钟(占 CI 总使用量的 11.8%)。
提高测试执行效率
一旦设置成本最小化,Linear 便积极并行化 API 测试套件,这是工作流中最大且最频繁的部分。
平衡工作负载
由于 Vitest 按文件而非测试时长分配工作,几个大文件可能会成为分片的瓶颈。Linear 将这些大文件拆分为更小、更集中的文件,并将分片数量从四个增加到八个。这将最慢分片的持续时间从 5.25 分钟降至 4.33 分钟。
模块状态缓存
通过引入一个选择加入的 Vitest 项目并设置 isolate: false,Linear 允许安全的测试文件在每个工作进程内共享模块注册表。这防止了为每个文件重复构建实体、GraphQL 和装饰器图。这是最大的单一改进,将最慢分片从约 300-379 秒降至 195 秒,并将每次运行的 API 分片总运行器时间从 32.8 分钟削减至 22 分钟。
社区观点和反驳
虽然 Linear 的技术方法侧重于基础设施和流水线效率,但社区讨论突出了更广泛的系统性挑战:
- AI 测试的价值: 一些贡献者质疑测试套件翻两番是否反映了价值的相应增长,认为 LLM 可能生成大量样板或琐碎的测试。
- 左移验证: 有人建议将代码检查和单元测试移入代理的本地循环(通过钩子或技能),以便 CI 仅处理资源密集型任务并接收预验证的候选代码。
- 替代工具: 几位开发者提倡使用 Bazel 或 Grog 等构建系统,这些系统利用激进缓存和依赖图,在大型项目中实现约 10 秒的构建时间。
- 移动的瓶颈: 工程师们普遍认为,加速 CI 只是将瓶颈进一步向下游移动,转移到人工代码审查、部署和回滚流程。
“加速 CI 只是将瓶颈转移到审查和部署。代理让队列更嘈杂——但它们并没有发明队列。”
SUMMARY: Linear 通过升级基础设施、优化门禁作业、减少设置开销和提高测试执行效率,缩短了拉取请求等待时间,并将每次测试的运行器时间减半,以跟上 AI 加速编码的步伐。
TITLE: Linear CI 优化:解决 AI 驱动的开发瓶颈
Sources
相关
- Dispatch
- Dispatch
- Dispatch
- Dispatch
- Dispatch