From 11e2808da68ffa12fd4cc6472638d252dedaea11 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 30 Jun 2026 16:16:31 +0800 Subject: [PATCH 1/3] =?UTF-8?q?refactor(=E7=89=88=E6=9C=AC=E8=A8=88?= =?UTF-8?q?=E7=AE=97=E6=B5=81=E7=A8=8B):=20=E5=B0=87=20main=20=E6=8B=86?= =?UTF-8?q?=E6=88=90=E5=8F=83=E6=95=B8=E6=AA=A2=E6=9F=A5=E3=80=81=E5=8F=96?= =?UTF-8?q?=E5=BE=97=E8=88=8A=E7=89=88=E6=9C=AC=E3=80=81=E8=A8=88=E7=AE=97?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E8=99=9F=E4=B8=89=E9=9A=8E=E6=AE=B5=E4=B8=A6?= =?UTF-8?q?=E6=8A=BD=E5=87=BA=20nextVersion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/index.js | 24 ++++++++++++++++-------- app/version.js | 28 ++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/app/index.js b/app/index.js index 9cf09b7..2bf60f2 100644 --- a/app/index.js +++ b/app/index.js @@ -3,7 +3,7 @@ const logger = require('./logger'); const { loadConfig } = require('./config'); const { fetchReleases } = require('./releases'); -const { calculateVersion } = require('./version'); +const { latestStableVersion, nextVersion } = require('./version'); const { writeOutput } = require('./output'); /** @@ -12,15 +12,18 @@ const { writeOutput } = require('./output'); * 失敗時(loadConfig 或 fetchReleases 拋錯)直接向外拋出例外,由呼叫端決定如何結束, * 以利單元測試覆蓋失敗路徑。相依模組可透過 deps 注入,預設使用各兄弟模組的實作。 * + * 流程分為三個階段:1. 參數檢查 2. 取得舊版本 3. 計算版本號。 + * * @param {Object} [deps={}] - 可注入的相依,供測試替換。 * @param {Function} [deps.loadConfig] - 載入設定的函式。 * @param {Function} [deps.fetchReleases] - 取得 release 的函式。 - * @param {Function} [deps.calculateVersion] - 計算版本號的函式。 + * @param {Function} [deps.latestStableVersion] - 從 release 清單取得最新穩定版(舊版本)的函式。 + * @param {Function} [deps.nextVersion] - 依舊版本計算本次版本號的函式。 * @param {Function} [deps.writeOutput] - 寫出 output 的函式。 * @param {{section:Function, info:Function, error:Function}} [deps.log] - log 記錄器。 * @returns {Promise} 計算出的版本號。 - * @throws {Error} 當任一注入相依(loadConfig/fetchReleases/calculateVersion/writeOutput)拋出例外時, - * 原樣向外傳播,由呼叫端決定如何結束。 + * @throws {Error} 當任一注入相依(loadConfig/fetchReleases/latestStableVersion/nextVersion/writeOutput) + * 拋出例外時,原樣向外傳播,由呼叫端決定如何結束。 * @remarks 由模組底部的 require.main 守衛在被直接執行時呼叫;失敗時頂層以模組層級 logger.error 輸出 * 並 exit(1)。單元測試可透過 deps 注入替身以覆蓋成功與各失敗路徑。 */ @@ -28,11 +31,13 @@ async function main(deps = {}) { const { loadConfig: loadConfigFn = loadConfig, fetchReleases: fetchReleasesFn = fetchReleases, - calculateVersion: calculateVersionFn = calculateVersion, + latestStableVersion: latestStableVersionFn = latestStableVersion, + nextVersion: nextVersionFn = nextVersion, writeOutput: writeOutputFn = writeOutput, log = logger, } = deps; + // 1. 參數檢查:載入並驗證環境變數設定 log.section('參數檢查'); const config = loadConfigFn(); @@ -41,17 +46,20 @@ async function main(deps = {}) { log.info(config.token ? 'GITEA_TOKEN=***' : 'GITEA_TOKEN=未提供'); log.info(`IS_BETA=${config.isBeta}`); - log.section('取得版本資料'); + // 2. 取得舊版本:抓取 release 清單並解析出最新穩定版 + log.section('取得舊版本'); const releaseUrl = `${config.serverUrl}/api/v1/repos/${config.repository}/releases`; log.info(`RELEASE_URL=${releaseUrl}`); const releases = await fetchReleasesFn(releaseUrl, { token: config.token, logger: log }); - - const { latest, version } = calculateVersionFn(releases, config.isBeta); + const latest = latestStableVersionFn(releases); log.info(`LATEST_VERSION=${latest}`); + // 3. 計算版本號:依舊版本算出本次版本號並寫出 output log.section('計算版本號'); + + const version = nextVersionFn(latest, releases, config.isBeta); log.info(`NEW_VERSION=${version}`); writeOutputFn('version', version); diff --git a/app/version.js b/app/version.js index 49c973a..6a941db 100644 --- a/app/version.js +++ b/app/version.js @@ -115,6 +115,26 @@ function nextBetaNumber(releases, version) { return max + 1; } +/** + * 依「已知的最新穩定版」計算本次要使用的版本號;isBeta 為 true 時產生 beta 版本號。 + * + * 此函式不負責「取得舊版本」(latest 由呼叫端傳入),僅負責「計算版本號」這一步, + * 讓取得舊版本與計算新版本兩個階段可各自獨立。 + * + * @param {string} latest - 已知的最新穩定版版本號字串(如 "1.2.3";查無時為 "0.0.0")。 + * @param {Array<{tag_name?: string}>} releases - release 物件清單;beta 流水號需據此比對。 + * @param {boolean} isBeta - 是否產生 beta 版本號;true 時回傳形如 "-beta."。 + * @returns {string} 本次要使用的版本號字串;非 beta 為下一個發行版(如 "1.3.0"), + * beta 為 "-beta."(如 "1.3.0-beta.1")。 + */ +function nextVersion(latest, releases, isBeta) { + const next = nextReleaseVersion(latest); + + return isBeta + ? `${next}-beta.${nextBetaNumber(releases, next)}` + : next; +} + /** * 計算最新穩定版與下一個版本號;isBeta 為 true 時產生 beta 版本號。 * @param {Array<{tag_name?: string}>} releases - release 物件清單。 @@ -125,13 +145,8 @@ function nextBetaNumber(releases, version) { */ function calculateVersion(releases, isBeta) { const latest = latestStableVersion(releases); - const next = nextReleaseVersion(latest); - const version = isBeta - ? `${next}-beta.${nextBetaNumber(releases, next)}` - : next; - - return { latest, version }; + return { latest, version: nextVersion(latest, releases, isBeta) }; } module.exports = { @@ -140,5 +155,6 @@ module.exports = { latestStableVersion, nextReleaseVersion, nextBetaNumber, + nextVersion, calculateVersion, }; -- 2.53.0 From ffd176a69f918e7fda81ffcf021a66d7247e7b38 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 30 Jun 2026 16:16:34 +0800 Subject: [PATCH 2/3] =?UTF-8?q?test(version):=20=E8=A3=9C=E4=B8=8A=20nextV?= =?UTF-8?q?ersion=20=E7=9A=84=E5=96=AE=E5=85=83=E6=B8=AC=E8=A9=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/test/version.test.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/test/version.test.js b/app/test/version.test.js index 5d3a636..a49f022 100644 --- a/app/test/version.test.js +++ b/app/test/version.test.js @@ -8,6 +8,7 @@ const { latestStableVersion, nextReleaseVersion, nextBetaNumber, + nextVersion, calculateVersion, } = require('../version'); @@ -77,6 +78,16 @@ test('nextBetaNumber 取對應 beta 流水號最大值 + 1', () => { assert.equal(nextBetaNumber(releases, '1.2.4'), 4); }); +test('nextVersion 依舊版本計算下一個穩定版', () => { + assert.equal(nextVersion('1.2.3', [], false), '1.2.4'); + assert.equal(nextVersion('0.0.0', [], false), '0.0.1'); +}); + +test('nextVersion 依舊版本計算下一個 beta 版', () => { + const releases = [{ tag_name: 'v1.2.4-beta.2' }]; + assert.equal(nextVersion('1.2.3', releases, true), '1.2.4-beta.3'); +}); + test('calculateVersion 計算下一個穩定版', () => { assert.deepEqual( calculateVersion([{ tag_name: 'v1.2.3' }], false), -- 2.53.0 From 0c3360fd8cc4577ae6314d9d46596fe3e2f53126 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 30 Jun 2026 16:28:10 +0800 Subject: [PATCH 3/3] =?UTF-8?q?chore(ci=20workflow):=20=E5=B0=87=20CI=20?= =?UTF-8?q?=E6=94=B9=E7=82=BA=E9=87=8B=E5=87=BA=E6=A8=99=E7=89=88=E4=B8=A6?= =?UTF-8?q?=E8=A8=88=E7=AE=97=E7=89=88=E6=9C=AC=E8=99=9F=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/ci.yaml | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 8013bc9..44a1521 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -16,25 +16,21 @@ on: # 僅在 PR 開啟 (opened) 或有新 commit 推送 (synchronize) 時觸發。 types: [opened, synchronize] jobs: - # job 識別碼:AI 程式碼審查。 - ai-code-review: - # job 顯示名稱。 - name: AI Code Review - # 指定執行於 ubuntu runner。 + release-tag-version: + name: Release Tag Version runs-on: ubuntu - # 此 job 所需的權限 (供 AI 寫回審查結果)。 - permissions: - # 可寫入儲存庫內容。 - contents: write - # 可在 PR 上留言/變更狀態。 - pull-requests: write - # 可建立/更新 issue。 - issues: write + outputs: + version: ${{ steps.release-tag-version.outputs.version }} steps: - # 呼叫共用的 OpenCode 程式碼審查 composite action。 - - name: AI 程式碼審查 by OpenCode - # 版本以變數 ACTION_OPENCODE_CODE_REVIEW_VERSION 控制,便於統一升級。 - uses: https://gitea.jsc.idv.tw/composite-actions/opencode-code-review@${{ vars.ACTION_OPENCODE_CODE_REVIEW_VERSION }} + - name: 釋出並標註成品版本 + id: release-tag-version + uses: https://gitea.jsc.idv.tw/composite-actions/release-tag-version@${{ vars.ACTION_RELEASE_TAG_VERSION }} with: - # 傳入留言用 token (secret),供 action 在 PR 上發表審查留言。 - comment_token: ${{ secrets.COMMENT_TOKEN }} + is_beta: true + calculate-version: + name: Calculate Version + runs-on: ubuntu + needs: release-tag-version + steps: + - name: 計算版本號 + uses: https://gitea.jsc.idv.tw/docker-actions/calculate-version@v${{ needs.release-tag-version.outputs.version }} -- 2.53.0