feat(ai-code-review): 建問題模式導向 issue,並整併流程調整、文件與 CI #14
Notifications
Due Date
No due date set.
Blocks
#6 feat(ai-code-review): 建問題模式導向 issue,並整併流程調整、文件與 CI
node-actions/ai-code-review
Reference: node-actions/ai-code-review#14
Reference in New Issue
Block a user
變更摘要
本 PR 將 ai-code-review action 分支的完整成果併入
develop,主要含四塊:create-issue: 'true'時,審查留言(工具/diff/角色/嚴重問題/警告+建議)全部改發到追蹤 issue、不再張貼到 PR;不執行「舊留言標過時/resolve」;issue 延後到「確定有保留問題」才建立;無保留問題或無可審查變更則不建 issue、PR 也完全不留言(靜默通過);有問題時最後在 PR 回貼一則 issue 連結並補掛標籤,形成雙向關聯。action.yml/src各模組文件、重建readme.md,新增.gitea/workflows/ci.yaml(多工具 code review 驗證)並啟用建問題模式。影響範圍
src/index.jsmain()依模式分流:留言去向、跳過 resolveOldComments、issue 延後建立、severe/others 導向 issue、有問題才在 PR 回貼連結src/lib/gitea.js新增addLabelsToIssuesrc/lib/templates.js新增issueLinkCommentsrc/lib/review.js新增postSevereToIssue,移除createIssueWithFindings、sortFindingsForIssuesrc/lib/gitrepo.js補抓淺層 checkout 的 base 歷史readme.md、action.yml、.gitea/workflows/ci.yaml、.gitea/workflows/readme.md風險與注意事項
readme.md尚未反映「建問題模式導向 issue」的最新行為與新/移除的函式,建議後續以 doc-funcs 重建文件。2026/07/17 18:49:58,未刷新。🤖 AI Code Review|審查工具
antigravity1.1.4gemini-3.5-flash36bf2d8644d77876f3f1342fb4a5f74add273192📋 變更摘要(送審 git diff)
action.ymlreadme.mdsrc/index.jssrc/lib/agents.jssrc/lib/context.jssrc/lib/gitea.jssrc/lib/gitrepo.jssrc/lib/review.jssrc/lib/roles.jssrc/lib/templates.js⚔️ 攻擊方登場
🛡️ 防守方登場
🔴 嚴重|⚡ Rogue
位置:
src/index.js第 216–218 行問題描述
在
ensureIssueCreated函式中,使用for...of迴圈搭配await來逐條對 Gitea API 發送留言請求。由於網路請求存在延遲(每次 RTT 約 100-300ms),在迴圈內阻塞式等待會導致整體執行時間隨留言數量線性增加,浪費大量 CPU 週期與網路連線資源。修改建議
可以將
issueBuffer中的所有情境留言合併為單一 Markdown 留言發送,僅需一次 API 呼叫;或者使用Promise.all將這些無相依性的留言請求並行化發送,大幅降低總延遲。建議寫法
🔴 嚴重|🗡️ Assassin
位置:
src/lib/review.js第 23–23 行問題描述
在
redactSecrets函式中,針對Authorization標頭的遮蔽正規表示式為/(authorization\\s*[:=]\\s*)\\S+/gi。此規則僅會遮蔽Authorization:後方的第一個非空白字串。當使用常見的Authorization: Bearer <token>或Authorization: token <token>格式時,僅有Bearer或token會被替換為***,而實際的敏感憑證(<token>)將會完整暴露並輸出至 CI 日誌中,造成憑證外洩風險。修改建議
修正正規表示式,使其能同時匹配驗證機制名稱(如 Bearer、token、Basic)與隨後的憑證內容。可以使用分組同時捕捉機制與憑證字串來進行遮蔽。
建議寫法
🔴 嚴重|🗡️ Assassin
位置:
src/lib/review.js第 25–25 行問題描述
在
redactSecrets函式中,遮蔽 URL 內嵌帳密的正規表示式為/(https?:\\/\\/)[^\\s/:@]+:[^\\s/@]+@/gi。此規則強制要求 URL 必須同時包含使用者名稱與密碼(以冒號:分隔,如http://user:pass@host)。但在實際使用情境中,常會使用僅包含 Token 的 URL(如https://<token>@gitea.com),此時該正規表示式將無法匹配,導致敏感的 Token 完整暴露在日誌中。修改建議
建議簡化並強化正規表示式,直接遮蔽
https://與主機名之間的@前的所有憑證字元,不論其是否包含冒號。建議寫法
🟠 警告|🧰 Leo
位置:
src/index.js第 186–225 行問題描述
將 postComment 和 ensureIssueCreated 這類包含多角色審查與建問題模式核心業務邏輯的輔助函式直接內嵌於 main() 主流程函式中。這會導致這些函式因閉包而強耦合 main() 內部的局部變數(例如 issue, issueBuffer, currentRunCommentIds 等),未來若需要維護或擴充建問題邏輯,將大幅增加 main() 的認知複雜度,且無法對這些核心邏輯進行獨立的單元測試(Unit Test)。
修改建議
建議將這些輔助函式抽離到 main() 之外,定義為模組私有函式,並明確地將需要的依賴與狀態(如 ctx, issueBuffer)透過參數傳入,以提升程式碼的模組化與可測試性。
建議寫法
🟠 警告|⚡ Rogue
位置:
src/lib/gitrepo.js第 134–134 行問題描述
在檢查是否為淺層 repository (shallow repository) 時,呼叫了外部子行程執行
git rev-parse --is-shallow-repository。建立與啟動 OS 子行程是非常昂貴的操作,會白白浪費數十毫秒的 CPU 週期與系統資源。修改建議
Git 在淺層 clone 時會在
.git目錄下建立一個shallow檔案。我們可以使用 Node.js 內建的fs.existsSync進行本地檔案檢查,不需啟動額外的 Git 子行程,執行速度可快上百倍。建議寫法
🟠 警告|⚡ Rogue
位置:
src/lib/gitrepo.js第 134–143 行問題描述
在處理淺層歷史不足的救援策略時,將最沉重的
--unshallow(完整拉取整個存取庫歷史,對於大型專案會下載數 GB 的資料並導致嚴重的網路和 I/O 阻塞)放在第一順位,而較輕量的--deepen卻放在後面。這會導致絕大多數情況下直接執行最慢、最耗資源的完整拉取。修改建議
應反轉策略順序,優先嘗試較輕量的
deepen。只有當deepen抓取後仍無法找出共同祖先時,才將unshallow作為最後的保底手段,以節省大量網路頻寬與時間。建議寫法
🟠 警告|🧰 Leo
位置:
src/lib/gitrepo.js第 293–305 行問題描述
為了防止 Git 推送失敗時在例外訊息中回顯包含 Token 與遠端 URL 的命令列參數,pushWithCredential 的 catch 區塊直接拋出一個固定的 Error('推送審查結果 commit 失敗...')。但這樣一來,它完全吞掉了原始的錯誤(例如 non-fast-forward 非快轉、分支保護規則阻擋、或連線逾時),六個月後的維護者在 CI log 中看到此錯誤時,完全無從判斷失敗的原因。
修改建議
建議在保留安全遮罩的前提下,保留原始 exception 的排錯線索。例如可以檢查並安全地過濾 err.message 或 err.stderr 中所有的敏感字串(如 Token/URL),然後將其作為新錯誤的 cause 屬性或附加訊息傳遞下去。
建議寫法
🟠 警告|🗡️ Assassin
位置:
src/lib/gitrepo.js第 299–299 行問題描述
在
pushWithCredential中,環境變數GIT_CONFIG_KEY_0被動態拼接為http.${remoteUrl}.extraheader。如果remoteUrl來自外部或未經嚴格驗證的 context,且 URL 中包含特殊字元(如點號、路徑分隔符號或引號等),可能會導致 Git 配置解析錯誤,或在特定平台下引發 Git 配置參數注入風險。修改建議
由於該執行程序僅為一次性的
git push操作,可直接將該憑證應用於所有 HTTP 請求,將GIT_CONFIG_KEY_0設定為靜態的http.extraheader,以避免動態拼接 URL 所帶來的注入風險。建議寫法
🟠 警告|🧰 Leo
位置:
src/lib/review.js第 28–38 行問題描述
redactSecrets 使用的正則表達式 replace(/\b[A-Za-z0-9_-]{40,}\b/g, '***') 過於寬鬆。它會將任何長度大於或等於 40 的英數字/底線/減號字串(例如 Git 的 40 碼 Commit SHA 或某些合法的 hash 值)全數遮蔽為 ***。這會導致日誌中所有相關的 Commit SHA 被抹除,極大增加了排錯與回溯歷史的難度,是一項未來難以維護的技術債。
修改建議
遮罩機制應該針對特定且高信賴度的敏感模式(例如特定 token 前綴如 ghp_),或者建立一個明確的敏感詞清單(包含 ctx.token 與 ctx.pushToken 等),而非使用粗暴的長度匹配。
建議寫法
🔵 建議|🧰 Leo
位置:
src/index.js第 45–285 行問題描述
程式碼中的註解(如 // ── 步驟 2:延後執行 ──)與日誌輸出(如 log('步驟3', ...)、log('步驟8', ...))強烈耦合了具體的數字編號。在此次變更中,因為步驟 2 被延後執行,導致後續所有步驟編號都必須在程式碼多處同步手動修改。這種硬編碼的步驟序號極易在未來的重構中遺漏修改,導致日誌順序編號與實際執行的步驟脫節,造成六個月後的自己除錯困難。
修改建議
建議移除日誌中寫死的數字步驟編號,改用描述性的階段名稱(例如 [DETECT_TOOL], [LOAD_DIFF], [SAVE_FINDINGS])來作為日誌範疇(Scope)標記,既保留流程脈絡,又不會引入多處同步修改的維護成本。
建議寫法
🔵 建議|🎼 Bard
位置:
src/index.js第 308–368 行問題描述
新增或修改的步驟分隔註解(如步驟 8 分組、步驟 2 延後、步驟 9、步驟 10、及建問題模式收束)其尾隨的水平分隔線(─)長度不一或僅存單一字元,破壞了專案既有程式碼中整齊劃一的長分隔線視覺排版,視覺上顯得雜亂、走調。
修改建議
補足尾隨的水平線 ─,使其與鄰近步驟分隔註解的長度(約 70~80 字元寬度)與視覺風格保持一致,維持排版的美觀。
建議寫法
🔵 建議|⚡ Rogue
位置:
src/index.js第 366–382 行問題描述
在建問題模式收束時,先
await gitea.createIssueComment再await gitea.addIssueDependency,這兩個 Gitea API 呼叫是獨立且無資料相依性的,卻以序列(Sequential)方式執行,白白浪費了一次網路往返(RTT)的等待時間。修改建議
使用
Promise.all同時發起這兩個請求,並行處理以減少整體 execution 的等待時間。建議寫法
🔵 建議|🎼 Bard
位置:
src/lib/review.js第 33–34 行問題描述
在 redactSecrets 函式中,針對 authorization 以及其他憑證關鍵字(如 token、secret、password 等)的敏感資訊遮蔽,分別使用了兩條結構極為相似的正規表示式進行替換。這造成了重複的替換邏輯與額外的處理開銷,程式碼的旋律顯得不夠俐落。
修改建議
建議將這兩條正規表示式合併為單一表達式,消除重複的 replace 呼叫,使程式碼更加簡潔優雅且提升運行效率。
建議寫法
🔵 建議|⚡ Rogue
位置:
src/lib/review.js第 48–53 行問題描述
在
agentFailureDetail之中,進行 stderr 與 stdout 的遮罩處理時,是先截斷至 2,000 字元,然後執行多次複雜的redactSecrets正規表示式替換,最後再截斷至 500 字元輸出。這會造成 1,500 字元的複雜 regex 運算結果在下一步被直接丟棄,白白浪費了 CPU 進行字串比對與取代的週期。修改建議
應在呼叫
redactSecrets之前,就先將字串截斷至目標長度(500 字元),再進行遮罩,可大幅減少 regex 運算負擔。建議寫法
🔵 建議|🎼 Bard
位置:
src/lib/templates.js第 335–337 行問題描述
issueFindingComment 函式的 @remarks 文件註解中,說明其使用情境為『建問題模式下 review.postSevereToIssue 把每條嚴重 finding... 作為問題明細的追蹤紀錄』。然而實際上,非嚴重的警告與建議(others)也會透過 review.postOthersToIssue 呼叫此模板進行發布,導致文件描述不夠完整。
修改建議
修正 @remarks 的使用情境說明,將 postOthersToIssue 亦併入描述中,使 JSDoc 文件能如實且精準地反映實際程式碼的呼叫情境。
建議寫法
🧩 code-review-resolve 處理進度
本議題為 AI Code Review 建問題模式的追蹤議題。以
--issue all併同.gitea/ai-review/findings/逐條處理後結果如下(對照目前程式碼與exclusions.json):src/index.js第 216–218 行src/lib/review.js第 23–23 行src/lib/review.js第 25–25 行src/index.js第 186–225 行src/lib/gitrepo.js第 134–134 行src/lib/gitrepo.js第 134–143 行src/lib/gitrepo.js第 293–305 行src/lib/gitrepo.js第 299–299 行src/lib/review.js第 28–38 行src/index.js第 45–285 行src/index.js第 308–368 行src/index.js第 366–382 行src/lib/review.js第 33–34 行src/lib/review.js第 48–53 行src/lib/templates.js第 335–337 行小計:✅ 已解決 1 條、🚫 誤報(已列入 exclusions)5 條、⏭️ 待人工處理 9 條。
resolveMergeBase補抓策略調整、deepen PR HEAD改用 head SHA、留言閉包改名、push-tokeninput 移除等)。.gitea/ai-review/exclusions.json既有裁決等價,不重複新增排除條目。處理完成,依 code-review-resolve 流程關閉本議題。