From adc3cc340e3e52b044462f0edd118dff72b17bad Mon Sep 17 00:00:00 2001 From: Jeffery Date: Fri, 26 Jun 2026 15:28:40 +0800 Subject: [PATCH] =?UTF-8?q?docs(README):=20=E6=96=B0=E5=A2=9E=20delete-uti?= =?UTF-8?q?ls=20=E4=B8=89=E5=80=8B=E5=8A=9F=E8=83=BD=E4=B8=A6=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E8=A1=8C=E8=99=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 isRetryableStatus/deleteWithRetry/runWithConcurrency 功能列表與使用範例, 更新 releases/tags 連結行號與更新時間。 Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 764e17f..bdf2849 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ release-cleanup 是一個 Gitea Docker Action,用於自動清理儲存庫中的成品(release)與標籤(tag):刪除超出保留數量的舊版本 release,並移除未被任何 release 指定的孤立 tag。原本以 bash 實作,現已改寫為模組化的 Node.js 程式,進入點仍為 `entrypoint.sh`。 -> 更新時間:2026/06/26 14:09:02 +> 更新時間:2026/06/26 15:27:17 ## 專案列表 @@ -46,10 +46,13 @@ release-cleanup 是一個 Gitea Docker Action,用於自動清理儲存庫中的 | [GiteaClient](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/gitea-client.js#L26) | [建立帶認證標頭的 Gitea API 客戶端。](#giteaclient) | | [GiteaClient.fetchAllPages](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/gitea-client.js#L50) | [逐頁讀取分頁式清單 API 並合併成單一陣列。](#giteaclientfetchallpages) | | [GiteaClient.deleteResource](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/gitea-client.js#L112) | [對指定資源發出 DELETE 請求並回傳狀態碼。](#giteaclientdeleteresource) | -| [selectReleasesToDelete](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/releases.js#L14) | [依時間排序後回傳超出保留數量的舊 release。](#selectreleasestodelete) | -| [cleanupReleases](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/releases.js#L44) | [讀取並刪除超出保留數量的舊版本 release。](#cleanupreleases) | -| [categorizeTags](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/tags.js#L17) | [將 tag 分類為保留、刪除或略過。](#categorizetags) | -| [cleanupOrphanTags](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/tags.js#L44) | [刪除未被任何 release 指定的孤立 tag。](#cleanuporphantags) | +| [selectReleasesToDelete](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/releases.js#L15) | [依時間排序後回傳超出保留數量的舊 release。](#selectreleasestodelete) | +| [cleanupReleases](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/releases.js#L45) | [讀取並刪除超出保留數量的舊版本 release。](#cleanupreleases) | +| [categorizeTags](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/tags.js#L18) | [將 tag 分類為保留、刪除或略過。](#categorizetags) | +| [cleanupOrphanTags](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/tags.js#L45) | [刪除未被任何 release 指定的孤立 tag。](#cleanuporphantags) | +| [isRetryableStatus](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/delete-utils.js#L22) | [判斷 HTTP 狀態碼是否為可重試的暫時性錯誤。](#isretryablestatus) | +| [deleteWithRetry](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/delete-utils.js#L34) | [帶指數退避的刪除,暫時性錯誤重試、永久性錯誤即止。](#deletewithretry) | +| [runWithConcurrency](https://gitea.jsc.idv.tw/docker-actions/release-cleanup/src/branch/develop/app/delete-utils.js#L64) | [以有上限併發逐項執行非同步工作。](#runwithconcurrency) | ## 使用範例 @@ -331,3 +334,48 @@ const config = loadConfig() const client = new GiteaClient({ token: config.token }) await cleanupOrphanTags(client, config) ``` + + +### isRetryableStatus + +判斷 HTTP 狀態碼是否為可重試的暫時性錯誤(429/502/503/504);其餘(含 500、401/403/404)視為不可重試。 + +```js +import { isRetryableStatus } from './delete-utils.js' + +isRetryableStatus(503) // true +isRetryableStatus(403) // false +isRetryableStatus(500) // false(視為確定性錯誤,不重試) +``` + + +### deleteWithRetry + +帶指數退避的刪除:204 視為成功;暫時性錯誤(網路例外或 429/502/503/504)會重試;永久性錯誤(如 401/403/404)立即停止。不對外拋例外,以回傳值表示結果。 + +```js +import { deleteWithRetry } from './delete-utils.js' + +const { status, error, attempts } = await deleteWithRetry(client, url) +if (status === 204) { + // 刪除成功 +} else { + // status 為最後一次 HTTP 狀態碼;網路例外時 status 為 0 且帶 error +} +``` + + +### runWithConcurrency + +以有上限的併發逐項執行非同步 worker,回傳對應輸入順序的結果;用於加速大量刪除同時避免對 API 造成過大壓力。 + +```js +import { runWithConcurrency } from './delete-utils.js' + +const urls = ['/a', '/b', '/c', '/d', '/e'] +const results = await runWithConcurrency( + urls, + async (url) => deleteWithRetry(client, url), + 4, // 最多同時 4 筆 +) +```