Linear CI 優化:解決 AI 驅動開發的瓶頸
AI 驅動的程式碼代理大幅提升了程式碼交付速度,但驗證流程卻未能跟上步伐。在 Linear,這種差異使持續整合(CI)成為主要瓶頸,增加了基礎設施成本,並延遲了開發者與代理的反饋時間。透過實施多層次的優化策略,Linear 將合併請求的等待時間從超過 6 分鐘縮短至僅略超過 5 分鐘,即使今年以來測試套件的規模幾乎增加了四倍。
基礎設施與工具鏈升級
升級底層硬體與編譯器工具鏈可在不改變 CI 流程邏輯的情況下立即獲得性能提升。
- 第三方執行器: 將工作負載從 GitHub Actions 移至具有更快 CPU、更高性能儲存與優秀快取基礎設施的第三方執行器,使各工作平均提速 34%,部分工作(如
tsc(TypeScript 編譯器))更提升了 52%。 - 原生編譯: 改用
tsgo,一個原生 TypeScript 編譯器,將tsc檢查的每周中位數時間減少 73%,有效消除了類型檢查的瓶頸。 - 基於 AST 的靜態檢查: Linear 將自訂的 lint 规則重寫為使用抽象語法樹(AST)進行靜態分析,而非依賴 TypeScript 類型資訊。這使得 ESLint 可以在不依賴完整類型圖的情況下運作,將 API lint 時間減少 68%,全倉儲 lint 時間減少 55%。
- Oxlint 整合: 改用 Oxlint 進一步降低了 linting 所耗的執行器分鐘數,因其在處理基於語法的規則時效率更高。
優化門檻工作
位於關鍵路徑上的工作——那些必須在其他任何工作開始前完成的工作——對總 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 多倉儲中,API 測試工作流程改為僅安裝 API 套件及其依賴,而非整個工作區。這使
pnpm install時間從 44-73 秒降至 16-18 秒。 - 重建 vs. 快取: 測試顯示,透過過濾安裝重建
node_modules(7.5 秒)比從快取還原(28 秒)更快,因此 Linear 放棄了node_modules快取。 - 資料庫結構快照: 改為在每次執行時載入生成的資料庫結構快照與啟動檔,而非重播完整的資料庫遷移歷史,將資料庫設定時間從 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 可能產生大量範本或無意義的測試。
- 左移驗證: 有人建議將 linting 與單元測試移入代理的本地循環(透過 Hooks 或技能),使 CI 僅處理資源密集型任務,並接收已預先驗證的候選者。
- 替代工具: 多位開發者提倡使用 Bazel 或 Grog 等建構系統,這些系統透過激進的快取與依賴圖,可在大型專案中實現 10 秒級的建構時間。
- 移動的瓶頸: 工程師中普遍存在一種共識:加快 CI 只是將瓶頸進一步推至人工程式碼審查、部署與回滾流程。
"加快 CI 只是將瓶頸移到審查與部署。代理讓佇列更嘈雜——它們並未創造它。"
Sources
相關
- Dispatch
- Dispatch
- Dispatch
- Dispatch
- Dispatch