@@ -1,8 +1,8 @@
# calculate-version
# calculate-version
> 更新時間:2026/06/26 10:49 :46
> 更新時間:2026/06/30 12:32 :40
計算版本號的 Gitea Action。依現有 release 推算下一個穩定版或 beta 版本號,並將結果寫入 Action output `version` 。核心邏輯以 Node.js 實作,置於 `app/` ,由 `entrypoint.sh` 作為容器進入點啟動。
計算版本號的 Gitea Action。依現有 release 推算下一個穩定版或 beta 版本號,並將結果寫入 Action output `version` 。核心邏輯以 Node.js 實作,置於 `app/` ,由 `entrypoint.sh` 作為容器進入點啟動;容器映像採多階段建置(build 階段 `node:latest` 、runtime 階段 `node:slim` ) 。
版本進位規則:`patch + 1` ;當 `patch` 達 10 進位至 `minor` , `minor` 達 10 進位至 `major` 。beta 版本號形如 `<next>-beta.<n>` ,其中 `<n>` 為該版本既有 beta 標籤的最大序號加 1。
版本進位規則:`patch + 1` ;當 `patch` 達 10 進位至 `minor` , `minor` 達 10 進位至 `major` 。beta 版本號形如 `<next>-beta.<n>` ,其中 `<n>` 為該版本既有 beta 標籤的最大序號加 1。
@@ -32,15 +32,15 @@
| 功能名稱 | 功能描述 |
| 功能名稱 | 功能描述 |
| --- | --- |
| --- | --- |
| [index.main ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/index.js#L23 ) | [Action 進入點:協調設定載入、release 取得、版本計算與輸出(支援相依注入)。 ](#indexmain ) |
| [index.main ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/index.js#L27 ) | [Action 進入點:協調設定載入、release 取得、版本計算與輸出(支援相依注入)。 ](#indexmain ) |
### logger( app/logger.js)
### logger( app/logger.js)
| 功能名稱 | 功能描述 |
| 功能名稱 | 功能描述 |
| --- | --- |
| --- | --- |
| [logger.section ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/logger.js#L16 ) | [輸出帶標題的區塊段落至標準輸出,標題前後以分隔線包夾。 ](#loggersection ) |
| [logger.section ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/logger.js#L45 ) | [輸出帶標題的區塊段落至標準輸出,標題前後以分隔線包夾。 ](#loggersection ) |
| [logger.info ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/logger.js#L2 6 ) | [輸出一般資訊 層級的 log 訊息,自動加上 `[info]` 前綴 。](#loggerinfo ) |
| [logger.info ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/logger.js#L60 ) | [輸出 INF 層級 log 訊息,格式為 `[INF][時間]: 訊息` 。](#loggerinfo ) |
| [logger.error ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/logger.js#L38 ) | [輸出錯誤 訊息至 stderr(僅輸出, 不終止行程)。 ](#loggererror ) |
| [logger.error ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/logger.js#L77 ) | [輸出 ERR 層級 訊息至 stderr( 格式為 `[ERR][時間]: 訊息` , 僅輸出不終止行程)。](#loggererror ) |
### config( app/config.js)
### config( app/config.js)
@@ -49,30 +49,30 @@
| [config.isUnset ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/config.js#L11 ) | [判斷環境變數值是否視為「未設定」。 ](#configisunset ) |
| [config.isUnset ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/config.js#L11 ) | [判斷環境變數值是否視為「未設定」。 ](#configisunset ) |
| [config.requireEnv ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/config.js#L23 ) | [驗證必填環境變數,未設定時拋出錯誤。 ](#configrequireenv ) |
| [config.requireEnv ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/config.js#L23 ) | [驗證必填環境變數,未設定時拋出錯誤。 ](#configrequireenv ) |
| [config.normalizeBetaFlag ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/config.js#L38 ) | [將 beta 旗標正規化為布林值。 ](#confignormalizebetaflag ) |
| [config.normalizeBetaFlag ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/config.js#L38 ) | [將 beta 旗標正規化為布林值。 ](#confignormalizebetaflag ) |
| [config.loadConfig ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/config.js#L6 8 ) | [從環境變數載入並驗證執行所需的設定。 ](#configloadconfig ) |
| [config.loadConfig ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/config.js#L80 ) | [從環境變數載入並驗證執行所需的設定。 ](#configloadconfig ) |
### version( app/version.js)
### version( app/version.js)
| 功能名稱 | 功能描述 |
| 功能名稱 | 功能描述 |
| --- | --- |
| --- | --- |
| [version.compareVersionArrays ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/version.js#L12 ) | [逐區段比較兩個版本號數值陣列,較短者視為較小。 ](#versioncompareversionarrays ) |
| [version.compareVersionArrays ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/version.js#L14 ) | [逐區段比較兩個版本號數值陣列,較短者視為較小。 ](#versioncompareversionarrays ) |
| [version.parseStableVersions ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/version.js#L36 ) | [從 release 清單解析出所有穩定版的版本號數值陣列。 ](#versionparsestableversions ) |
| [version.parseStableVersions ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/version.js#L38 ) | [從 release 清單解析出所有穩定版的版本號數值陣列。 ](#versionparsestableversions ) |
| [version.latestStableVersion ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/version.js#L55 ) | [取得 release 清單中最新的穩定版版本號字串。 ](#versionlateststableversion ) |
| [version.latestStableVersion ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/version.js#L57 ) | [取得 release 清單中最新的穩定版版本號字串。 ](#versionlateststableversion ) |
| [version.nextReleaseVersion ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/version.js#L74 ) | [依最新穩定版計算下一個發行版本號。 ](#versionnextreleaseversion ) |
| [version.nextReleaseVersion ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/version.js#L78 ) | [依最新穩定版計算下一個發行版本號。 ](#versionnextreleaseversion ) |
| [version.nextBetaNumber ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/version.js#L97 ) | [計算指定版本號的下一個 beta 流水號。 ](#versionnextbetanumber ) |
| [version.nextBetaNumber ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/version.js#L101 ) | [計算指定版本號的下一個 beta 流水號。 ](#versionnextbetanumber ) |
| [version.calculateVersion ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/version.js#L122 ) | [計算最新穩定版與下一個版本號(支援 beta)。 ](#versioncalculateversion ) |
| [version.calculateVersion ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/version.js#L126 ) | [計算最新穩定版與下一個版本號(支援 beta)。 ](#versioncalculateversion ) |
### releases( app/releases.js)
### releases( app/releases.js)
| 功能名稱 | 功能描述 |
| 功能名稱 | 功能描述 |
| --- | --- |
| --- | --- |
| [releases.fetchReleases ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/releases.js#L22 ) | [以分頁方式取得指定 Gitea repo 的所有 release。 ](#releasesfetchreleases ) |
| [releases.fetchReleases ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/releases.js#L24 ) | [以分頁方式取得指定 Gitea repo 的所有 release。 ](#releasesfetchreleases ) |
### output( app/output.js)
### output( app/output.js)
| 功能名稱 | 功能描述 |
| 功能名稱 | 功能描述 |
| --- | --- |
| --- | --- |
| [output.writeOutput ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/output.js#L14 ) | [將一行 `name=value` 附加寫入 Action 的輸出檔。 ](#outputwriteoutput ) |
| [output.writeOutput ](https://gitea.jsc.idv.tw/docker-actions/calculate-version/src/branch/develop/app/output.js#L16 ) | [將一行 `name=value` 附加寫入 Action 的輸出檔。 ](#outputwriteoutput ) |
## 使用範例
## 使用範例
@@ -97,7 +97,7 @@ const version = await main({
<a id="loggersection"></a>
<a id="loggersection"></a>
### logger.section
### logger.section
輸出帶標題的區塊段落至標準輸出:先一個換行,接著 50 個 `=` 的主分隔線、標題文字,最後 50 個 `-` 的次分隔線,用於在 log 中建立可視段落區隔。
輸出帶標題的區塊段落至標準輸出:先一個換行,接著 50 個 `=` 的主分隔線、標題文字,最後 50 個 `-` 的次分隔線,用於在 log 中建立可視段落區隔。此為結構性段落標題,不套用 `[等級][時間]` 前綴。
``` js
``` js
const logger = require ( './logger' ) ;
const logger = require ( './logger' ) ;
@@ -113,25 +113,25 @@ logger.section('參數檢查');
<a id="loggerinfo"></a>
<a id="loggerinfo"></a>
### logger.info
### logger.info
輸出一般資訊層級訊息至標準輸出,自動加上 `[info]` 前綴與 換行;不會結束行程。
輸出一般資訊( INF) 層級訊息至標準輸出,格式統一為 `[INF][{時間}]: {訊息}` ,時間使用台灣時區(Asia/Taipei)、格式 `yyyy/MM/dd HH:mm:ss` ,並於結尾 換行;不會結束行程。
``` js
``` js
const logger = require ( './logger' ) ;
const logger = require ( './logger' ) ;
logger . info ( 'IS_BETA=false' ) ;
logger . info ( 'IS_BETA=false' ) ;
// 輸出:[info] IS_BETA=false
// 輸出:[INF][2026/06/30 12:00:00]: IS_BETA=false
```
```
<a id="loggererror"></a>
<a id="loggererror"></a>
### logger.error
### logger.error
輸出錯誤訊息至標準錯誤輸出(stderr),自動加上 `[error]` 前綴與換行 。僅負責輸出,**不終止行程**;是否結束由呼叫端(進入點)決定,以利測試與錯誤復原。
輸出錯誤( ERR)層級 訊息至標準錯誤輸出(stderr),格式統一為 `[ERR][{時間}]: {訊息}` (時間為台灣時區) 。僅負責輸出,**不終止行程**;是否結束由呼叫端(進入點)決定,以利測試與錯誤復原。
``` js
``` js
const logger = require ( './logger' ) ;
const logger = require ( './logger' ) ;
logger . error ( 'GITEA_SERVER_URL 未設定' ) ;
logger . error ( 'GITEA_SERVER_URL 未設定' ) ;
// 對 stderr 輸出:[error] GITEA_SERVER_URL 未設定
// 對 stderr 輸出:[ERR][2026/06/30 12:00:00]: GITEA_SERVER_URL 未設定
```
```
<a id="configisunset"></a>
<a id="configisunset"></a>
@@ -191,7 +191,7 @@ const config = loadConfig({
<a id="versioncompareversionarrays"></a>
<a id="versioncompareversionarrays"></a>
### version.compareVersionArrays
### version.compareVersionArrays
逐區段(element-wise)比較兩個版本號數值陣列,較短的陣列視為較小。回傳值 `> 0` 表示 a 大於 b、`< 0` 表示 a 小於 b、`0` 表示相等。
逐區段(element-wise)比較兩個版本號數值陣列,較短的陣列視為較小。回傳值 `> 0` 表示 a 大於 b、`< 0` 表示 a 小於 b、`0` 表示相等;相異區段回傳的是該段差值(非固定 ±1) 。
``` js
``` js
const { compareVersionArrays } = require ( './version' ) ;
const { compareVersionArrays } = require ( './version' ) ;
@@ -203,7 +203,7 @@ compareVersionArrays([1, 2], [1, 2, 0]); // < 0(較短者較小)
<a id="versionparsestableversions"></a>
<a id="versionparsestableversions"></a>
### version.parseStableVersions
### version.parseStableVersions
從 release 清單解析出所有穩定版(排除 beta、排除格式不合法者)的版本號數值陣列;會去除 tag 開頭的 `v` 。
從 release 清單解析出所有穩定版(排除 beta、排除格式不合法者)的版本號數值陣列;會去除 tag 開頭的 `v` 。傳入非陣列時回傳空陣列。
``` js
``` js
const { parseStableVersions } = require ( './version' ) ;
const { parseStableVersions } = require ( './version' ) ;
@@ -231,7 +231,7 @@ latestStableVersion([]); // "0.0.0"
<a id="versionnextreleaseversion"></a>
<a id="versionnextreleaseversion"></a>
### version.nextReleaseVersion
### version.nextReleaseVersion
依最新穩定版字串計算下一個發行版本號:`patch + 1` , `patch` 達 10 進位至 `minor` , `minor` 達 10 進位至 `major` 。
依最新穩定版字串計算下一個發行版本號:`patch + 1` , `patch` 達 10 進位至 `minor` , `minor` 達 10 進位至 `major` (「逢 10 進位」為本專案自訂約定,非標準 SemVer) 。
``` js
``` js
const { nextReleaseVersion } = require ( './version' ) ;
const { nextReleaseVersion } = require ( './version' ) ;
@@ -271,7 +271,7 @@ calculateVersion([{ tag_name: 'v1.2.3' }], true);
<a id="releasesfetchreleases"></a>
<a id="releasesfetchreleases"></a>
### releases.fetchReleases
### releases.fetchReleases
以分頁方式取得指定 Gitea repo 的所有 release,並回傳合併後的陣列。使用全域 `fetch` 逐頁請求(每頁 limit 為 10);當某頁回傳空資料、`null` 或筆數少於上限時即停止。提供 `options.token` 時以授權方式請求。網路失敗、回應讀取失敗、非 2xx、無法解析或非陣列回應時拋出 `Error` (含頁碼)。
以分頁方式取得指定 Gitea repo 的所有 release,並回傳合併後的陣列。使用全域 `fetch` ( Node.js 18+) 逐頁請求(每頁 limit 為 10);當某頁回傳空資料、`null` 或筆數少於上限時即停止。提供 `options.token` 時以授權方式請求。網路失敗、回應讀取失敗、非 2xx、無法解析或非陣列回應時拋出 `Error` (含頁碼)。
``` js
``` js
const { fetchReleases } = require ( './releases' ) ;
const { fetchReleases } = require ( './releases' ) ;
@@ -287,7 +287,7 @@ const releases = await fetchReleases(
<a id="outputwriteoutput"></a>
<a id="outputwriteoutput"></a>
### output.writeOutput
### output.writeOutput
將一行 `name=value` 附加寫入 GitHub/Gitea Action 的輸出檔(預設取 `process.env.GITHUB_OUTPUT` )。輸出檔路徑為 falsy 時拋出 `Error` 。
將一行 `name=value` 附加寫入 GitHub/Gitea Action 的輸出檔(預設取 `process.env.GITHUB_OUTPUT` )。以 append 方式寫入、不覆蓋既有內容; 輸出檔路徑為 falsy 時拋出 `Error` 。
``` js
``` js
const { writeOutput } = require ( './output' ) ;
const { writeOutput } = require ( './output' ) ;