'use strict'; const logger = require('./logger'); const { loadConfig } = require('./config'); const { fetchReleases } = require('./releases'); const { latestStableVersion, nextVersion } = require('./version'); const { writeOutput } = require('./output'); /** * Action 進入點:協調設定載入、release 取得、版本號計算與輸出寫出。 * * 失敗時(loadConfig 或 fetchReleases 拋錯)直接向外拋出例外,由呼叫端決定如何結束, * 以利單元測試覆蓋失敗路徑。相依模組可透過 deps 注入,預設使用各兄弟模組的實作。 * * 流程分為三個階段:1. 參數檢查 2. 取得舊版本 3. 計算版本號。 * * @param {Object} [deps={}] - 可注入的相依,供測試替換。 * @param {Function} [deps.loadConfig] - 載入設定的函式。 * @param {Function} [deps.fetchReleases] - 取得 release 的函式。 * @param {Function} [deps.latestStableVersion] - 從 release 清單取得最新穩定版(舊版本)的函式。 * @param {Function} [deps.nextVersion] - 依舊版本計算本次版本號的函式。 * @param {Function} [deps.writeOutput] - 寫出 output 的函式。 * @param {{forStage:Function, info:Function, error:Function}} [deps.log] - log 記錄器;以 forStage(階段) 取得綁定階段的子記錄器後輸出。 * @returns {Promise} 計算出的版本號。 * @throws {Error} 當任一注入相依(loadConfig/fetchReleases/latestStableVersion/nextVersion/writeOutput) * 拋出例外時,原樣向外傳播,由呼叫端決定如何結束。 * @remarks 由模組底部的 require.main 守衛在被直接執行時呼叫;失敗時頂層以模組層級 logger.error 輸出 * 並 exit(1)。單元測試可透過 deps 注入替身以覆蓋成功與各失敗路徑。 */ async function main(deps = {}) { const { loadConfig: loadConfigFn = loadConfig, fetchReleases: fetchReleasesFn = fetchReleases, latestStableVersion: latestStableVersionFn = latestStableVersion, nextVersion: nextVersionFn = nextVersion, writeOutput: writeOutputFn = writeOutput, log = logger, } = deps; // 1. 參數檢查:載入並驗證環境變數設定 const checkLog = log.forStage('參數檢查'); const config = loadConfigFn(); 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 清單並解析出最新穩定版 const fetchLog = log.forStage('取得舊版本'); const releaseUrl = `${config.serverUrl}/api/v1/repos/${config.repository}/releases`; fetchLog.info(`RELEASE_URL=${releaseUrl}`); const releases = await fetchReleasesFn(releaseUrl, { token: config.token, logger: fetchLog }); const latest = latestStableVersionFn(releases); fetchLog.info(`LATEST_VERSION=${latest}`); // 3. 計算版本號:依舊版本算出本次版本號並寫出 output const calcLog = log.forStage('計算版本號'); const version = nextVersionFn(latest, releases, config.isBeta); calcLog.info(`NEW_VERSION=${version}`); writeOutputFn('version', version); return version; } // 僅在被直接執行時啟動(被 require/測試載入時不自動執行),失敗則在頂層回報並以狀態碼 1 結束 if (require.main === module) { main().catch((error) => { logger.error(error.message); process.exit(1); }); } module.exports = { main };