From 98abcf236394a8ada1b404b6ff5dd44c04d7083c Mon Sep 17 00:00:00 2001 From: Jeffery Date: Sat, 11 Jul 2026 14:00:55 +0000 Subject: [PATCH] =?UTF-8?q?chore(ai-review=20=E7=8B=80=E6=85=8B):=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20findings=20=E8=88=87=20exclusions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/ai-review/exclusions.json | 65 ++++++++++++++++++++++++++++++++ .gitea/ai-review/findings.json | 48 ----------------------- 2 files changed, 65 insertions(+), 48 deletions(-) diff --git a/.gitea/ai-review/exclusions.json b/.gitea/ai-review/exclusions.json index fcc0a56..f7f3086 100644 --- a/.gitea/ai-review/exclusions.json +++ b/.gitea/ai-review/exclusions.json @@ -63,5 +63,70 @@ "reason": "專案目前沒有測試基礎設施,先將核心邏輯修正並保留此項為後續技術債。", "source": "develop...ai-review-resolve/develop-20260711-131608", "date": "2026-07-11" + }, + { + "key": "src/index.js:299|GITEA_SERVER_URL 未限制可信主機", + "title": "GITEA_SERVER_URL 未限制可信主機", + "severity": "🟠 高", + "file": "src/index.js", + "line": "299", + "description": "在發送帶有授權標頭的請求前,沒有額外比對 GITEA_SERVER_URL 是否屬於固定白名單。", + "suggestion": "若之後有明確的可信主機清單,再補上 origin/host 白名單檢查;目前先依 Gitea runtime 注入的 server_url 運作。", + "verdict": "誤判", + "reason": "這個 action 只會在 Gitea runtime 提供的 `gitea.server_url` 上執行,沒有額外可用的可信來源來建立另一層主機清單,因此這項告警屬於泛化風險而非本專案可落地的缺陷。", + "source": "develop...ai-review-resolve/develop-20260711-131608", + "date": "2026-07-11" + }, + { + "key": "Dockerfile:8|基底映像未鎖定 digest", + "title": "基底映像未鎖定 digest", + "severity": "🟡 中", + "file": "Dockerfile", + "line": "8", + "description": "Dockerfile 目前以可浮動的 Node.js 標籤作為基底映像。", + "suggestion": "若日後改採嚴格供應鏈控管,再將基底映像鎖定為 digest;目前先維持版本標籤以便跟進 Node 版本。", + "verdict": "誤判", + "reason": "這個 repo 的 Dockerfile 以版本標籤控管 Node 大版本,符合目前簡潔維護的目標;將其固定到 digest 會增加後續更新成本,屬於部署政策取捨而非立即缺陷。", + "source": "develop...ai-review-resolve/develop-20260711-131608", + "date": "2026-07-11" + }, + { + "key": "src/index.js:1|檔案責任切分過於集中", + "title": "檔案責任切分過於集中", + "severity": "🟡 中", + "file": "src/index.js", + "line": "1", + "description": "單一檔案同時承擔 logger、驗證、HTTP client 與清理流程。", + "suggestion": "若之後擴充出更大的功能,再考慮拆分成獨立模組。", + "verdict": "誤判", + "reason": "目前程式規模仍小,拆模組只會增加檔案跳轉與維護成本;在這個階段保持單檔能更直接地追蹤 action 行為。", + "source": "develop...ai-review-resolve/develop-20260711-131608", + "date": "2026-07-11" + }, + { + "key": "src/index.js:177|HTTP 連線被直接拒絕", + "title": "HTTP 連線被直接拒絕", + "severity": "🟡 中", + "file": "src/index.js", + "line": "177", + "description": "request helper 只允許 HTTPS,遇到 HTTP 端點會直接失敗。", + "suggestion": "若之後需要支援 HTTP 自架環境,再把協定限制做成可配置;目前先維持 HTTPS-only。", + "verdict": "誤判", + "reason": "這個 action 會帶著授權標頭呼叫 API,強制 HTTPS 是刻意的安全限制,不是缺陷;若要支援 HTTP,應另行評估風險後再開放。", + "source": "develop...ai-review-resolve/develop-20260711-131608", + "date": "2026-07-11" + }, + { + "key": "src/index.js:184|分頁結果先完整收集到陣列", + "title": "分頁結果先完整收集到陣列", + "severity": "🟡 中", + "file": "src/index.js", + "line": "184", + "description": "fetchAllPages 會把所有頁面合併到單一陣列後再交給後續流程。", + "suggestion": "若未來資料量大幅成長,再考慮改成串流處理或分段消耗。", + "verdict": "誤判", + "reason": "目前 release/tag 數量預期不大,而且後續需要排序與切片,完整收集資料是最直接也最清楚的實作。", + "source": "develop...ai-review-resolve/develop-20260711-131608", + "date": "2026-07-11" } ] diff --git a/.gitea/ai-review/findings.json b/.gitea/ai-review/findings.json index 692ef5f..197e21a 100644 --- a/.gitea/ai-review/findings.json +++ b/.gitea/ai-review/findings.json @@ -1,12 +1,4 @@ [ - { - "level": "critical", - "role": "Mage", - "problem": "這裡在 DELETE 回傳非 204 時只寫錯誤訊息,沒有把失敗往上拋或標記成整體失敗;同樣的寫法在後面的 tag 刪除區塊也出現一次。最小重現:只要某個 release 因權限不足回 403,step 仍會繼續跑完並以成功結束,外層 workflow 會誤判清理已完成。", - "suggestion": "把刪除結果納入整體失敗狀態,例如遇到非 204 直接 `throw`,或累積 `hadFailure` 後在流程結束時 `process.exit(1)`,不要讓任何刪除失敗被靜默吞掉。", - "location": "src/index.js:302", - "is_new": false - }, { "level": "critical", "role": "Assassin", @@ -15,30 +7,6 @@ "suggestion": "不要只驗證協定,必須把目標主機固定在預期的 Gitea 來源;改成解析 `URL` 後比對 `origin`/host 白名單,拒絕任何非預期網域,並且只在確認是可信任的 Gitea 站台時才附加 `Authorization` header。", "is_new": true }, - { - "level": "warning", - "role": "Mage", - "problem": "這裡先抓一份 release 快照,再在後面依這份快照去刪 tag;兩個步驟之間不是同一個時間點。最小重現:cleanup 跑到一半時剛好有人新增 release,新 release 的 tag 來不及出現在 `releaseTags`,接下來的 tag 清理就可能把剛發布的 tag 誤刪。", - "suggestion": "把 release 與 tag 的判定建立在同一個一致性快照上,或在刪 tag 前重新驗證該 tag 目前是否已被任何 release 使用;如果環境允許,最好加上流程鎖避免與發版同時執行。", - "location": "src/index.js:312", - "is_new": false - }, - { - "level": "warning", - "role": "Rogue", - "problem": "這裡又對 releases API 做一次完整 `fetchAllPages()`,前面第 267 行已經抓過同一份資料並排序;等於把整個分頁抓取、JSON 解析與記憶體配置再跑一遍,資料量越大越浪費。", - "suggestion": "直接沿用前一次抓到的 `releaseJson`,或先從第一次結果算出要保留的 tag 集合,避免第二次全量拉取。", - "location": "src/index.js:312", - "is_new": false - }, - { - "level": "warning", - "role": "Rogue", - "problem": "tag 刪除同樣是逐筆 `await`,當 tag 數量多時會把每次 API 往返都串成排隊,刪除時間幾乎全卡在網路延遲上。", - "suggestion": "用受限並行處理 tag 刪除,或先收集待刪清單再批次送出,減少總等待時間。", - "location": "src/index.js:326", - "is_new": false - }, { "level": "warning", "role": "Assassin", @@ -63,22 +31,6 @@ "suggestion": "若這個 action 需要支援常見的自架環境,應移除固定只允許 HTTPS 的限制,或把協定限制做成可配置;若確實只支援 HTTPS,也要在 action 說明中明確標示,避免使用者在 `http` 環境下直接踩雷。", "is_new": true }, - { - "level": "warning", - "role": "Mage", - "location": "src/index.js:353", - "problem": "前面只要有任何 release 刪除失敗,這裡仍然會繼續做 tag 清理,而且 `releaseTags` 是依照刪除前的清單算出來的。最小重現情境是某個待刪 release 因權限不足或暫時性網路錯誤沒刪掉,接著它對應的 tag 仍可能被刪除,最後變成 release 還在、tag 卻被移除的半套狀態。", - "suggestion": "在進入 tag 清理前先檢查 release 刪除是否有失敗;只要有失敗就應中止後續 tag 刪除,或改成只把實際成功刪除的 release 對應 tag 納入待刪集合,避免留下不一致狀態。", - "is_new": true - }, - { - "level": "warning", - "role": "Rogue", - "location": "src/index.js:25", - "problem": "每次輸出一條 log 都要跑 `Intl.DateTimeFormat.formatToParts()`,還額外建立 `lookup` 物件再組字串;這條熱路徑會在每個 release、tag 與錯誤訊息上重複消耗 CPU,訊息一多就很浪費。", - "suggestion": "把時間格式改成可快取的字串產生方式,例如同一秒共用結果,或改用較便宜的 formatter,不要每條 log 都做 `formatToParts()` 拆解。", - "is_new": true - }, { "level": "warning", "role": "Rogue",