docs(calculate-version): 重建 README 並補齊指令檔註解與 logger JSDoc #12
+12
-12
@@ -20,7 +20,7 @@ const { writeOutput } = require('./output');
|
||||
* @param {Function} [deps.latestStableVersion] - 從 release 清單取得最新穩定版(舊版本)的函式。
|
||||
* @param {Function} [deps.nextVersion] - 依舊版本計算本次版本號的函式。
|
||||
* @param {Function} [deps.writeOutput] - 寫出 output 的函式。
|
||||
* @param {{section:Function, info:Function, error:Function}} [deps.log] - log 記錄器。
|
||||
* @param {{forStage:Function, info:Function, error:Function}} [deps.log] - log 記錄器;以 forStage(階段) 取得綁定階段的子記錄器後輸出。
|
||||
* @returns {Promise<string>} 計算出的版本號。
|
||||
* @throws {Error} 當任一注入相依(loadConfig/fetchReleases/latestStableVersion/nextVersion/writeOutput)
|
||||
* 拋出例外時,原樣向外傳播,由呼叫端決定如何結束。
|
||||
@@ -38,29 +38,29 @@ async function main(deps = {}) {
|
||||
} = deps;
|
||||
|
||||
// 1. 參數檢查:載入並驗證環境變數設定
|
||||
log.section('參數檢查');
|
||||
const checkLog = log.forStage('參數檢查');
|
||||
|
||||
const config = loadConfigFn();
|
||||
log.info(`GITEA_SERVER_URL=${config.serverUrl}`);
|
||||
log.info(`GITEA_REPOSITORY=${config.repository}`);
|
||||
log.info(config.token ? 'GITEA_TOKEN=***' : 'GITEA_TOKEN=未提供');
|
||||
log.info(`IS_BETA=${config.isBeta}`);
|
||||
checkLog.info(`GITEA_SERVER_URL=${config.serverUrl}`);
|
||||
checkLog.info(`GITEA_REPOSITORY=${config.repository}`);
|
||||
checkLog.info(config.token ? 'GITEA_TOKEN=***' : 'GITEA_TOKEN=未提供');
|
||||
checkLog.info(`IS_BETA=${config.isBeta}`);
|
||||
|
||||
// 2. 取得舊版本:抓取 release 清單並解析出最新穩定版
|
||||
log.section('取得舊版本');
|
||||
const fetchLog = log.forStage('取得舊版本');
|
||||
|
||||
const releaseUrl = `${config.serverUrl}/api/v1/repos/${config.repository}/releases`;
|
||||
log.info(`RELEASE_URL=${releaseUrl}`);
|
||||
fetchLog.info(`RELEASE_URL=${releaseUrl}`);
|
||||
|
||||
const releases = await fetchReleasesFn(releaseUrl, { token: config.token, logger: log });
|
||||
const releases = await fetchReleasesFn(releaseUrl, { token: config.token, logger: fetchLog });
|
||||
const latest = latestStableVersionFn(releases);
|
||||
log.info(`LATEST_VERSION=${latest}`);
|
||||
fetchLog.info(`LATEST_VERSION=${latest}`);
|
||||
|
||||
// 3. 計算版本號:依舊版本算出本次版本號並寫出 output
|
||||
log.section('計算版本號');
|
||||
const calcLog = log.forStage('計算版本號');
|
||||
|
||||
const version = nextVersionFn(latest, releases, config.isBeta);
|
||||
log.info(`NEW_VERSION=${version}`);
|
||||
calcLog.info(`NEW_VERSION=${version}`);
|
||||
writeOutputFn('version', version);
|
||||
|
||||
return version;
|
||||
|
||||
+42
-27
@@ -1,13 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
// 主分隔線與次分隔線寬度(沿用原 entrypoint.sh 的視覺樣式)
|
||||
const LINE = '='.repeat(50);
|
||||
const SUBLINE = '-'.repeat(50);
|
||||
|
||||
/**
|
||||
* 產生台灣時區(Asia/Taipei)的時間戳,格式固定為 `yyyy/MM/dd HH:mm:ss`。
|
||||
*
|
||||
* 供 log 訊息統一格式 `[{等級}][{時間}]: {訊息}` 的時間欄位使用。
|
||||
* 供 log 訊息統一格式 `[{階段}][{等級}][{時間}]: {訊息}` 的時間欄位使用。
|
||||
*
|
||||
* @returns {string} 台灣時區當下時間字串,例如 `2026/06/30 12:13:04`。
|
||||
*/
|
||||
@@ -31,51 +27,70 @@ function taipeiTimestamp() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 輸出帶標題的區塊段落至標準輸出,標題前後以分隔線包夾,
|
||||
* 用於在 log 中建立可視的段落區隔。
|
||||
* 將單一 log 訊息寫入指定輸出串流,格式統一為 `[{階段}][{等級}][{時間}]: {訊息}` 並於結尾換行。
|
||||
*
|
||||
* 輸出格式為:換行 + 主分隔線(50 個 `=`)+ 標題 + 次分隔線(50 個 `-`)。
|
||||
* 此為結構性段落標題(非 INF/WRN/ERR 等級訊息),故不套用 `[{等級}][{時間}]` 前綴。
|
||||
* 階段(stage)為選填;省略或空字串時略過開頭的 `[{階段}]` 區塊,輸出退化為 `[{等級}][{時間}]: {訊息}`。
|
||||
* 一次呼叫只輸出一則訊息(一行一則)。
|
||||
*
|
||||
* @param {string} title - 區塊標題文字;會原樣輸出於兩條分隔線之間。
|
||||
* @param {NodeJS.WriteStream} stream - 目標輸出串流(process.stdout 或 process.stderr)。
|
||||
* @param {string} level - 訊息等級,限 `INF`/`WRN`/`ERR`/`TRC`/`DBG`。
|
||||
* @param {string} message - 要輸出的訊息內容。
|
||||
* @param {string} [stage] - 階段名稱(選填)。
|
||||
* @returns {void}
|
||||
* @remarks 通常在進入一個處理階段前呼叫(例如「參數檢查」「取得舊版本」),
|
||||
* 用以在 CI/容器 log 中分隔各階段輸出,便於閱讀與定位。
|
||||
*/
|
||||
function section(title) {
|
||||
process.stdout.write(`\n${LINE}\n${title}\n${SUBLINE}\n`);
|
||||
function write(stream, level, message, stage) {
|
||||
const stagePrefix = stage ? `[${stage}]` : '';
|
||||
stream.write(`${stagePrefix}[${level}][${taipeiTimestamp()}]: ${message}\n`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 輸出一般資訊(INF)層級的 log 訊息至標準輸出。
|
||||
*
|
||||
* 訊息格式統一為 `[INF][{台灣時間}]: {訊息}`,時間使用台灣時區(Asia/Taipei),
|
||||
* 格式為 `yyyy/MM/dd HH:mm:ss`,並於結尾換行。
|
||||
* 訊息格式統一為 `[{階段}][INF][{台灣時間}]: {訊息}`,時間使用台灣時區(Asia/Taipei),
|
||||
* 格式為 `yyyy/MM/dd HH:mm:ss`,並於結尾換行;未提供 stage 時略過 `[{階段}]` 區塊。
|
||||
*
|
||||
* @param {string} message - 要輸出的資訊內容。
|
||||
* @param {string} [stage] - 階段名稱(選填),用於在訊息開頭標示所屬處理階段。
|
||||
* @returns {void}
|
||||
* @remarks 用於回報正常流程進度(如設定值、URL、各頁取得筆數);此調整僅變更輸出前綴格式,
|
||||
* 不改變訊息所反映的實際行為與內容。
|
||||
* @remarks 用於回報正常流程進度(如設定值、URL、各頁取得筆數);可直接呼叫,或經 forStage()
|
||||
* 取得綁定階段的子記錄器後以單一 message 參數呼叫。
|
||||
*/
|
||||
function info(message) {
|
||||
process.stdout.write(`[INF][${taipeiTimestamp()}]: ${message}\n`);
|
||||
function info(message, stage) {
|
||||
write(process.stdout, 'INF', message, stage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 輸出錯誤(ERR)層級的 log 訊息至標準錯誤輸出(stderr)。
|
||||
*
|
||||
* 訊息格式統一為 `[ERR][{台灣時間}]: {訊息}`,時間使用台灣時區(Asia/Taipei),
|
||||
* 格式為 `yyyy/MM/dd HH:mm:ss`,並於結尾換行。
|
||||
* 訊息格式統一為 `[{階段}][ERR][{台灣時間}]: {訊息}`,時間使用台灣時區(Asia/Taipei),
|
||||
* 格式為 `yyyy/MM/dd HH:mm:ss`,並於結尾換行;未提供 stage 時略過 `[{階段}]` 區塊。
|
||||
*
|
||||
* 僅負責輸出,不終止行程;是否結束由呼叫端(進入點)決定,以利測試與錯誤復原。
|
||||
*
|
||||
* @param {string} message - 要輸出的錯誤描述內容。
|
||||
* @param {string} [stage] - 階段名稱(選填),用於在訊息開頭標示所屬處理階段。
|
||||
* @returns {void}
|
||||
* @remarks 由進入點在頂層捕捉到例外時呼叫,輸出至 stderr 後再由呼叫端決定 exit code;
|
||||
* 此調整僅變更輸出前綴格式,不改變訊息所反映的實際行為與內容。
|
||||
* @remarks 由進入點在頂層捕捉到例外時呼叫(此情境無對應階段,省略 stage),輸出至 stderr 後
|
||||
* 再由呼叫端決定 exit code。
|
||||
*/
|
||||
function error(message) {
|
||||
process.stderr.write(`[ERR][${taipeiTimestamp()}]: ${message}\n`);
|
||||
function error(message, stage) {
|
||||
write(process.stderr, 'ERR', message, stage);
|
||||
}
|
||||
|
||||
module.exports = { section, info, error };
|
||||
/**
|
||||
* 建立綁定特定階段(stage)的子記錄器;其 info/error 會自動帶入該階段名稱,
|
||||
* 呼叫端僅需傳入 message 即可輸出 `[{階段}][{等級}][{時間}]: {訊息}`。
|
||||
*
|
||||
* @param {string} stage - 階段名稱,例如「參數檢查」「取得舊版本」「計算版本號」。
|
||||
* @returns {{ info: (message: string) => void, error: (message: string) => void }} 綁定該階段的記錄器。
|
||||
* @remarks 由進入點為每個處理階段建立一個子記錄器,使該階段(含其呼叫的 fetchReleases 等模組)
|
||||
* 輸出的每一則訊息都帶有一致的階段前綴,取代過往以分隔線區塊標示階段的做法。
|
||||
*/
|
||||
function forStage(stage) {
|
||||
return {
|
||||
info: (message) => info(message, stage),
|
||||
error: (message) => error(message, stage),
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { info, error, forStage };
|
||||
|
||||
Reference in New Issue
Block a user