diff --git a/.gitea/ai-review/exclusions.json b/.gitea/ai-review/exclusions.json new file mode 100644 index 0000000..e299bde --- /dev/null +++ b/.gitea/ai-review/exclusions.json @@ -0,0 +1,26 @@ +[ + { + "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() 為防禦性處理,確保被直接以非字串呼叫時也不致拋錯。" + } +] diff --git a/.gitea/ai-review/findings.json b/.gitea/ai-review/findings.json index 631774c..fe51488 100644 --- a/.gitea/ai-review/findings.json +++ b/.gitea/ai-review/findings.json @@ -1,82 +1 @@ -[ - { - "level": "critical", - "role": "Assassin", - "location": "Dockerfile:13", - "problem": "使用了 `--no-check-certificate` 參數下載軟體包,這會停用 TLS 憑證檢查。攻擊者若能進行中間人攻擊(MITM),即可攔截連線並將惡意的套件注入到映像檔中。", - "suggestion": "移除 `--no-check-certificate`。若確實有無法解決的憑證問題,應排查來源網域的信任鏈或安裝正確的憑證,而不是直接關閉安全機制。", - "is_new": true - }, - { - "level": "critical", - "role": "Assassin", - "location": "app/index.js:41", - "problem": "Action 未對 `GITEA_SERVER_URL` 進行格式驗證,攻擊者若能控制 CI/CD 環境變數,即可將該值設定為惡意 URL,進而誘使 Action 將 `GITEA_TOKEN` 傳送至攻擊者伺服器,導致敏感憑證外洩。", - "suggestion": "在 `app/config.js` 的 `loadConfig` 中,對 `GITEA_SERVER_URL` 進行嚴格驗證,確保其格式正確(例如開頭必須為 `https://`)且符合預期的網域白名單(若適用)。", - "is_new": true - }, - { - "level": "critical", - "role": "Leo", - "location": "app/logger.js:41", - "problem": "fail 函數在內部直接呼叫 process.exit(1),這會導致單元測試或呼叫此函數的程式無法攔截錯誤進行復原,且會直接終止整個 Node.js 行程,測試時會導致測試 runner 直接崩潰。", - "suggestion": "建議將 fail 函數改為只負責輸出錯誤訊息並拋出例外(throw Error),由最外層的 main 函數負責攔截並決定", - "is_new": true - }, - { - "level": "critical", - "role": "Maya", - "location": "app/index.js:18", - "problem": "主邏輯函式 `main` 處理了 `loadConfig` 與 `fetchReleases` 的例外情境,但缺乏針對這些失敗路徑的整合測試,無法確保錯誤發生時流程能正確終止。", - "suggestion": "建議編寫整合測試,透過 mock 相關依賴(如 `loadConfig`、`fetchReleases`)來模擬錯誤,並驗證 `main` 是否正確觸發錯誤處理機制。", - "is_new": true - }, - { - "level": "warning", - "role": "Bard", - "location": "app/index.js:15", - "problem": "此函式註解過於詳盡描述執行流程(如 logger.fail、writeOutput),應專注於描述函式功能而非具體實作步驟。", - "suggestion": "簡化為:/** Action 進入點:執行版本計算並寫入輸出。 */", - "is_new": true - }, - { - "level": "warning", - "role": "Mage", - "location": "app/releases.js:52", - "problem": "fetch 的 response.text() 方法可能因連線中斷等原因拋出例外,且目前未被包裹在 try-catch 區塊中,若發生錯誤將無法提供明確的 API 頁碼上下文。", - "suggestion": "將 response.text() 以及後續的 JSON.parse 邏輯整合進現有的 try-catch 區塊,確保錯誤處理能準確捕捉並包含頁碼 (page) 資訊。", - "is_new": true - }, - { - "level": "warning", - "role": "Rogue", - "location": "app/releases.js:49", - "problem": "浪費 CPU 週期在手動處理 JSON 解析。`response.text()` 再 `JSON.parse()` 的效能比 `response.json()` 慢得多,且造成不必要的字串記憶體分配。", - "suggestion": "直接使用 `await response.json()`。", - "is_new": true - }, - { - "level": "warning", - "role": "Rogue", - "location": "app/version.js:128", - "problem": "重複遍歷資料!在 `calculateVersion` 中,先呼叫 `latestStableVersion` 遍歷一次 release 清單,隨後又呼叫 `nextBetaNumber` 再遍歷一次。這在資料量大時是完全不必要的 O(N) 浪費。", - "suggestion": "應先在 `calculateVersion` 內將 `releases` 解析並篩選一次,將結果傳遞給後續函式,避免重複遍歷。", - "is_new": true - }, - { - "level": "info", - "role": "Bard", - "location": "app/version.js:77", - "problem": "String(latest) 呼叫顯得冗贅,因為 latest 在此處已明確為字串型別。", - "suggestion": "直接使用 latest.split('.') 即可。", - "is_new": true - }, - { - "level": "info", - "role": "Bard", - "location": "app/logger.js:34", - "problem": "註解提及 process.exit(1) 後續程式碼不會執行,此為程式語言基本常識,屬於冗餘註解。", - "suggestion": "移除此行註解,讓程式碼更精簡。", - "is_new": true - } -] +[]