Files
calculate-next-version/README.md
T
JefferyandClaude Fable 5 1773c646d5
docker-actions/template: CI / BUILD (pull_request) Successful in 4s
refactor: 統一日誌格式為 [階段][等級][時間] 並補齊指令檔文件與 README
- logger.js format() 組字順序改為階段在前、等級居中、時間在後(Asia/Taipei)
- entrypoint.sh 啟動訊息改用新格式並更新標頭時間
- action.yml 新增用途/更新時間標頭與逐行繁中註解,設定值不變
- dockerfile 檔名維持小寫並與 action.yml 的 image 引用一致
- 新增 src/logger.js、src/version.js 模組與完整 JSDoc;重建 README.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 09:30:44 +08:00

192 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Calculate Next Version
從 git tag 取得最新版號,依 `is_beta` 計算下一個正式版或 beta 版號(各號碼滿 9 進位)並輸出為 `value` 的 Gitea/GitHub Docker container action。
- 更新時間:2026/07/16 09:23:47
## action 使用方式
```yaml
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # 需要完整 tag 歷史才能計算版號
- id: version
uses: docker-actions/calculate-next-version@master
with:
is_beta: 'false'
- run: echo "下一版號:${{ steps.version.outputs.value }}"
```
| 類型 | 名稱 | 必填 | 預設值 | 說明 |
| --- | --- | --- | --- | --- |
| input | `is_beta` | 否 | `false` | 是否為 beta 版(true 時產生 X.Y.Z-beta.N 版號) |
| output | `value` | — | — | 計算出的下一版號 |
版號規則:
- 版號來源為 repo 的 git tag(格式 `X.Y.Z``X.Y.Z-beta.N`,不帶前綴),取最大版號;無任何版號 tag 時從 `0.0.1`beta 為 `0.0.1-beta.1`)起算。
- `is_beta=false`:最新為正式版 → patch +1`1.2.3``1.2.4`);最新為 beta → 去掉 beta 尾碼轉正式(`1.2.4-beta.3``1.2.4`)。
- `is_beta=true`:最新為正式版 → patch +1 加 `-beta.1`;最新為 beta → beta 號 +1`beta.9``beta.10`,無上限)。
- major/minor/patch 各上限 9,滿 9 進位(`1.2.9``1.3.0``1.9.9``2.0.0`);`9.9.9` 再進位則報錯並以非零 exit code 結束。
日誌格式:所有輸出訊息統一為 `[階段][等級][時間]: 訊息``階段` 選填;`等級``INF`/`WRN`/`ERR`/`TRC`/`DBG``時間` 為 Asia/Taipei 時區的 `yyyy/MM/dd HH:mm:ss`)。
## 專案列表
### 專案描述表
| 專案名稱 | 專案描述 |
| --- | --- |
| [calculate-next-version](https://gitea.jsc.idv.tw/docker-actions/calculate-next-version/src/branch/master) | Docker container action:提供版號解析/比較/進位計算(version 模組)與統一格式日誌輸出(logger 模組),從 git tag 計算下一個正式版或 beta 版號並寫出為 action 輸出 `value`。 |
### 參考專案表
| 專案名稱 | 參考專案列表 |
| --- | --- |
| [calculate-next-version](https://gitea.jsc.idv.tw/docker-actions/calculate-next-version/src/branch/master) | 無 |
### NuGet 套件表
| 專案名稱 | NuGet 套件列表 |
| --- | --- |
| [calculate-next-version](https://gitea.jsc.idv.tw/docker-actions/calculate-next-version/src/branch/master) | 無(Node.js 專案,僅使用 node 內建模組,無外部相依) |
## 功能列表
### calculate-next-version
| 功能名稱 | 功能描述 |
| --- | --- |
| [logger.inf](https://gitea.jsc.idv.tw/docker-actions/calculate-next-version/src/branch/master/src/logger.js#L86) | [輸出 INF(一般資訊)等級的日誌訊息到 stdout](#loggerinf) |
| [logger.wrn](https://gitea.jsc.idv.tw/docker-actions/calculate-next-version/src/branch/master/src/logger.js#L101) | [輸出 WRN(警告)等級的日誌訊息到 stdout](#loggerwrn) |
| [logger.err](https://gitea.jsc.idv.tw/docker-actions/calculate-next-version/src/branch/master/src/logger.js#L116) | [輸出 ERR(錯誤)等級的日誌訊息到 stderr](#loggererr) |
| [logger.trc](https://gitea.jsc.idv.tw/docker-actions/calculate-next-version/src/branch/master/src/logger.js#L131) | [輸出 TRC(細部追蹤)等級的日誌訊息到 stdout](#loggertrc) |
| [logger.dbg](https://gitea.jsc.idv.tw/docker-actions/calculate-next-version/src/branch/master/src/logger.js#L146) | [輸出 DBG(除錯)等級的日誌訊息到 stdout](#loggerdbg) |
| [version.parse](https://gitea.jsc.idv.tw/docker-actions/calculate-next-version/src/branch/master/src/version.js#L26) | [解析版號字串為版號物件,不符格式回傳 null](#versionparse) |
| [version.stringify](https://gitea.jsc.idv.tw/docker-actions/calculate-next-version/src/branch/master/src/version.js#L52) | [將版號物件轉換為版號字串](#versionstringify) |
| [version.compare](https://gitea.jsc.idv.tw/docker-actions/calculate-next-version/src/branch/master/src/version.js#L72) | [比較兩個版號物件的大小,正式版大於同號 beta](#versioncompare) |
| [version.next](https://gitea.jsc.idv.tw/docker-actions/calculate-next-version/src/branch/master/src/version.js#L136) | [依最新版號與 is_beta 旗標計算下一版號](#versionnext) |
## 使用範例
<a id="loggerinf"></a>
### logger.inf
輸出 INF(一般資訊)等級的日誌訊息到 stdout,格式為 `[階段][等級][時間]: 訊息`(時間為 Asia/Taipei 時區的 `yyyy/MM/dd HH:mm:ss`);`stage` 選填,省略時訊息不含 `[階段]` 區塊。用於記錄流程中的正常進度,例如讀到的輸入、計算結果、寫出的輸出。
```javascript
const logger = require('./logger');
logger.inf('下一版號:1.2.4', '計算版號');
// [計算版號][INF][2026/07/16 09:23:47]: 下一版號:1.2.4
logger.inf('計算完成');
// [INF][2026/07/16 09:23:47]: 計算完成
```
<a id="loggerwrn"></a>
### logger.wrn
輸出 WRN(警告)等級的日誌訊息到 stdout,格式與參數同 `logger.inf`。用於非致命的異常狀況,例如找不到任何版號 tag、需注意的邊界條件。
```javascript
const logger = require('./logger');
logger.wrn('找不到任何符合 X.Y.Z 或 X.Y.Z-beta.N 格式的 tag,將從起始版號計算', '讀取版號');
// [讀取版號][WRN][2026/07/16 09:23:47]: 找不到任何符合 X.Y.Z 或 X.Y.Z-beta.N 格式的 tag,將從起始版號計算
```
<a id="loggererr"></a>
### logger.err
輸出 ERR(錯誤)等級的日誌訊息到 stderr(`console.error`),格式與參數同 `logger.inf`。用於可預期錯誤與未捕捉例外的回報;呼叫端通常在輸出後以非零 exit code 結束。
```javascript
const logger = require('./logger');
logger.err('找不到環境變數 GITHUB_OUTPUT,無法寫出輸出', '寫出結果');
// [寫出結果][ERR][2026/07/16 09:23:47]: 找不到環境變數 GITHUB_OUTPUT,無法寫出輸出
process.exit(1);
```
<a id="loggertrc"></a>
### logger.trc
輸出 TRC(細部追蹤)等級的日誌訊息到 stdout,格式與參數同 `logger.inf`。用於記錄低層次操作的細節,例如實際執行的外部指令、逐筆解析的中間結果。
```javascript
const logger = require('./logger');
logger.trc('執行指令:git tag --list', '讀取版號');
// [讀取版號][TRC][2026/07/16 09:23:47]: 執行指令:git tag --list
```
<a id="loggerdbg"></a>
### logger.dbg
輸出 DBG(除錯)等級的日誌訊息到 stdout,格式與參數同 `logger.inf`。用於協助開發者追蹤程式流程與詳細狀態,例如被略過的不符格式 tag。
```javascript
const logger = require('./logger');
logger.dbg('略過不符合版號格式的 tagnot-a-version', '讀取版號');
// [讀取版號][DBG][2026/07/16 09:23:47]: 略過不符合版號格式的 tagnot-a-version
```
<a id="versionparse"></a>
### version.parse
解析版號字串為版號物件 `{ major, minor, patch, beta }`;支援正式版(`X.Y.Z`)與 beta 版(`X.Y.Z-beta.N`)兩種格式,`beta``null` 表示正式版。不符合格式(含 `null`、非字串轉出的值)時回傳 `null`、不拋出例外,適合逐一解析 git tag 並過濾非版號 tag。
```javascript
const { parse } = require('./version');
parse('1.2.3'); // => { major: 1, minor: 2, patch: 3, beta: null }
parse('1.2.3-beta.5'); // => { major: 1, minor: 2, patch: 3, beta: 5 }
parse('v1.2'); // => null(不符合格式)
```
<a id="versionstringify"></a>
### version.stringify
將版號物件轉換為版號字串;`beta``null` 時輸出 `X.Y.Z`,否則輸出 `X.Y.Z-beta.N`。為 `version.parse` 的反向操作,用於日誌輸出與最終寫出 action 的 `value`
```javascript
const { stringify } = require('./version');
stringify({ major: 1, minor: 2, patch: 3, beta: null }); // => '1.2.3'
stringify({ major: 1, minor: 2, patch: 3, beta: 5 }); // => '1.2.3-beta.5'
```
<a id="versioncompare"></a>
### version.compare
比較兩個版號物件的大小,回傳正數(a > b)、0(相等)或負數(a < b)。依 major → minor → patch → beta 的順序比較;同號碼時正式版大於 beta 版(`1.2.4` > `1.2.4-beta.3`),beta 版之間依號碼比較。用於在所有 git tag 中挑出最大(最新)的版號。
```javascript
const { parse, compare } = require('./version');
compare(parse('1.2.4'), parse('1.2.4-beta.3')); // => 1(正式版較大)
compare(parse('1.2.4-beta.5'), parse('1.2.4-beta.3')); // => 2beta 依號碼比較)
compare(parse('2.0.0'), parse('1.9.9')); // => 1
```
<a id="versionnext"></a>
### version.next
依最新版號與 `is_beta` 旗標計算下一版號。`latest``null` 時起算 `0.0.1`beta 為 `0.0.1-beta.1`);最新為 beta 版時,`isBeta=false` 去尾碼轉正式、`isBeta=true` 則 beta 號 +1(無上限);最新為正式版時 patch 進位(各位數滿 9 進位),`isBeta=true` 再加 `-beta.1`。最新正式版已達 `9.9.9` 需再進位時拋出 `Error`(呼叫端輸出 ERR 後以非零 exit code 結束)。
```javascript
const { parse, next, stringify } = require('./version');
stringify(next(parse('1.2.3'), false)); // => '1.2.4'
stringify(next(parse('1.2.3'), true)); // => '1.2.4-beta.1'
stringify(next(parse('1.2.4-beta.3'), false)); // => '1.2.4'(轉正式)
stringify(next(parse('1.2.9'), false)); // => '1.3.0'(滿 9 進位)
stringify(next(null, true)); // => '0.0.1-beta.1'
```