Files
release-cleanup/app/index.js
T
JefferyandClaude Opus 4.8 154ab032bf fix(release-cleanup): 強化輸入驗證、請求逾時與錯誤處理
解決 AI review 的安全性與健壯性問題:
- 驗證 GITEA_SERVER_URL 為合法 http/https URL(降低 SSRF 風險)
- 驗證 GITEA_REPOSITORY 為 owner/repo 形式並拒絕路徑穿越
- 為所有 fetch 請求加上 30 秒逾時(AbortSignal.timeout),避免卡死
- fetchAllPages 解析前檢查 content-type,非 JSON 時拋出明確錯誤
- selectReleasesToDelete 對無效 created_at 防呆,避免 NaN 排序
- index.js 匯出 main 並加上直接執行守衛,錯誤輸出含類型與堆疊

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

50 lines
1.6 KiB
JavaScript

// 進入點:載入設定、建立 Gitea 客戶端,依序清理舊成品與孤立 tag。
import { loadConfig } from './config.js'
import { GiteaClient } from './gitea-client.js'
import { cleanupReleases } from './releases.js'
import { cleanupOrphanTags } from './tags.js'
import { separator, fail } from './logger.js'
/**
* Action 主流程:讀取並驗證環境設定、建立帶認證的 Gitea 客戶端,
* 先清理超出保留數量的舊 release,再清理未被任何 release 指定的孤立 tag,最後輸出結尾分隔線。
*
* 任一步驟拋出的例外不在此攔截,改由模組層級的 `main().catch(...)` 統一處理並以非零狀態結束。
*
* @returns {Promise<void>} 流程完成時 resolve;設定驗證或讀取 API 失敗時 reject。
*/
export async function main() {
const config = loadConfig()
const client = new GiteaClient({ token: config.token })
await cleanupReleases(client, config)
await cleanupOrphanTags(client, config)
separator()
}
/**
* 將錯誤輸出至 stderr,並盡量保留可供除錯的上下文(錯誤類型與堆疊),
* 以便區分設定驗證錯誤與網路/API 請求錯誤。
* @param {unknown} error 捕捉到的錯誤
*/
function reportFatal(error) {
if (error instanceof Error) {
fail(`${error.name}: ${error.message}`)
if (error.stack) {
process.stderr.write(`${error.stack}\n`)
}
} else {
fail(String(error))
}
}
// 僅在直接以 `node index.js` 執行時啟動主流程;被測試 import 時不自動執行,方便撰寫整合測試。
if (import.meta.url === `file://${process.argv[1]}`) {
main().catch((error) => {
reportFatal(error)
process.exit(1)
})
}