Files
calculate-version/.gitea/ai-review/exclusions.json
T
JefferyandClaude Opus 4.8 fcb1dc4525
CI / AI Code Review (pull_request) Failing after 39s
chore(ai-review 狀態): 更新 findings.json 與 exclusions.json
已解決 5 條(critical x1、warning x2、info x2:抽常數、提升 regex、補邊界測試),5 條判定為誤報寫入 exclusions(過度收緊 regex、迴圈測試已帶訊息、總長度冗餘、片段建議互相衝突、mock 過早抽離),findings 清空。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 14:11:36 +08:00

105 lines
7.5 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[
{
"location": "app/index.js:15",
"role": "Bard",
"original_finding": "此函式註解過於詳盡描述執行流程(如 logger.fail、writeOutput),應專注於描述函式功能而非具體實作步驟。",
"reason": "詳述行為的 JSDoc 為本專案 doc-funcs 文件慣例,全模組一致採用;main 的 JSDoc 另需說明可注入的 deps 參數,刻意保留必要細節。"
},
{
"location": "app/releases.js:49",
"role": "Rogue",
"original_finding": "浪費 CPU 週期在手動處理 JSON 解析。response.text() 再 JSON.parse() 的效能比 response.json() 慢得多。建議直接使用 await response.json()。",
"reason": "text()+JSON.parse 為刻意設計:需先以字串判斷空 body 或字面 'null' 以決定分頁是否結束,改用 response.json() 會在空回應時拋錯而破壞分頁終止邏輯。"
},
{
"location": "app/version.js:128",
"role": "Rogue",
"original_finding": "重複遍歷資料!在 calculateVersion 中先呼叫 latestStableVersion 遍歷一次,隨後又呼叫 nextBetaNumber 再遍歷一次。建議先解析並篩選一次再傳遞給後續函式。",
"reason": "latestStableVersion 篩選的是穩定版、nextBetaNumber 篩選的是對應 beta 標籤,兩者為不同子集無法共用單次解析;且 release 為分頁取得的小資料集,效益可忽略,現行設計以可組合的純函式換取可讀性。"
},
{
"location": "app/version.js:77",
"role": "Bard",
"original_finding": "String(latest) 呼叫顯得冗贅,因為 latest 在此處已明確為字串型別。建議直接使用 latest.split('.')。",
"reason": "nextReleaseVersion 為對外公開(exported)函式,String() 為防禦性處理,確保被直接以非字串呼叫時也不致拋錯。"
},
{
"location": "Dockerfile:13",
"role": "Assassin",
"original_finding": "移除 `--no-check-certificate`。若確實有無法解決的憑證問題,應排查來源網域的信任鏈或安裝正確的憑證,而不是直接關閉安全機制。",
"reason": "AI 對話收斂判定為誤報(問題在最新程式碼中不成立或不適用)"
},
{
"location": "app/index.js:41",
"role": "Assassin",
"original_finding": "Action 未對 GITEA_SERVER_URL 進行格式驗證,攻擊者若能控制 CI/CD 環境變數,即可將該值設定為惡意 URL,導致 GITEA_TOKEN 外洩。建議嚴格驗證格式並符合網域白名單。",
"reason": "GITEA_SERVER_URL 由 Gitea Actions 平台注入(gitea.server_url),非一般威脅模型下使用者可控;loadConfig 已加入 http/https URL 格式驗證;網域白名單屬各部署環境特定決策,不宜硬寫進通用 action。"
},
{
"location": "app/index.js:18",
"role": "Maya",
"original_finding": "主邏輯函式 main 處理了 loadConfig 與 fetchReleases 的例外情境,但缺乏針對這些失敗路徑的整合測試。",
"reason": "前提已不成立:test/index.test.js 已以相依注入新增 main 成功路徑,以及 loadConfig 失敗、fetchReleases 失敗兩條失敗路徑的整合測試。"
},
{
"location": "app/output.js:16",
"role": "Assassin",
"original_finding": "writeOutput 直接接收 file 路徑並 fs.appendFileSync 寫入,預設來源為 GITHUB_OUTPUT,存在任意檔案寫入/路徑穿越風險。建議對路徑加入嚴格驗證。",
"reason": "GITHUB_OUTPUT 由 Action runner 注入並指向授權的暫存輸出檔,寫入它正是回傳 step output 的標準機制;對通用 action 而言硬性限制路徑會破壞功能,且該變數於正常威脅模型中非使用者可控。"
},
{
"location": "app/version.js:4",
"role": "Leo",
"original_finding": "版本號區段的進位上限(10)被直接硬編碼在程式中,未來調整進位規則需深入核心修改。建議設為配置常數或參數化。",
"reason": "進位上限已抽出為模組頂層具名常數 SEGMENT_LIMIT,可單點調整;進位規則為本 action 固定的業務規則,參數化屬尚無需求的過度設計。"
},
{
"location": "app/logger.js:4",
"role": "Leo",
"original_finding": "日誌分隔線寬度與符號直接硬編碼在模組內,調整風格需改多處。建議集中管理並提供通用產生函數。",
"reason": "分隔線已是模組頂層集中定義的常數 LINE/SUBLINE,單點即可調整;為固定的視覺樣式再加產生函數屬過度設計。"
},
{
"location": "app/test/releases.test.js:10",
"role": "Leo",
"original_finding": "withFetch 為全域 fetch 的通用封裝工具,目前定義在特定測試檔案內。建議提取至獨立的測試工具檔案(例如 app/test/test-utils.js)以提升重用性。",
"reason": "目前僅 releases.test.js 單一測試檔使用 withFetchlogger.test.js 使用的是不同的 stdout/stderr 攔截輔助),尚無第二個消費者;為單一用途提前抽出共用模組屬過度設計。"
},
{
"location": "app/test/logger.test.js:8",
"role": "Leo",
"original_finding": "在測試中使用 monkey-patch 直接覆蓋 process.stdout.write 或 process.stderr.write 是極度危險的模式,可能導致狀態污染;建議重構 logger 使其支援依賴注入。",
"reason": "攔截已於 finally 還原原本的 write,無狀態污染,且為 Node 測試 stdout/stderr 輸出的標準作法;logger 僅是寫入 stdout/stderr 的薄封裝,為其引入依賴注入框架屬過度設計。已將兩個攔截輔助合併為單一 captureStream。"
},
{
"location": "app/config.js:63",
"role": "Mage",
"original_finding": "正規表達式 ^[A-Za-z0-9._-]+$ 仍允許以點號開頭或結尾的名稱(如 .foo 或 foo.)。建議調整為點號只能存在於中間。",
"reason": "路徑穿越風險來自 .、.. 與額外斜線,皆已明確排除;前/後綴點號非穿越向量,且禁止會誤拒如 .github 這類合法 repo 名稱。"
},
{
"location": "app/test/config.test.js:65",
"role": "Bard",
"original_finding": "for...of 迴圈測試將多種錯誤案例綁在同一個測試名稱下,失敗時難以辨識是哪一種格式。建議拆分或加入描述性訊息。",
"reason": "迴圈內 assert.throws 已帶入第三引數描述訊息(應拒絕:<repo>),失敗時可定位具體案例;逐案拆成獨立 test 屬純風格偏好。"
},
{
"location": "app/config.js:62",
"role": "Mage",
"original_finding": "parts.every 僅檢查單一區段長度,未對 owner/repo 總長度做限制。建議分割前先限制 value 總長度。",
"reason": "已限定恰兩段且每段 <= MAX_REPO_NAME_LENGTH,總長度已被間接上限;再加總長度檢查為冗餘。"
},
{
"location": "app/releases.js:68",
"role": "Assassin",
"original_finding": "將未經清洗的 API 回應片段納入 Error,若 API 返回敏感資訊可能導致外洩。建議僅含概括描述或先脫敏。",
"reason": "此片段為前一輪審查明確要求加入以利除錯;release 清單 API 的非 JSON 回應通常為錯誤頁/代理訊息而非機密資料,且片段已截斷。兩輪建議互相衝突,維持可偵錯性。"
},
{
"location": "app/test/releases.test.js:33",
"role": "Bard",
"original_finding": "jsonResponse 輔助函式定義在測試檔內,建議統一抽離至 app/test/support/mock.js 集中管理。",
"reason": "目前僅 releases.test.js 單一測試檔使用,「若未來」屬臆測性需求,為單一消費者提前抽出共用模組屬過度設計。"
}
]