release-cleanup:文件化補齊、日誌格式統一與 CI 自我清理管線(develop → master) #10

Merged
admin merged 7 commits from develop into master 2026-07-01 01:35:55 +00:00
Showing only changes of commit c37b33f397 - Show all commits
+39 -30
View File
@@ -2,26 +2,21 @@
'use strict';
/**
* 在 stdout 輸出一條視覺分隔線(前後各一個換行 + 50 個等號),
* 用於在 log 中切割不同區段
*
* @returns {void}
* 目前流程階段名稱,作為每行 log 的 `[階段]` 前綴使用;
* 為空字串時省略整個 `[階段]` 區塊
* @type {string}
*/
function separator() {
process.stdout.write('\n==================================================\n');
}
let currentStage = '';
/**
* 輸出一個區段標題區塊:上緣等號分隔線、標題文字、下緣虛線,
* 用於在 log 中標示流程進入新階段
* 設定目前流程階段名稱,之後輸出的 log 會以 `[階段]` 前綴標示所屬階段。
* 傳入空字串可清除階段前綴
*
* @param {string} title 區段標題文字
* @param {string} name 階段名稱(顯示於每行 log 開頭的 `[階段]` 區塊)
* @returns {void}
*/
function section(title) {
separator();
process.stdout.write(`${title}\n`);
process.stdout.write('--------------------------------------------------\n');
function stage(name) {
currentStage = name;
}
/**
@@ -38,45 +33,59 @@ function timestamp() {
}
/**
* 以 `[INF][時間]:` 前綴將一般資訊訊息輸出到 stdout(時間為 Asia/Taipei
* 依統一格式組出一行 log:`[階段?][等級][時間]: 訊息`
* 階段取自目前 currentStage(為空字串時省略整個 `[階段]` 區塊);
* 時間為 Asia/Taipei 的 `yyyy/MM/dd HH:mm:ss`。
*
* @param {string} level 等級碼(INF/WRN/ERR)。
* @param {string} msg 訊息內容。
* @returns {string} 組裝後的 log 字串。
*/
function formatLog(level, msg) {
const stagePart = currentStage ? `[${currentStage}]` : '';
return `${stagePart}[${level}][${timestamp()}]: ${msg}`;
}
/**
* 以 `[階段?][INF][時間]:` 前綴將一般資訊訊息輸出到 stdout(時間為 Asia/Taipei)。
*
* @param {string} msg 要輸出的訊息內容。
* @returns {void}
*/
function info(msg) {
console.log(`[INF][${timestamp()}]: ${msg}`);
console.log(formatLog('INF', msg));
}
/**
* 以 `[INF][時間]:` 前綴將成功訊息輸出到 stdout(時間為 Asia/Taipei)。
* 以 `[階段?][INF][時間]:` 前綴將成功訊息輸出到 stdout(時間為 Asia/Taipei)。
* 規範等級碼無「成功」,故等級採 INF,成功語意保留於訊息文字。
*
* @param {string} msg 要輸出的訊息內容。
* @returns {void}
*/
function success(msg) {
console.log(`[INF][${timestamp()}]: ${msg}`);
console.log(formatLog('INF', msg));
}
/**
* 以 `[WRN][時間]:` 前綴將警告訊息輸出到 stdout(時間為 Asia/Taipei)。
* 以 `[階段?][WRN][時間]:` 前綴將警告訊息輸出到 stdout(時間為 Asia/Taipei)。
*
* @param {string} msg 要輸出的訊息內容。
* @returns {void}
*/
function warn(msg) {
console.log(`[WRN][${timestamp()}]: ${msg}`);
console.log(formatLog('WRN', msg));
}
/**
* 以 `[ERR][時間]:` 前綴將錯誤訊息輸出到 stderr(時間為 Asia/Taipei)。
* 以 `[階段?][ERR][時間]:` 前綴將錯誤訊息輸出到 stderr(時間為 Asia/Taipei)。
* 僅負責輸出,不會結束程序(是否離開由呼叫端決定)。
*
* @param {string} msg 要輸出的錯誤訊息內容。
* @returns {void}
*/
function fail(msg) {
console.error(`[ERR][${timestamp()}]: ${msg}`);
console.error(formatLog('ERR', msg));
}
/**
@@ -92,8 +101,8 @@ function isEmptyOrNull(value) {
}
/**
* 檢查必填值。先以 [INFO] 印出 name=value
* 若值被判定為空(見 isEmptyOrNull),印出 [ERR] 並以 exit code 1 結束程序。
* 檢查必填值。先以 info[INF]印出 name=value
* 若值被判定為空(見 isEmptyOrNull),以 fail[ERR])輸出並以 exit code 1 結束程序。
*
* @param {string} name 參數名稱(用於 log 與錯誤訊息)。
* @param {*} value 要驗證的參數值。
@@ -157,7 +166,9 @@ async function main() {
const GITEA_TOKEN = process.env.GITEA_TOKEN;
const KEEP_COUNT_RAW = process.env.KEEP_COUNT;
section('參數檢查');
// 於容器啟動橫幅與後續 log 之間留一空行,方便在 CI log 中閱讀
process.stdout.write('\n');
stage('參數檢查');
requireValue('GITEA_SERVER_URL', GITEA_SERVER_URL);
requireValue('GITEA_REPOSITORY', GITEA_REPOSITORY);
requireValue('KEEP_COUNT', KEEP_COUNT_RAW);
@@ -225,7 +236,7 @@ async function main() {
const releaseApiUrl = `${GITEA_SERVER_URL}/api/v1/repos/${GITEA_REPOSITORY}/releases`;
section('取得成品資訊');
stage('取得舊版本');
info(`GET ${releaseApiUrl}`);
let releases = await fetchAllPages(releaseApiUrl);
@@ -251,7 +262,7 @@ async function main() {
if (releasesToDelete.length === 0) {
success('沒有需要清理的舊版本成品');
} else {
section('刪除舊版本成品');
stage('刪除舊版本');
info(`DELETE_RELEASE_COUNT=${releasesToDelete.length}`);
for (const release of releasesToDelete) {
@@ -276,7 +287,7 @@ async function main() {
}
}
section('刪除未指定 release 的 tag');
stage('刪除舊版本');
// 重新取得 release 清單,得到刪除舊版本後仍指定 tag 的成品
const currentReleases = await fetchAllPages(releaseApiUrl);
@@ -311,8 +322,6 @@ async function main() {
fail(`刪除 tag 失敗: ${tagName}, HTTP ${code}`);
}
}
separator();
}
main().catch((err) => {