我們如何運用 AI 讓 CI 更加嚴格、可觀測,並且更容易跨儲存庫進行改進。
在實作與交付端都有經驗後,我學到在當前的 AI 時代,複雜的需求不一定是最主要的問題。
AI 可以幫助我們拆解需求、探索不熟悉的儲存庫,並產生實作構想。這使得實作步驟變得更容易。
但實作只是交付的一環。功能仍然必須通過真正的工程系統。
它必須符合儲存庫、CI 規則、審查流程以及部署路徑,才能順利交付。
隨著實作速度加快,周遭的工程系統變得更加重要。真正的挑戰在於確保每一項變更都經過測試、符合需求審查,並且可以安全合併。
超越被取代的恐懼
目前存在許多關於 AI 取代開發者的恐懼。
其中部分擔憂是合理的。當例行實作任務可以由 AI 協助生成、測試並審查時,入門級機會可能會變得更有限。
這是一個重要的挑戰,特別是對於想要獲得第一次軟體開發機會的人而言。
但我並不認為這是開發者角色的終結。
我認為這是軟體工作最令人興奮的時期之一。
價值正在轉移。
撰寫例行程式碼的差異化程度正在降低。理解問題、提出正確的問題、驗證行為、做出取捨,以及為結果承擔責任,這些能力正變得更加重要。
AI 可以產生實作,但它不會自動理解商業脈絡、隱藏的限制、營運風險,或是該方案是否適合團隊。
這就是為什麼工作流程品質至關重要。
受益最大的開發者,不一定是那些要求 AI 生成最多程式碼的人,而是那些能夠在有紀律的流程中使用 AI 的人:定義需求、檢視證據、測試結果、審查風險,並改善周遭的系統。
對於初級開發者而言,路徑可能改變,但並未消失。基礎知識、除錯、溝通、產品理解,以及與 AI 有效協作的能力,將變得更加重要。
這種視角轉變,改變了我們處理 CI 的方式。我們沒有先問如何讓它跑得更快,而是問如何讓它捕捉更多正確的問題。
真正的工作是強化 CI 工作流程
最近,我們處理了一個 GitLab CI 工作流程,它包含多項職責:
- 當建立合併請求時,將連結的議題移至
Status::In Review。 - 合併後將議題移至
Status::Done。 - 對整個合併請求執行 AI 審查。
- 當 AI 審查確認有關鍵或高嚴重性問題時,阻擋管線。
- 當合併請求不包含關閉參照時,留下留言。
重要的部分不只是新增更多 CI 工作。
我們運用 AI 檢視工作流程本身,並提出更好的問題:
Status::In Review是否證明合併請求確實與工單連結?Status::Done是否僅在真正合併至預設分支後才執行?- AI 發現是否可以在沒有具體證據的情況下阻擋合併?
- 當合併請求缺少關閉參照時,會發生什麼事?
- 哪些檢查是通用政策,哪些檢查屬於單一儲存庫?
這些問題將 CI 從一組指令轉變為品質管制系統。
目標不是讓 CI 變得更複雜,而是讓每項決策更加明確:哪些是自動檢查的、需要哪些證據,以及什麼應該阻擋合併。
AI 在管線中的實際運用方式
AI 審查並非開發者必須手動執行的獨立工具,而是當合併請求以預設分支為目標時,會自動執行的 GitLab CI 工作。
設定包含四個簡單部分:
- 在 CI 工作中安裝固定版本的 AI CLI。
- 由小型儲存庫指令碼收集合併請求內容。
- AI 回傳結構化的 JSON 報告。
- 另一個工作評估該報告,並決定管線是否通過。
此工作使用固定版本的 AI CLI,而非安裝最新版本:
ai_review:
image: node:22-bookworm-slim
before_script:
- npm install --global @openai/codex@<pinned-version>
script:
- python scripts/ai_review.py review
進入全螢幕模式 離開全螢幕模式
在本例中,AI 透過 OpenAI Codex CLI 存取。具體的 CLI 可能有所不同,但重要的是版本必須明確,且工作在隔離的 CI 環境中執行。
儲存庫指令碼不會盲目將整個儲存庫傳送給模型。它只收集審查所需的內容:
- 合併請求描述;
- 連結的關閉議題及其需求;
- 變更的檔案與差異;
- 變更周圍的相關檔案內容;
- 目前的 commit SHA 與目標分支。
提示詞也定義了 AI 允許得出的結論。例如,需求會標記為 Covered、Partial、Missing 或 Not verifiable。發現必須包含類別、嚴重性、受影響路徑、證據、影響與建議。
回應在使用前會根據 JSON 結構描述進行驗證。報告會儲存為 CI 構件,並以合併請求留言的形式張貼。這使得推理過程可見,並為下一個工作提供穩定的輸入。
憑證依職責分離:
- AI 存取權杖允許審查工作呼叫 AI 工具;
- GitLab 自動化權杖允許工作流程讀取合併請求資料,並更新留言或標籤。
兩者皆以遮罩的群組層級 CI 變數進行管理。審查工作使用 AI 權杖。閘門工作不需要呼叫 AI,因此它會使用報告構件,並從其環境中移除 AI 權杖。
這種分離有兩個原因。它限制了敏感憑證的暴露範圍,並防止最終閘門再次發出 AI 請求,以免結果與已審查的報告不同。
實際流程如下:
合併請求
-> 收集 GitLab 內容
-> 執行結構化輸出的 AI 審查
-> report.json 構件與留言
-> 確定性閘門
-> 通過或阻擋管線
進入全螢幕模式 離開全螢幕模式
因此,AI 用於分析與解釋。GitLab CI 仍負責驗證輸出、檢查 commit、更新合併請求,以及執行最終政策。
封裝改進的工作流程,而非儲存庫
共享元件是實用的成果,但不是主要的改進。主要改進是讓 CI 政策明確且可執行。一旦明確,我們就可以封裝可重用的部分。
改進工作流程後,下一個問題很簡單:
我們真的需要在每個儲存庫中手動設定相同的工作流程嗎?
答案仍然是否定的。
我們沒有將改進後的 .gitlab-ci.yml 邏輯複製到每個儲存庫,而是建立了一個共享的 GitLab CI 元件。
使用端儲存庫只需引入共享範本:
include:
- project: your-group/ci-components
ref: v0.1.0
file: /templates/issue-ai-review.yml
進入全螢幕模式 離開全螢幕模式
共享元件提供:
issue_status_in_reviewissue_status_doneai_reviewai_review_gate
儲存庫仍擁有自己的建置、lint、單元測試、E2E 以及部署工作。
這種分離很重要。
Go 儲存庫不應被迫使用 Python 儲存庫結構。前端儲存庫不應繼承後端測試指令。
但兩個儲存庫仍可能需要相同的合併請求政策。
可重用的部分是品質政策,而不是管線中的每個指令。
AI 審查需要確定性邊界
AI 審查很有用,但 AI 回應不應直接決定合併請求是否可以合併。
AI 審查者會產生結構化報告。它會評估工單涵蓋度、正確性、回歸風險、安全性、效能、可維護性及其他類別。
關鍵與高嚴重性發現會被獨立驗證。
最終閘門會檢查確定性條件:
- 報告是否針對目前的 commit?
- 發現是否已獨立確認?
- 嚴重性是否仍需阻擋?
- 報告產生後是否新增了人工覆寫?
這為我們提供了更好的邊界。
AI 適合對大型合併請求進行推理。
管線負責執行政策。
這種區分很重要,因為 AI 輸出是機率的,而合併閘門應是可預測的。
讓工作流程可安全重用
工作流程的品質不只來自 AI 步驟。我們也需要讓自動化可預測且可安全重用。
缺少關閉參照會變得可見
如果合併請求不包含如 Closes #123 的參照,管線會自動留下留言說明缺少什麼。
工作也會失敗,因此問題在合併前就會被發現。更新描述後,可以重試管線。
固定共享元件版本
每個儲存庫使用特定元件版本,例如 v0.1.0,而不是靜默跟隨最新變更。
這表示更新共享 CI 不會意外改變每個儲存庫。儲存庫可以在變更經過審查後再更新版本。
使用專用機器人進行自動化
工作流程需要憑證來更新議題標籤與留言。這些憑證儲存在群組層級,並屬於專用 CI 機器人,而非開發者的個人帳戶。
這讓所有權留在團隊手中,並讓自動化在人員或職責變動時更容易維護。
保留儲存庫特定檢查在本地
共享元件處理通用的合併請求政策。每個儲存庫仍定義自己的建置、lint、單元測試、E2E 以及部署工作。
標籤也可以依儲存庫設定。Go 專案與 TypeScript 專案不需要因為共享相同的審查政策,就使用相同的指令。
結果是共用的品質標準,而不假設每個儲存庫都有相同的結構。
工程領導力有什麼改變?
AI 改變了瓶頸。
以往,大部分工作是將需求轉譯為程式碼,並手動檢查 CI 工作流程是否捕捉到預期政策。
現在,AI 可以大幅減少這些實作摩擦。
工程領導角色更專注於:
- 定義可重用的邊界;
- 決定哪些檢查必須保持確定性;
- 將重複的政策轉為自動化;
- 讓 AI 輸出可驗證;
- 保留各儲存庫之間的彈性;以及
- 確保速度不會移除流程中的證據。
工作仍然複雜。
但複雜度可以組織成更小、可重用的系統。
最終重點
複雜需求仍需謹慎思考。
AI 並未消除對架構、測試或審查的需求。
但它改變了什麼是可行的。
原本依賴人工檢查的審查流程,可以變成自動化、基於證據的閘門。
一旦品質政策明確,重複的 CI 邏輯就可以變成版本化的共享元件。
最大的改進不只是更快寫程式碼。
而是建立一個系統,讓複雜的工作更容易協調、驗證與重用。
這正是 AI 為工程團隊創造最大槓桿效應之處。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.