Pull Request 堆在待審清單裡,資深工程師花兩小時逐行看程式碼,結果還是漏掉了某個邊界條件沒處理;新人寫的程式碼風格與團隊不一致,審查意見來回改了五輪才過關。這類「人肉審碼」是工程團隊最常見的瓶頸:慢、主觀、而且品質取決於當天誰有空、心情好不好。這篇是操作配方:用 GitHub Copilot、CodeRabbit、SonarQube 與 LLM 節點串出一條自動化審查流水線,讓機器做初步篩選與風險分級,人只處理真正需要判斷的高風險變更。全文最重要的一節是第五節——哪些環節可以交給靜態分析工具,哪些環節必須由 LLM 做語義理解,這條邊界畫錯了,自動化會比人工更危險。
這個場景解決什麼
適合這個配方的流程有四種特徵:高頻率(每天都有 PR)、跨模組(變更影響多個服務或層級)、規則說得清楚(團隊有 coding guideline)、繁瑣但必須做。四者俱備的人工審查,通常有三種損耗:延遲(PR 等半天沒人看)、漏檢(邊界條件、異常處理被忽略)、不一致(不同審查者標準不同)。
做完這個配方之後的目標狀態:低風險變更自動通過初審並給出建議,高風險變更被標記並推到人面前,附帶結構化的審查要點。人的角色從「每一行都看」變成「只看 flagged 的部分」。
同時畫清邊界:這篇處理的是程式碼品質與安全性的初步篩選,不是要你用 AI 取代架構決策;需要業務邏輯判斷與權衡取捨的環節(例如「這個設計是否符合長期演進方向」)也不在自動化範圍內。判斷一個場景值不值得自動化,先讀什麼時候不該用 AI。
工具組合與前置準備
- GitHub Copilot:GitHub 推出的 AI 編程助手,內建於 VS Code 與 JetBrains IDE,支援程式碼補全、解釋、重構建議。企業版提供自訂提示詞與團隊知識庫整合。定價以官網為準;接通後第一件事是在組織設定中限制可訪問的倉庫範圍。
- CodeRabbit:專為 PR 審查設計的 AI 工具,能讀取 diff、理解上下文、給出具體改進建議,並支援與 GitHub/GitLab 深度整合。優點是專注於審查場景,提示詞已針對此任務優化;缺點是需要額外訂閱。方案與定價以官網為準。
- SonarQube:開源代碼品質平台,支援 30+ 語言的靜態分析,涵蓋 bug、漏洞、代碼異味、重複率等維度。可自架或採用雲端版 SonarCloud。自建與採購的系統性取捨見自建還是採購。
- LLM API(本文以 DeepSeek 為例,任何供應商皆可):負責流程中「語義理解」與「自然語言生成」的判斷。單價以供應商官網為準;接通後第一件事是在供應商控制台設定花費上限與用量告警。
前置檢查表——每一項都有明確答案才動工:
| 檢查項 | 要確認什麼 | 沒確認就做的後果 |
|---|---|---|
| 倉庫權限 | CI/CD 帳號是否有讀取 PR、寫入評論的權限 | 流程跑完但無法回寫審查意見 |
| 編碼規範 | 團隊是否有書面 coding guideline、lint 規則 | AI 給出的建議與團隊習慣衝突,造成混亂 |
| 資料分級 | 程式碼是否包含敏感資訊(金鑰、內部 API);能否傳給外部 LLM | 敏感程式碼流經未經評估的工具,合規事故 |
| 維運責任 | 上線後誰看告警、誰調整提示詞與規則 | 誤報太多導致團隊關閉自動化,比沒有更糟 |
資料分級的判斷方法見企業資料安全基本盤。
憑證紀律(先講,因為最常被忽略):所有 API Key、OAuth Token 放進 CI/CD 平台的 secrets 機制;不要寫死在 workflow 檔案、註解或說明文件裡;不要把含憑證的配置檔提交到公開倉庫。
一、盤點人工審查痛點
花兩週,把所有 PR 審查中的常見問題列成一張表:
| 問題類型 | 發生頻率 | 平均發現時間 | 修復成本 | 現在誰發現 |
|---|---|---|---|---|
| 缺少異常處理 | 每週 3-5 次 | 測試階段或上線後 | 高(需熱修復) | 資深工程師 |
| 變數命名不一致 | 每天 2-3 次 | 審查當下 | 低(立即修改) | 任意審查者 |
| 潛在 SQL Injection | 每月 1-2 次 | 安全掃描或滲透測試 | 極高(資安事故) | 安全團隊 |
| 重複程式碼 | 每週 1-2 次 | 代碼重構會議 | 中(技術債累積) | Tech Lead |
兩個填寫紀律:頻率與成本是從實際 issue tracker 與 git log 統計出來的,不靠印象——口頭回憶幾乎總是低估;修復成本要寫具體事件(哪次 hotfix、花了多少人天),寫不出成本的問題,說明它可能根本不值得優先自動化。
這張表有兩個用途:下一步的選型依據,以及上線後計算效益的基線。「自動化前平均每筆 PR 審查多久、自動化後例外處理要多久」都從這張表與後面的執行紀錄算出來——自己測的數字,比任何文章裡的參考值可靠。
二、選一條最痛的審查流程
四個條件同時成立才動手:頻率高(每天發生)、規則寫得出來(能寫成給新人的說明)、出錯有代價(漏檢會出事)、工具鏈有介面。
兩類流程先避開:業務邏輯極度複雜且無文檔的(AI 無法理解上下文,誤報率過高);團隊規範尚未統一的(今天說 A 明天說 B,自動化追不上變化)。
第一版切小:只做「PR 開啟 → 靜態分析 → 安全掃描 → LLM 語義審查 → 風險分級 → 評論回寫」這一條主幹。客製化規則、歷史程式碼批量掃描全留到第二版。一條穩定跑通的主幹,勝過一張完整但沒上線的設計圖。
三、自架還是雲端
| 考量點 | 自架 | 官方雲端 |
|---|---|---|
| 資料位置 | 程式碼與分析結果在自己環境,適合分級要求高的專案 | 程式碼經供應商環境,須先過資料分級這一關 |
| 維護責任 | 升級、擴展、停機處置都是你的 | 供應商負責 |
| 起步速度 | 需要伺服器資源與基本 DevOps 能力 | 註冊即用,幾分鐘內完成整合 |
| 預算形態 | 伺服器費用加維運人力 | 訂閱制,金額以官網為準 |
決策方法:資料分級結果說「不能出網」時,自架 SonarQube 幾乎是唯一選項;否則先用 CodeRabbit 或 GitHub Copilot Enterprise 把第一條流程跑通,累積了真實用量與失敗紀錄,再評估要不要遷移。不論哪種,都先用測試分支跑通示範流程,第一天不碰生產倉庫。
四、串出最小可跑版本
節點組裝順序:
- 觸發節點:GitHub Actions 的
pull_request事件觸發。優先事件型觸發,退而求其次才用定時輪詢。 - 靜態分析節點:執行 SonarQube Scanner 或 ESLint/Pylint,輸出結構化的警告清單。
- 安全掃描節點:執行 SAST 工具(如 Semgrep、Bandit、Checkov),檢測常見漏洞模式。
- LLM 語義審查節點:將 diff 內容、相關檔案上下文、團隊規範送入 LLM,要求輸出結構化的審查意見 JSON。
- 風險分級節點:根據靜態分析結果、安全掃描等級、LLM 評分,計算綜合風險分數(低/中/高)。
- 評論回寫節點:將審查意見以 GitHub Comment 或 Review API 回寫到 PR,高風險項目 @ 指定審查者。
試跑期三條紀律:
- 用測試分支:建立
feature/test-pr分支,故意放入已知問題(缺少錯誤處理、硬編碼密碼),驗證工具能否正確檢測。 - 留執行紀錄:除平台內建的執行歷史外,為重要流程加一個「台帳」分支——每次執行把時間、PR 編號、風險等級、檢測到的問題數寫進一張專用表格或資料庫。這是第八節監控的原料。
- 影子模式上線:自動化先與人工並行跑幾天——機器給出建議但不強制阻擋,人照樣審查,逐日比對兩邊結果。連續一致之後才讓自動化接管部分低風險 PR,人轉為抽查。
五、哪些環節交給靜態分析、哪些必須用 LLM
這是全文最重要的一節。原則一句話:確定性的模式匹配給靜態分析工具,LLM 只做「語境理解」這一類規則寫不盡的事。
| 環節 | 用什麼 | 為什麼 |
|---|---|---|
| 語法錯誤、未使用變數、重複程式碼 | SonarQube / ESLint / Pylint | 同樣輸入必須同樣輸出;這些是確定性規則,LLM 做不到這個保證 |
| 常見漏洞模式(SQLi、XSS、硬編碼金鑰) | Semgrep / Bandit / Checkov | 基於 AST 或正則的模式匹配,準確率高且可解釋 |
| 變數命名是否符合團隊習慣 | LLM 節點 | 「習慣」難以用規則窮舉,LLM 能理解語境與意圖 |
| 這段程式碼的可讀性與維護性評估 | LLM 節點 | 主觀但重要的維度,需要語義理解 |
| 變更是否影響上下游模組 | LLM 節點+依賴圖分析 | 需要理解呼叫關係與數據流,靜態分析只能給出部分答案 |
| 審查意見的自然語言表達 | LLM 節點 | 但意見裡的程式碼片段由靜態分析工具原樣注入,LLM 不得改寫任何程式碼 |
兩條鐵律:
- 程式碼片段永遠不經過 LLM 的嘴。 這些內容由靜態分析工具原樣提取;LLM 只產語言,不產事實。自動化審查裡代價最高的事故,形態幾乎都是「模型改寫了一行程式碼,而且改得很像真的」。
- LLM 輸出永遠當作不可信輸入。 LLM 節點要求輸出固定結構的 JSON(欄位在提示詞裡逐一列舉);下游第一個節點做格式校驗,校驗不過直接進例外分支,不允許「盡量解析」。
LLM 節點的提示詞寫法:給審查維度枚舉(安全性、可讀性、效能、一致性)、給輸出 JSON 的欄位定義、給邊界規則(「只根據提供的 diff 與上下文判斷,不補充推測」),溫度調低以減少隨機性。提示詞不神奇,神奇的是它後面接了校驗節點。
以下是一個典型的 LLM 審查提示詞範例:
你是一位資深軟體工程師,負責審查以下 Pull Request 的變更。
【上下文】
- 專案語言:TypeScript + React
- 團隊規範:變數使用 camelCase,函式名稱需動詞開頭,禁止使用 any 類型
【Diff 內容】
{{diff_content}}
【相關檔案上下文】
{{related_files_context}}
【審查維度】
請從以下四個維度評估,每個維度給出 1-5 分(5 為最佳):
1. 安全性:是否有潛在漏洞(XSS、Injection、敏感資料洩露)
2. 可讀性:變數命名、函式長度、註解完整性
3. 一致性:是否符合團隊編碼規範
4. 效能:是否有明顯的效能問題(不必要的迴圈、記憶體洩漏風險)
【輸出格式】
請嚴格按照以下 JSON 格式輸出,不要添加任何其他文字:
{
"scores": {
"security": number,
"readability": number,
"consistency": number,
"performance": number
},
"risk_level": "low" | "medium" | "high",
"comments": [
{
"file": string,
"line": number,
"severity": "info" | "warning" | "error",
"message": string,
"suggestion": string
}
],
"summary": string
}
【邊界規則】
- 只根據提供的 diff 與上下文判斷,不補充推測
- 如果無法確定某些資訊,在 comments 中標記為 "needs_human_review"
- 不要改寫任何程式碼,只提供建議
六、錯誤處理、重試與冪等
先把失敗分成三類,因為三類的處置完全不同:
| 失敗類型 | 例子 | 處置 |
|---|---|---|
| 暫時性 | API 限流、網路逾時 | 節點自動重試(設次數與間隔);重試耗盡仍失敗進例外分支 |
| 資料性 | Diff 為空、檔案編碼異常、LLM 輸出格式錯誤 | 不重試(重試還是錯);直接進例外分支,人修資料後重跑 |
| 設定性 | API Key 過期、SonarQube 服務停機、GitHub Token 權限不足 | 立即停止流程並告警,等人介入 |
冪等是重試的前提:流程要保證「同一個 PR 跑兩次不會重複發送評論」。做法是在發送評論前先查詢該 PR 是否已有來自本自動化帳號的評論——存在就更新而非新增,絕不無腦追加。沒有冪等設計就開重試,等於裝了一台評論製造機:重複的審查意見,比人工審查還難收拾。
七、失敗告警
- 告警發到「有人在值班」的渠道:即時通訊群組或 email,且群組裡有明確的值班表。告警沒人看,等於沒有告警。
- 告警內容模板:流程名稱、PR 編號、失敗節點、錯誤摘要、發生時間、重跑方式。讓收到的人在半分鐘內能決定「現在處理還是稍後處理」。
- 分級防洗版:單筆 PR 審查例外進每日匯總;API Key 過期、服務停機這類「流程已停」的事件才即時推送。每筆例外都彈一次通知,值班的人很快會把渠道靜音——告警系統就死在靜音那一刻。
八、上線後的監控
- 前兩週是觀察期:每天看執行歷史與台帳,記錄執行總數、失敗次數、誤報率(人工標記為不相關的建議比例)。兩週之後自己算誤報率與主因分佈——這是你的流程自己的數據,判斷門檻(誤報率高到多少要調整提示詞)由你的團隊容忍度決定,定了就寫進值班說明,不要引用任何文章裡的現成數字。
- 每週抽樣複核:固定抽 5-10 筆已自動通過的 PR,人工複查是否有漏檢問題。抽樣筆數依 PR 量自定,關鍵是固定頻率、留下紀錄、發現漏檢就調整規則或提示詞。抽樣抓的是「流程沒報錯但漏掉了重要問題」這類最安靜的事故。
- 變更紀律:團隊編碼規範更新、LLM 供應商更新模型版本、你改提示詞,都算變更。改動前先用最近的例外樣本與幾筆正常樣本重跑一遍,確認沒有變差再上;改動寫進台帳。
- 成本:LLM 節點的用量乘上供應官網單價,加上 SonarQube 授權費與你的維運時間,就是這條流程的真實成本;估算方法見AI 成本怎麼算。
成果與驗收標準
| 檢查點 | 通過標準 | 沒通過怎麼辦 |
|---|---|---|
| 盤點基線 | 有審查痛點表,頻率與成本是從 issue tracker 統計的紀錄 | 回到第一節;先別急著搭流程 |
| 主幹跑通 | 測試分支端到端跑完,檢測到故意放入的問題 | 檢查工具配置與權限 |
| 確定性邊界 | 程式碼片段沒有任何一個由 LLM 改寫 | 改成靜態分析工具直接提取 |
| LLM 輸出校驗 | LLM 輸出有格式校驗節點,不合法進例外分支 | 在 LLM 節點後補校驗 |
| 冪等 | 手動觸發同一個 PR 兩次,沒有重複評論 | 加評論存在性檢查 |
| 影子期 | 與人工並行連續數日結果一致才交接 | 延長影子期,逐項找不一致的原因 |
| 告警有效 | 故意製造一次失敗(暫撤測試 API Key),告警在承諾時間內到達值班渠道且內容完整 | 修告警路由與值班安排 |
| 監控習慣 | 台帳連續兩週每週有紀錄,抽樣複核有留痕 | 把監控指派到具體的人,放進行事曆 |
常見踩坑
- 讓 LLM 做確定性工作:「讓 AI 順便檢查一下語法」一時方便,代價是同樣輸入可能不同輸出,出了錯無法重現、無從追查。
- 用個人帳號的憑證:當事人離職、改密碼的那天,流程集體猝死。用服務帳號,並納入組織的憑證管理。
- 直接在生產倉庫上實驗:正確順序是測試分支、非敏感專案小範圍、全量。跳級的人通常在第二步就出事。
- 沒做冪等就開重試:重試機制會把偶發錯誤放大成重複評論事故。
- LLM 節點不設花費上限:一個迴圈觸發的臭蟲能讓流程整夜持續呼叫 API。上限與告警在供應商控制台設定,五分鐘的事。
- 告警發到沒人看的渠道:沒有值班表的告警是自我安慰。
- 一次自動化所有審查維度:一週把安全性、可讀性、效能、一致性全部自動化,第二週就沒有人力調整誤報。先讓安全性審查穩定跑滿一個月,把模式沉澱成範本,再複製到其他維度。
- 忽略團隊文化阻力:自動化審查初期誤報率可能高達 30-40%,如果沒有提前溝通與教育,團隊會迅速失去信任。第一個月重點不是降低誤報,而是建立「AI 建議供參考,最終決定權在人」的文化共識。
下一步
- 同一套「自動篩選+人工閘門」模式用在 API 文檔場景:API 文檔同步更新系統
- 技術債的量化與優先級排序:技術債追蹤與重構優先級排序
- CI/CD 管道的異常檢測:CI/CD 管道異常檢測與修復建議
- 微服務架構的依賴可視化:微服務依賴關係地圖生成
- 資料分級與安全邊界:企業資料安全基本盤
- 上線前的合規檢查表:AI 合規與風險邊界
- 流程越串越多、要不要升級成平台:自建還是採購