chore: remove ai-review findings.json due to lack of relevant tests and CI workflows

This commit is contained in:
2026-05-15 05:35:27 +00:00
parent baf14a9984
commit d4f9e2b91c
-184
View File
@@ -1,184 +0,0 @@
[
{
"level": "critical",
"role": "Maya",
"location": "entrypoint.sh",
"suggestion": "此 Git Diff 引入了大量新的函數 (`trim`, `url_encode`, `parse_repo_context`, `fetch_package_versions`) 並對現有函數進行了重大重構 (`resolve_keep_count`, `resolve_package_names`, `api_request`, `collect_package_candidates`, `process_candidates`)。然而,程式碼庫中完全沒有為這些關鍵邏輯變更提供任何測試。這導致無法驗證新功能的正確性、邊界條件處理以及重構後的穩定性。請立即為所有新增及修改的函數補齊單元測試和整合測試。",
"is_new": false
},
{
"level": "critical",
"role": "Maya",
"location": "entrypoint.sh:10-14",
"suggestion": "新增 `trim` 函數的單元測試。此函數為核心工具,被多處使用,應確保其能正確處理各種輸入,例如:空字串、只包含空白的字串、前後有空白的字串、中間有空白的字串、無空白的字串等。",
"is_new": true
},
{
"level": "critical",
"role": "Maya",
"location": "entrypoint.sh:16-19",
"suggestion": "新增 `url_encode` 函數的單元測試。此函數用於 URL 編碼,應測試包含特殊字元、空格、空字串、已編碼字串等情況,確保其符合 RFC 3986 標準。",
"is_new": true
},
{
"level": "critical",
"role": "Maya",
"location": "entrypoint.sh:39-49",
"suggestion": "新增 `resolve_keep_count` 函數的單元測試。應測試以下邊界條件和無效輸入:\n1. 有效的非負整數 (例如 0, 1, 5)。\n2. 包含前後空白的有效整數 (例如 \" 5 \")。\n3. 空字串或只包含空白的字串 (應回退到預設值 2)。\n4. 無效的非數字輸入 (例如 \"abc\", \"-1\", \"1.5\"),確保能正確觸發 `fail`。",
"is_new": true
},
{
"level": "critical",
"role": "Maya",
"location": "entrypoint.sh:51-75",
"suggestion": "新增 `resolve_package_names` 函數的單元測試。此函數處理使用者輸入的套件名稱,應測試以下情況:\n1. 空字串或只包含空白的字串 (應觸發 `fail`)。\n2. 單一套件名稱。\n3. 多個套件名稱,以逗號或換行符分隔。\n4. 包含前後空白的套件名稱 (應被 `trim` 處理)。\n5. 重複的套件名稱 (應被正確去重)。\n6. 包含空令牌的輸入 (例如 \"pkg1,,pkg2\")。\n7. 包含特殊字元 (例如連字號、點) 的套件名稱。",
"is_new": true
},
{
"level": "critical",
"role": "Maya",
"location": "entrypoint.sh:77-92",
"suggestion": "新增 `parse_repo_context` 函數的單元測試。此函數解析 Gitea 儲存庫字串,應測試以下邊界條件和無效輸入:\n1. 有效的儲存庫名稱 (例如 \"owner/repo\", \"org/project-name\")。\n2. 包含前後空白的有效儲存庫名稱。\n3. 空字串或無斜線的字串 (應觸發 `fail`)。\n4. 包含多個斜線的字串 (例如 \"owner/repo/sub\"),確保能正確觸發 `fail`。",
"is_new": true
},
{
"level": "critical",
"role": "Maya",
"location": "entrypoint.sh:133-184",
"suggestion": "新增 `fetch_package_versions` 函數的單元測試。此函數是獲取套件版本的核心邏輯,應測試以下情況:\n1. 套件不存在 (應返回空 JSON 陣列,HTTP 404)。\n2. 套件存在但沒有版本。\n3. 套件版本數量少於分頁限制 (PAGE_LIMIT)。\n4. 套件版本數量多於分頁限制,需要多頁獲取。\n5. Gitea API 返回非 2xx/404 錯誤時的處理。\n6. `PAGE_LIMIT` 為無效值 (非數字、零、負數) 時的處理。",
"is_new": true
},
{
"level": "critical",
"role": "Zara",
"location": "entrypoint.sh:L209",
"suggestion": "在 `collect_package_candidates` 函數中,針對每個 `package_name` 呼叫 `fetch_package_versions` 會導致 N+1 查詢問題。如果 Gitea API 支援一次性查詢多個套件或所有套件的版本(如同舊版程式碼的 `fetch_all_pages` 似乎暗示的),應改為一次性取得所有相關套件的版本資料,然後在本地進行過濾和分組。這將大幅減少 API 請求的總數,顯著提升執行效率並降低 Gitea 伺服器的負載。",
"is_new": true
},
{
"level": "critical",
"role": "Maya",
"location": "entrypoint.sh:186-231",
"suggestion": "新增 `collect_package_candidates` 函數的單元測試。此函數負責識別要刪除的套件版本,應測試以下情況:\n1. 沒有提供套件名稱或提供的套件名稱不存在。\n2. 套件版本數量少於 `keep_count` (不應有刪除候選)。\n3. 套件版本數量多於 `keep_count` (應正確識別最舊的版本作為候選)。\n4. `keep_count` 為 0 或 1 的邊界情況。\n5. 確保 `sort_by(.created_at, .version)` 排序邏輯的正確性,特別是在 `created_at` 相同時的行為。",
"is_new": true
},
{
"level": "critical",
"role": "Maya",
"location": "entrypoint.sh:233-278",
"suggestion": "新增 `process_candidates` 函數的單元測試。此函數負責執行刪除操作,應測試以下情況:\n1. 候選文件為空 (不應執行任何刪除)。\n2. 候選文件中包含一個或多個刪除項目。\n3. 模擬 `api_request` 成功刪除的情況。\n4. 模擬 `api_request` 刪除失敗的情況 (例如 404, 500)。\n5. 確保最終的摘要日誌輸出正確反映刪除和錯誤計數。",
"is_new": true
},
{
"level": "critical",
"role": "Maya",
"location": "entrypoint.sh:280-312",
"suggestion": "新增 `main` 函數的整合測試。此函數是腳本的入口點,應透過設置不同的環境變數 (例如 `GITEA_SERVER_URL`, `GITEA_REPOSITORY`, `RUNNER_TOKEN`, `INPUT_KEEP_COUNT`, `INPUT_PACKAGE_NAMES`) 來模擬真實場景,並驗證整個流程的正確性,包括:\n1. 成功執行並刪除指定套件版本。\n2. 在輸入無效時正確觸發 `fail`。\n3. 在 Gitea API 返回錯誤時的行為。\n4. 確保所有臨時文件在腳本結束時被正確清理。",
"is_new": true
},
{
"level": "warning",
"role": "Maya",
"location": "entrypoint.sh:94-131",
"suggestion": "雖然 `api_request` 函數的重構使其更易於測試,但仍缺少針對其行為的單元測試。建議使用 mock 方式模擬 `curl` 命令,以測試以下情況:\n1. 成功的 HTTP 請求 (2xx 狀態碼)。\n2. 各種錯誤的 HTTP 響應 (例如 404, 500)。\n3. `curl` 命令本身失敗的情況。\n4. 響應頭中包含或不包含 `x-gitea-request-id` 或 `x-request-id` 的情況。\n5. 確保臨時文件在所有執行路徑中都被正確清理。",
"is_new": true
},
{
"level": "warning",
"role": "Leo",
"location": "entrypoint.sh:91",
"suggestion": "在 `api_request` 函式中直接呼叫 `fail` 會導致函式在發生錯誤時直接終止整個腳本。為了提高模組化和錯誤處理的彈性,建議 `api_request` 函式在失敗時返回一個非零的狀態碼或錯誤訊息,讓呼叫者(例如 `fetch_package_versions` 或 `process_candidates`)決定如何處理錯誤,例如是繼續執行還是終止腳本。這將使 `api_request` 成為一個更純粹的 HTTP 請求工具函式。",
"is_new": true
},
{
"level": "warning",
"role": "Rex",
"location": "entrypoint.sh:105",
"suggestion": "`GITEA_SERVER_URL` 變數直接用於建構 API 請求的基礎 URL。如果此變數可被攻擊者控制,可能導致 API 請求被重定向到惡意伺服器。請確保 `GITEA_SERVER_URL` 始終來自受信任、不可變的配置或環境變數。如果它可能來自使用者輸入,則必須實施嚴格的驗證。",
"is_new": false
},
{
"level": "warning",
"role": "Zara",
"location": "entrypoint.sh:125, entrypoint.sh:126, entrypoint.sh:240, entrypoint.sh:241",
"suggestion": "在 `fetch_package_versions` 函式中,`page_file` 和 `headers_file` 在 `while` 迴圈的每次迭代中都被建立和刪除。同樣地,在 `process_candidates` 函式中,`body_file` 和 `headers_file` 也在迴圈中重複建立和刪除。這會導致頻繁的 `mktemp` 和 `rm -f` 系統呼叫,增加 I/O 和程序啟動的開銷,尤其是在處理大量分頁或多個待刪除版本時。建議在迴圈外部只建立一次這些暫存檔案,並在迴圈內部重複使用它們,最後在函式結束時統一刪除。",
"is_new": false
},
{
"level": "warning",
"role": "Zara",
"location": "entrypoint.sh:L171, entrypoint.sh:L342",
"suggestion": "`url_encode` 函數每次執行都會啟動一個 `jq` 外部程序。雖然 `jq` 功能強大,但在迴圈中頻繁呼叫它(例如在 `fetch_package_versions` 和 `process_candidates` 中對每個套件名稱或版本進行編碼)會產生顯著的程序啟動開銷。考慮在 Bash 中實現一個更輕量級的 URL 編碼函數,特別是如果需要編碼的字元集有限且已知,以減少外部程序呼叫的頻率。",
"is_new": true
},
{
"level": "info",
"role": "Aria",
"location": "entrypoint.sh:13",
"suggestion": "trim 函數中的參數擴展 (`value=\"${value#\"${value%%[![:space:]]*}\"}\"`) 雖然高效且為純 Bash 實現,但對於不熟悉 Bash 進階語法的人來說可能較難理解。可以考慮添加更詳細的註釋來解釋其工作原理,或在極端追求可讀性的情況下,使用 `sed` 或 `awk` 等工具來實現,儘管這會引入外部依賴。",
"is_new": false
},
{
"level": "info",
"role": "Leo",
"location": "entrypoint.sh",
"suggestion": "程式碼中多處使用了 `log` 函式。為確保可維護性,建議在腳本開頭或一個專門的工具函式庫中明確定義 `log` 函式,並考慮其輸出格式(例如是否包含時間戳、日誌級別等),以便於日誌分析和問題追蹤。雖然此 diff 未包含 `log` 函式的定義,但其廣泛使用使其成為一個值得關注的點。",
"is_new": false
},
{
"level": "info",
"role": "Maya",
"location": "entrypoint.sh",
"suggestion": "除了單元測試和整合測試,建議開發端到端(E2E)測試。這些測試應在一個隔離的測試環境中運行 `main` 函數,並與一個模擬的 Gitea 實例或專用的測試 Gitea 實例互動,以驗證整個工作流程的正確性。",
"is_new": false
},
{
"level": "info",
"role": "Maya",
"location": "entrypoint.sh",
"suggestion": "建議在專案中新增一個 `test/` 目錄,將所有測試腳本放在其中。並將這些測試整合到 CI/CD 流程中,確保每次程式碼變更都能自動執行測試,從而及早發現問題並維持程式碼品質。",
"is_new": false
},
{
"level": "info",
"role": "Aria",
"location": "entrypoint.sh:148",
"suggestion": "在 `fetch_package_versions` 函數中,`limit=100` 是一個硬編碼的數值。考慮將此值定義為一個具名的變數(例如 `PAGE_LIMIT`),以提高可讀性和未來的可配置性。",
"is_new": false
},
{
"level": "info",
"role": "Zara",
"location": "entrypoint.sh:149",
"suggestion": "在 `fetch_package_versions` 函式中,每次取得新分頁資料後,都透過 `jq -s '.[0] + .[1]'` 將新資料與已聚合的資料合併。這會導致 `jq` 程序被重複啟動,並且每次合併都需要重新讀取和解析所有已聚合的 JSON 資料,效率會隨著資料量增加而降低。建議考慮更高效的 JSON 聚合策略,例如將所有分頁的 JSON 陣列收集起來,最後一次性地合併,或者使用 `jq` 的 streaming 模式(如果適用)來減少重複處理的開銷。",
"is_new": false
},
{
"level": "info",
"role": "Zara",
"location": "entrypoint.sh:204, entrypoint.sh:215",
"suggestion": "在 `collect_package_candidates` 函式中,針對每個套件的版本清單,`jq` 被呼叫兩次進行排序:一次用於日誌輸出,另一次用於選取待刪除的候選版本。雖然 `jq` 排序效率高,但兩次外部程序呼叫仍會產生額外開銷。建議優化為只排序一次,然後將排序後的結果用於後續的日誌記錄和候選版本篩選,以減少重複的計算和程序啟動。",
"is_new": false
},
{
"level": "info",
"role": "Aria",
"location": "entrypoint.sh:249",
"suggestion": "為了提高 `trap` 命令的穩健性並避免潛在的引用問題,建議將清理邏輯封裝在一個獨立的函數中,然後 `trap` 該函數。例如:\n\n```bash\ncleanup() {\n rm -f -- \"${candidate_file}\"\n}\ntrap cleanup EXIT\n```\n\n目前的寫法 `trap \"rm -f -- '${candidate_file}'\" EXIT` 在 `candidate_file` 包含特殊字元(如單引號)時可能導致非預期的行為,儘管 `mktemp` 生成的檔名通常不會有此問題。",
"is_new": true
},
{
"level": "info",
"role": "Rex",
"location": "entrypoint.sh:300",
"suggestion": "雖然目前程式碼對 `RESOLVED_GITEA_TOKEN` 的使用已盡量小心,但將敏感資訊(如 API token)以 `export` 方式設定為環境變數,可能會在某些情況下(例如子程序繼承環境變數、或系統日誌意外記錄環境)造成資訊洩漏。建議考慮在 `curl` 命令中直接使用 `-H \"Authorization: token ${token}\"` 而非依賴 `export`,以限制 token 的作用域,或確保所有子程序都不會意外地存取或記錄此變數。",
"is_new": false
},
{
"level": "info",
"role": "Rex",
"location": "entrypoint.sh:342-344,354",
"suggestion": "審查日誌中輸出的環境變數和輸入值。雖然這些資訊(Gitea Server URL, Repository, Package Names)通常不包含直接的機密,但若其中包含任何敏感資料或可被利用的資訊,可能會造成洩漏。建議僅在必要時記錄,並考慮對敏感資訊進行遮蔽處理。",
"is_new": true
}
]