Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa4f7cd50b | ||
|
|
c8fe088e42 | ||
|
|
33d5aacee5 | ||
|
|
6ee9195f52 | ||
|
|
768ab84b00 | ||
|
|
c60b71e987 | ||
|
|
96cb99c136 | ||
|
|
24ed2ab164 | ||
|
|
1ed40a6b04 | ||
|
|
88e3e3d184 | ||
|
|
5883abd306 | ||
|
|
140b9c6fb1 |
@@ -0,0 +1 @@
|
|||||||
|
[]
|
||||||
@@ -1,66 +1,139 @@
|
|||||||
|
# --------------------------------------------------
|
||||||
|
# 用途:定義 CI 工作流程,處理 pull request 的版本發佈與測試。
|
||||||
|
# 更新日期:2026/07/11 21:08:44(Asia/Taipei)
|
||||||
|
# --------------------------------------------------
|
||||||
|
|
||||||
|
# 工作流程名稱。
|
||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
|
# 定義觸發條件。
|
||||||
on:
|
on:
|
||||||
|
# 只在 pull_request 事件上執行,避免其他事件重複觸發。
|
||||||
pull_request:
|
pull_request:
|
||||||
|
# 限定 PR 目標分支為 master 與 develop。
|
||||||
branches:
|
branches:
|
||||||
|
# 正式分支。
|
||||||
- master
|
- master
|
||||||
|
# 開發分支。
|
||||||
- develop
|
- develop
|
||||||
|
# 只在 PR 建立與同步更新時執行。
|
||||||
types: [opened, synchronize]
|
types: [opened, synchronize]
|
||||||
|
|
||||||
|
# 定義各個 job。
|
||||||
jobs:
|
jobs:
|
||||||
|
# build job 先建立 release,並計算基礎版本資訊。
|
||||||
build:
|
build:
|
||||||
|
# 顯示名稱。
|
||||||
name: 1. BUILD
|
name: 1. BUILD
|
||||||
|
# 使用 Ubuntu runner。
|
||||||
runs-on: ubuntu
|
runs-on: ubuntu
|
||||||
|
# 供此 job 與後續輸出共用的環境變數。
|
||||||
env:
|
env:
|
||||||
|
# 預設 beta 版版本字串,使用 run_number 保持唯一。
|
||||||
VERSION: "0.0.0-beta.${{ gitea.run_number }}"
|
VERSION: "0.0.0-beta.${{ gitea.run_number }}"
|
||||||
|
# 只要 PR 的 base branch 是 develop,就視為 beta 流程。
|
||||||
IS_BETA: ${{ gitea.base_ref == 'develop' }}
|
IS_BETA: ${{ gitea.base_ref == 'develop' }}
|
||||||
|
# 將環境變數輸出到下游 job。
|
||||||
outputs:
|
outputs:
|
||||||
|
# 提供 test job 使用的版本號。
|
||||||
version: ${{ env.VERSION }}
|
version: ${{ env.VERSION }}
|
||||||
|
# 提供 test 與 result job 使用的 beta 判斷結果。
|
||||||
is_beta: ${{ env.IS_BETA }}
|
is_beta: ${{ env.IS_BETA }}
|
||||||
|
# 定義 build job 的步驟。
|
||||||
steps:
|
steps:
|
||||||
|
# 在 Gitea 上建立 release,並讓 tag 與版本對齊。
|
||||||
- name: Publishing Release
|
- name: Publishing Release
|
||||||
|
# 使用外部 release action,版本由倉庫變數控制。
|
||||||
uses: akkuman/gitea-release-action@${{ vars.ACTION_GITEA_RELEASE_VERSION }}
|
uses: akkuman/gitea-release-action@${{ vars.ACTION_GITEA_RELEASE_VERSION }}
|
||||||
with:
|
with:
|
||||||
|
# release 名稱包含倉庫名稱與版本號。
|
||||||
name: "${{ gitea.event.repository.name }} v${{ env.VERSION }}"
|
name: "${{ gitea.event.repository.name }} v${{ env.VERSION }}"
|
||||||
|
# tag 名稱固定使用 v 前綴。
|
||||||
tag_name: "v${{ env.VERSION }}"
|
tag_name: "v${{ env.VERSION }}"
|
||||||
|
# 對應到目前提交。
|
||||||
target_commitish: ${{ gitea.sha }}
|
target_commitish: ${{ gitea.sha }}
|
||||||
|
# beta 分支建立 prerelease,正式分支則不是。
|
||||||
prerelease: ${{ env.IS_BETA }}
|
prerelease: ${{ env.IS_BETA }}
|
||||||
|
|
||||||
|
# test job 以 build 輸出為基礎執行版本計算與 beta 專屬檢查。
|
||||||
test:
|
test:
|
||||||
|
# 顯示名稱。
|
||||||
name: 2. TEST
|
name: 2. TEST
|
||||||
|
# 使用 Ubuntu runner。
|
||||||
runs-on: ubuntu
|
runs-on: ubuntu
|
||||||
|
# 必須等 build 完成,才能取得版本資訊。
|
||||||
needs: [build]
|
needs: [build]
|
||||||
|
# 將 build 的輸出轉成此 job 的環境變數。
|
||||||
env:
|
env:
|
||||||
|
# 取用 build job 輸出的版本。
|
||||||
VERSION: ${{ needs.build.outputs.version }}
|
VERSION: ${{ needs.build.outputs.version }}
|
||||||
|
# 取用 build job 輸出的 beta 狀態。
|
||||||
IS_BETA: ${{ needs.build.outputs.is_beta }}
|
IS_BETA: ${{ needs.build.outputs.is_beta }}
|
||||||
|
# 將 calculate-version 的結果往下輸出。
|
||||||
outputs:
|
outputs:
|
||||||
|
# 最終版本號由 calculate-version step 產生。
|
||||||
version: ${{ steps.calculate-version.outputs.version }}
|
version: ${{ steps.calculate-version.outputs.version }}
|
||||||
|
# 定義 test job 的步驟。
|
||||||
steps:
|
steps:
|
||||||
|
# 執行 calculate-version action 取得版本號。
|
||||||
- name: Run Calculate Version
|
- name: Run Calculate Version
|
||||||
|
# 用 commit 對應版本的動態 action 版本。
|
||||||
id: calculate-version
|
id: calculate-version
|
||||||
uses: https://gitea.jsc.idv.tw/actions/calculate-version@v${{ env.VERSION }}
|
uses: https://gitea.jsc.idv.tw/actions/calculate-version@v${{ env.VERSION }}
|
||||||
with:
|
with:
|
||||||
|
# 將 beta 狀態轉成布林值傳入 action。
|
||||||
is_beta: ${{ env.IS_BETA == "true" }}
|
is_beta: ${{ env.IS_BETA == "true" }}
|
||||||
|
# beta 流程才需要安裝 LLM CLI。
|
||||||
- name: Setup LLM CLI
|
- name: Setup LLM CLI
|
||||||
|
# 動態指定 setup action 版本。
|
||||||
uses: https://gitea.jsc.idv.tw/actions/setup-${{ vars.ACTION_SETUP_LLM_CLI }}
|
uses: https://gitea.jsc.idv.tw/actions/setup-${{ vars.ACTION_SETUP_LLM_CLI }}
|
||||||
|
# 只有 beta 分支才執行。
|
||||||
|
if: ${{ env.IS_BETA == 'true' }}
|
||||||
with:
|
with:
|
||||||
|
# 提供 OAuth 憑證給 CLI 安裝流程。
|
||||||
oauth: ${{ secrets.LLM_OAUTH }}
|
oauth: ${{ secrets.LLM_OAUTH }}
|
||||||
|
# beta 流程才執行 AI Code Review。
|
||||||
- name: Run AI Code Review
|
- name: Run AI Code Review
|
||||||
id: ai-code-review
|
# 用倉庫變數指定 action 版本。
|
||||||
uses: https://gitea.jsc.idv.tw/actions/ai-code-review@${{ vars.ACTION_AI_CODE_REVIEW_VERSION }}
|
uses: https://gitea.jsc.idv.tw/actions/ai-code-review@${{ vars.ACTION_AI_CODE_REVIEW_VERSION }}
|
||||||
|
# 步驟 id 供必要時引用輸出。
|
||||||
|
id: ai-code-review
|
||||||
|
# 只有 beta 分支才執行。
|
||||||
|
if: ${{ env.IS_BETA == 'true' }}
|
||||||
with:
|
with:
|
||||||
|
# 提供 token 給 AI review 流程。
|
||||||
token: ${{ secrets.TOKEN }}
|
token: ${{ secrets.TOKEN }}
|
||||||
|
# 指定模型名稱。
|
||||||
model: ${{ vars.LLM_NAME }}
|
model: ${{ vars.LLM_NAME }}
|
||||||
|
|
||||||
|
# result job 只在非 beta 流程時,根據 test 的結果再發佈一次 release。
|
||||||
result:
|
result:
|
||||||
|
# 顯示名稱。
|
||||||
name: 3. RESULT
|
name: 3. RESULT
|
||||||
|
# 使用 Ubuntu runner。
|
||||||
runs-on: ubuntu
|
runs-on: ubuntu
|
||||||
needs: [build,test]
|
# 必須等待 build 與 test 都完成。
|
||||||
|
needs: [build, test]
|
||||||
|
# 只有正式版才會進到這個 job。
|
||||||
if: ${{ needs.build.outputs.is_beta == 'false' }}
|
if: ${{ needs.build.outputs.is_beta == 'false' }}
|
||||||
|
# 重新帶入版本與 beta 狀態,供 release 步驟使用。
|
||||||
env:
|
env:
|
||||||
|
# 取用 test job 算出的版本號。
|
||||||
VERSION: ${{ needs.test.outputs.version }}
|
VERSION: ${{ needs.test.outputs.version }}
|
||||||
|
# 取用 build job 的 beta 狀態。
|
||||||
IS_BETA: ${{ needs.build.outputs.is_beta }}
|
IS_BETA: ${{ needs.build.outputs.is_beta }}
|
||||||
|
# 定義 result job 的步驟。
|
||||||
steps:
|
steps:
|
||||||
|
# 再次發佈 release,作為正式結果。
|
||||||
- name: Publishing Release
|
- name: Publishing Release
|
||||||
|
# 與 build job 使用相同的 release action 與版本來源。
|
||||||
uses: akkuman/gitea-release-action@${{ vars.ACTION_GITEA_RELEASE_VERSION }}
|
uses: akkuman/gitea-release-action@${{ vars.ACTION_GITEA_RELEASE_VERSION }}
|
||||||
with:
|
with:
|
||||||
|
# release 名稱包含倉庫名稱與最終版本號。
|
||||||
name: "${{ gitea.event.repository.name }} v${{ env.VERSION }}"
|
name: "${{ gitea.event.repository.name }} v${{ env.VERSION }}"
|
||||||
|
# 使用與 build 相同的 tag 命名方式。
|
||||||
tag_name: "v${{ env.VERSION }}"
|
tag_name: "v${{ env.VERSION }}"
|
||||||
|
# 指向目前提交。
|
||||||
target_commitish: ${{ gitea.sha }}
|
target_commitish: ${{ gitea.sha }}
|
||||||
|
# 這裡再次判斷是否為 beta,正式版時會是 false。
|
||||||
prerelease: ${{ env.IS_BETA == "true" }}
|
prerelease: ${{ env.IS_BETA == "true" }}
|
||||||
|
|||||||
@@ -1,21 +1,48 @@
|
|||||||
|
# --------------------------------------------------
|
||||||
|
# 用途:定義 CD 工作流程,於 master push 後找出對應 tag 並輸出結果。
|
||||||
|
# 更新日期:2026/07/11 21:08:44(Asia/Taipei)
|
||||||
|
# --------------------------------------------------
|
||||||
|
|
||||||
|
# 工作流程名稱。
|
||||||
name: CD
|
name: CD
|
||||||
|
|
||||||
|
# 定義觸發條件。
|
||||||
on:
|
on:
|
||||||
|
# 只在 push 事件上執行。
|
||||||
push:
|
push:
|
||||||
|
# 限定 master 分支,避免其他分支觸發部署流程。
|
||||||
branches:
|
branches:
|
||||||
|
# 正式分支。
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
# 定義部署工作。
|
||||||
jobs:
|
jobs:
|
||||||
|
# deploy job:檢出原始碼並找出 commit 對應的 tag。
|
||||||
deploy:
|
deploy:
|
||||||
|
# 顯示名稱。
|
||||||
name: DEPLOY
|
name: DEPLOY
|
||||||
|
# 使用 Ubuntu runner。
|
||||||
runs-on: ubuntu
|
runs-on: ubuntu
|
||||||
|
# 由 push 事件中的 commits 取出要查找的 commit SHA。
|
||||||
env:
|
env:
|
||||||
|
# 目前流程預設取第二筆 commit 的 id;此索引是否永遠存在需人工確認。
|
||||||
COMMIT_SHA: ${{ gitea.event.commits[1].id }}
|
COMMIT_SHA: ${{ gitea.event.commits[1].id }}
|
||||||
|
# 定義 deploy job 的步驟。
|
||||||
steps:
|
steps:
|
||||||
|
# 先檢出完整原始碼與 tag 歷史,讓後續可以查詢 tag。
|
||||||
- name: Source Code Checkout
|
- name: Source Code Checkout
|
||||||
|
# 使用 checkout action,版本由倉庫變數控制。
|
||||||
uses: actions/checkout@${{ vars.ACTION_CHECKOUT_VERSION }}
|
uses: actions/checkout@${{ vars.ACTION_CHECKOUT_VERSION }}
|
||||||
with:
|
with:
|
||||||
|
# 取得完整歷史,避免 tag 查詢因淺層 clone 而失敗。
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
# 根據 COMMIT_SHA 找出包含該提交的最新 tag。
|
||||||
- name: Get Commit Tag
|
- name: Get Commit Tag
|
||||||
|
# 將查到的 tag 寫入 Gitea output。
|
||||||
id: commit
|
id: commit
|
||||||
run: echo "tag=$(git for-each-ref --sort=-refname --format='%(refname:strip=2)' refs/tags --contains ${{ env.COMMIT_SHA }} | head -n 1)" >> $GITEA_OUTPUT
|
run: >-
|
||||||
|
echo "tag=$(git for-each-ref --sort=-refname --format='%(refname:strip=2)' refs/tags --contains ${{ env.COMMIT_SHA }} | head -n 1)" >> $GITEA_OUTPUT
|
||||||
|
# 將查到的 tag 輸出到日誌,方便人工確認。
|
||||||
- name: Show Tag
|
- name: Show Tag
|
||||||
run: echo "${{ steps.commit.outputs.tag }}"
|
run: >-
|
||||||
|
echo "[DEPLOY][INF][$(TZ='Asia/Taipei' date +'%Y/%m/%d %H:%M:%S')]: ${{ steps.commit.outputs.tag }}"
|
||||||
|
|||||||
@@ -1,9 +1,41 @@
|
|||||||
# GITEA COMPOSITE ACTION 的工作流列表
|
# 工作流程說明
|
||||||
|
|
||||||
- CI
|
以下內容整理 `.gitea/workflows/` 目前的工作流程與用途,作為專案內工作流程的說明文件。
|
||||||
- BUILD
|
|
||||||
- TEST
|
## 總覽
|
||||||
- RESULT
|
|
||||||
- CD
|
| Workflow 名稱 | 檔案位置 | 觸發條件 | 主要用途 | 相關參數 |
|
||||||
- BUILD
|
| ------------- | ------------------------------ | --------------------------------------------------------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
- DEPLOY
|
| CI | `.gitea/workflows/ci.yaml` | `pull_request` 到 `master` 與 `develop`,事件型別為 `opened`、`synchronize` | 在 PR 階段建立 release、計算版本,beta 分支還會執行 AI code review | `VERSION`、`IS_BETA`、`vars.ACTION_GITEA_RELEASE_VERSION`、`vars.ACTION_SETUP_LLM_CLI`、`vars.ACTION_AI_CODE_REVIEW_VERSION`、`secrets.LLM_OAUTH`、`secrets.TOKEN`、`vars.LLM_NAME` |
|
||||||
|
| CD | `.gitea/workflows/master.yaml` | `push` 到 `master` | 根據 commit 找出對應 tag,供部署流程或後續檢查使用 | `COMMIT_SHA`、`vars.ACTION_CHECKOUT_VERSION` |
|
||||||
|
|
||||||
|
## CI
|
||||||
|
|
||||||
|
- 檔案位置:`.gitea/workflows/ci.yaml`
|
||||||
|
- 觸發條件:`pull_request` 到 `master` 與 `develop`,事件型別包含 `opened` 與 `synchronize`
|
||||||
|
- 用途說明:先發佈 release 草稿,再呼叫 `calculate-version` action 計算版本;若是 beta 分支,還會設定 LLM CLI 並執行 AI code review。
|
||||||
|
- 主要輸入 / 環境參數:
|
||||||
|
- `VERSION`:預設為 `0.0.0-beta.${{ gitea.run_number }}`,供後續 job 使用。
|
||||||
|
- `IS_BETA`:由 `gitea.base_ref == 'develop'` 推得,控制 beta 與正式版流程。
|
||||||
|
- `vars.ACTION_GITEA_RELEASE_VERSION`:`gitea-release-action` 版本。
|
||||||
|
- `vars.ACTION_SETUP_LLM_CLI`:LLM CLI 安裝 action 版本。
|
||||||
|
- `vars.ACTION_AI_CODE_REVIEW_VERSION`:AI code review action 版本。
|
||||||
|
- `secrets.LLM_OAUTH`、`secrets.TOKEN`:beta 流程所需憑證。
|
||||||
|
- `vars.LLM_NAME`:AI code review 使用的模型名稱。
|
||||||
|
- 重要注意事項:
|
||||||
|
- `result` job 只在 `IS_BETA == 'false'` 時執行。
|
||||||
|
- `test` job 的 action 來源是 `https://gitea.jsc.idv.tw/actions/calculate-version@v${{ env.VERSION }}`,版本號需與 release 流程對齊。
|
||||||
|
- 若 `develop` 與 `master` 的 release 節奏不同,需確認 `VERSION` 的預設生成邏輯是否符合預期。
|
||||||
|
|
||||||
|
## CD
|
||||||
|
|
||||||
|
- 檔案位置:`.gitea/workflows/master.yaml`
|
||||||
|
- 觸發條件:`push` 到 `master`
|
||||||
|
- 用途說明:檢出原始碼後,根據提交 SHA 找出對應 tag,並輸出查得的結果。
|
||||||
|
- 主要輸入 / 環境參數:
|
||||||
|
- `COMMIT_SHA`:目前流程中使用 `gitea.event.commits[1].id`,需確認該索引在所有 push 事件下都存在。
|
||||||
|
- `vars.ACTION_CHECKOUT_VERSION`:`actions/checkout` 版本。
|
||||||
|
- 重要注意事項:
|
||||||
|
- `fetch-depth: 0` 是必要條件,否則 `git for-each-ref --contains` 可能找不到完整 tag。
|
||||||
|
- `Get Commit Tag` 的 `run` 指令假設 tag 存在;若找不到,輸出會是空字串,需人工確認下游是否能接受。
|
||||||
|
- `Show Tag` 目前採用統一輸出格式草稿,正式實作時仍需確認 shell 內的時間取得方式。
|
||||||
|
|||||||
+12
@@ -1,10 +1,22 @@
|
|||||||
|
# --------------------------------------------------
|
||||||
|
# 用途:定義 calculate-version action 的 Docker 執行環境與啟動入口。
|
||||||
|
# 更新日期:2026/07/11 21:08:44(Asia/Taipei)
|
||||||
|
# --------------------------------------------------
|
||||||
|
|
||||||
|
# 使用 Node LTS Alpine 映像,兼顧 Node 執行環境與較小的映像體積。
|
||||||
FROM node:lts-alpine
|
FROM node:lts-alpine
|
||||||
|
|
||||||
|
# 將工作目錄切換到 /action,後續複製與執行都以此為基準。
|
||||||
WORKDIR /action
|
WORKDIR /action
|
||||||
|
|
||||||
|
# 複製 action 的主程式來源到容器內,供 entrypoint 執行。
|
||||||
COPY src/ /action/src/
|
COPY src/ /action/src/
|
||||||
|
|
||||||
|
# 複製 entrypoint 腳本到容器內,作為啟動入口。
|
||||||
COPY entrypoint.sh /action/entrypoint.sh
|
COPY entrypoint.sh /action/entrypoint.sh
|
||||||
|
|
||||||
|
# 賦予 entrypoint 可執行權限,否則容器啟動時無法直接執行。
|
||||||
RUN chmod +x /action/entrypoint.sh
|
RUN chmod +x /action/entrypoint.sh
|
||||||
|
|
||||||
|
# 指定容器啟動時直接執行 entrypoint 腳本。
|
||||||
ENTRYPOINT ["/action/entrypoint.sh"]
|
ENTRYPOINT ["/action/entrypoint.sh"]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# calculate-version
|
# calculate-version
|
||||||
|
|
||||||
更新時間:2026/07/11 14:03:52(Asia/Taipei)
|
更新時間:2026/07/11 21:08:44(Asia/Taipei)
|
||||||
|
|
||||||
這個專案是一個 Gitea Docker action,會讀取 repository 的 release 清單,計算下一個正式版或 beta 版本號,並將結果輸出成 action output。
|
這個專案是一個以 Node.js 實作的 Gitea Docker action,負責從 release 清單計算下一個正式版或 beta 版本,並把結果輸出給後續工作流程使用。
|
||||||
|
|
||||||
## 專案列表
|
## 專案列表
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
| 專案名稱 | 專案描述 |
|
| 專案名稱 | 專案描述 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| [calculate-version](https://gitea.jsc.idv.tw/actions/calculate-version/src/branch/develop/) | 這是一個用來計算 Gitea release 下一版版本號的 Node.js action,支援正式版與 beta 版推算。 |
|
| [calculate-version](https://gitea.jsc.idv.tw/actions/calculate-version/src/branch/develop/) | 這是一個以 Node.js 實作的 Gitea Docker action,負責取得 release 資料、計算下一個版本號,並輸出給 workflow 或 action 使用。 |
|
||||||
|
|
||||||
### 參考專案表
|
### 參考專案表
|
||||||
|
|
||||||
@@ -30,8 +30,122 @@
|
|||||||
|
|
||||||
| 功能名稱 | 功能描述 |
|
| 功能名稱 | 功能描述 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 無 | 此專案未公開可列入 README 的功能。 |
|
| [calculate-version.normalizeBetaFlag](https://gitea.jsc.idv.tw/actions/calculate-version/src/branch/develop/src/index.js#L95) | [將 beta 輸入正規化成字串 `false`](#calculateversionnormalizebetaflag) |
|
||||||
|
| [calculate-version.parseVersionParts](https://gitea.jsc.idv.tw/actions/calculate-version/src/branch/develop/src/index.js#L130) | [將版本字串拆成可比較的數字片段](#calculateversionparseversionparts) |
|
||||||
|
| [calculate-version.compareVersionParts](https://gitea.jsc.idv.tw/actions/calculate-version/src/branch/develop/src/index.js#L148) | [比較兩組版本片段的大小](#calculateversioncompareversionparts) |
|
||||||
|
| [calculate-version.stableVersionFromTag](https://gitea.jsc.idv.tw/actions/calculate-version/src/branch/develop/src/index.js#L171) | [從 tag 解析穩定版版本片段](#calculateversionstableversionfromtag) |
|
||||||
|
| [calculate-version.latestStableVersion](https://gitea.jsc.idv.tw/actions/calculate-version/src/branch/develop/src/index.js#L192) | [找出 release 清單中的最新穩定版](#calculateversionlateststableversion) |
|
||||||
|
| [calculate-version.nextReleaseVersion](https://gitea.jsc.idv.tw/actions/calculate-version/src/branch/develop/src/index.js#L218) | [推算下一個正式版版本號](#calculateversionnextreleaseversion) |
|
||||||
|
| [calculate-version.nextBetaNumber](https://gitea.jsc.idv.tw/actions/calculate-version/src/branch/develop/src/index.js#L247) | [推算下一個 beta 編號](#calculateversionnextbetanumber) |
|
||||||
|
| [calculate-version.calculateVersion](https://gitea.jsc.idv.tw/actions/calculate-version/src/branch/develop/src/index.js#L275) | [依 release 資料與 beta 旗標計算目前版本與下一版](#calculateversioncalculateversion) |
|
||||||
|
| [calculate-version.fetchReleases](https://gitea.jsc.idv.tw/actions/calculate-version/src/branch/develop/src/index.js#L357) | [分頁抓取 repository 的 release 清單](#calculateversionfetchreleases) |
|
||||||
|
| [calculate-version.main](https://gitea.jsc.idv.tw/actions/calculate-version/src/branch/develop/src/index.js#L396) | [執行 action 主流程並輸出版本結果](#calculateversionmain) |
|
||||||
|
|
||||||
## 使用範例
|
## 使用範例
|
||||||
|
|
||||||
此專案目前沒有可對外列入 README 的公開方法,因此沒有對應的使用範例。
|
### <a id="calculateversionnormalizebetaflag"></a>calculate-version.normalizeBetaFlag
|
||||||
|
將 action 輸入或環境變數轉成固定的字串旗標,避免後續流程混用空值與字串。
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { normalizeBetaFlag } = require('./src/index.js');
|
||||||
|
|
||||||
|
const isBeta = normalizeBetaFlag(process.env.IS_BETA);
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="calculateversionparseversionparts"></a>calculate-version.parseVersionParts
|
||||||
|
將版本字串拆成數字陣列,適合後續比較或進位運算。
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { parseVersionParts } = require('./src/index.js');
|
||||||
|
|
||||||
|
const parts = parseVersionParts('1.2.3');
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="calculateversioncompareversionparts"></a>calculate-version.compareVersionParts
|
||||||
|
比較兩組版本片段,常用於排序 release 版本。
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { compareVersionParts } = require('./src/index.js');
|
||||||
|
|
||||||
|
const sorted = [[1, 2, 10], [1, 2, 3]].sort(compareVersionParts);
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="calculateversionstableversionfromtag"></a>calculate-version.stableVersionFromTag
|
||||||
|
從 tag 名稱過濾出穩定版版本,忽略 beta 與不合法格式。
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { stableVersionFromTag } = require('./src/index.js');
|
||||||
|
|
||||||
|
const parts = stableVersionFromTag('v1.2.3');
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="calculateversionlateststableversion"></a>calculate-version.latestStableVersion
|
||||||
|
從 release 清單中找出最新穩定版,若沒有可用資料就回傳 `0.0.0`。
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { latestStableVersion } = require('./src/index.js');
|
||||||
|
|
||||||
|
const latest = latestStableVersion([
|
||||||
|
{ tag_name: 'v1.2.2' },
|
||||||
|
{ tag_name: 'v1.2.3-beta.1' },
|
||||||
|
{ tag_name: 'v1.2.3' },
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="calculateversionnextreleaseversion"></a>calculate-version.nextReleaseVersion
|
||||||
|
將正式版版本號往下一版遞增,patch 會以 10 為進位界線。
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { nextReleaseVersion } = require('./src/index.js');
|
||||||
|
|
||||||
|
const nextVersion = nextReleaseVersion('1.2.9');
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="calculateversionnextbetanumber"></a>calculate-version.nextBetaNumber
|
||||||
|
推算下一個 beta 編號,會找出目前版本對應的最大 `beta.N` 再加一。
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { nextBetaNumber } = require('./src/index.js');
|
||||||
|
|
||||||
|
const betaNumber = nextBetaNumber([
|
||||||
|
{ tag_name: 'v1.2.4-beta.1' },
|
||||||
|
{ tag_name: 'v1.2.4-beta.3' },
|
||||||
|
], '1.2.4');
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="calculateversioncalculateversion"></a>calculate-version.calculateVersion
|
||||||
|
依 release 資料與 beta 狀態回傳 `[latestVersion, nextVersion]`。
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { calculateVersion } = require('./src/index.js');
|
||||||
|
|
||||||
|
const [latest, nextVersion] = calculateVersion([
|
||||||
|
{ tag_name: 'v1.2.3' },
|
||||||
|
{ tag_name: 'v1.2.4-beta.1' },
|
||||||
|
], 'false');
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="calculateversionfetchreleases"></a>calculate-version.fetchReleases
|
||||||
|
分頁抓取 repository 的 release 清單,直到 API 沒有新資料為止。
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { fetchReleases } = require('./src/index.js');
|
||||||
|
|
||||||
|
// 需人工確認:baseUrl 與 repository 必須對應實際 Gitea 環境。
|
||||||
|
(async () => {
|
||||||
|
const releases = await fetchReleases('https://gitea.example.com', 'owner/repo', 'token-value');
|
||||||
|
console.log(releases);
|
||||||
|
})();
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="calculateversionmain"></a>calculate-version.main
|
||||||
|
執行 action 主流程,通常由 Gitea action runtime 觸發。
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { main } = require('./src/index.js');
|
||||||
|
|
||||||
|
// 需人工確認:這個入口通常應由 Gitea action 啟動,且需要完整環境變數。
|
||||||
|
(async () => {
|
||||||
|
await main();
|
||||||
|
})();
|
||||||
|
```
|
||||||
|
|||||||
+41
-9
@@ -1,22 +1,54 @@
|
|||||||
name: 'Calculate Version'
|
# --------------------------------------------------
|
||||||
description: '計算版本號'
|
# 用途:宣告 Calculate Version action 的輸入、輸出與 Docker 執行方式。
|
||||||
author: 'Jeffery'
|
# 更新日期:2026/07/11 21:08:44(Asia/Taipei)
|
||||||
|
# --------------------------------------------------
|
||||||
|
|
||||||
|
# action 的顯示名稱。
|
||||||
|
name: "Calculate Version"
|
||||||
|
|
||||||
|
# action 的簡短描述。
|
||||||
|
description: "計算版本號"
|
||||||
|
|
||||||
|
# action 的作者資訊。
|
||||||
|
author: "Jeffery"
|
||||||
|
|
||||||
|
# 宣告可由呼叫端傳入的輸入參數。
|
||||||
inputs:
|
inputs:
|
||||||
|
# 是否以 beta 模式計算版本,預設關閉。
|
||||||
is_beta:
|
is_beta:
|
||||||
description: '是否為 beta 版本'
|
# 參數說明文字。
|
||||||
default: 'false'
|
description: "是否為 beta 版本"
|
||||||
|
# 未提供時預設為 false,讓一般流程走正式版邏輯。
|
||||||
|
default: "false"
|
||||||
|
# 用於讀取 release 資訊的 token,保留為可選輸入。
|
||||||
runner_token:
|
runner_token:
|
||||||
description: '用於讀取 release 的 token'
|
# 參數說明文字。
|
||||||
|
description: "用於讀取 release 的 token"
|
||||||
|
# 明確標示不是必填,呼叫端可依環境提供。
|
||||||
required: false
|
required: false
|
||||||
|
|
||||||
|
# 宣告 action 會輸出的結果欄位。
|
||||||
outputs:
|
outputs:
|
||||||
|
# 將計算後的版本號輸出給後續工作流程使用。
|
||||||
version:
|
version:
|
||||||
description: '計算出的版本號'
|
# 輸出說明文字。
|
||||||
|
description: "計算出的版本號"
|
||||||
|
|
||||||
|
# 指定此 action 以 Docker 模式執行。
|
||||||
runs:
|
runs:
|
||||||
using: 'docker'
|
# 透過 Docker image 啟動。
|
||||||
image: 'Dockerfile'
|
using: "docker"
|
||||||
|
# 使用同目錄下的 Dockerfile 建置映像。
|
||||||
|
image: "Dockerfile"
|
||||||
|
# 將 Gitea 與呼叫端輸入注入容器環境,供 entrypoint 與 Node 程式讀取。
|
||||||
env:
|
env:
|
||||||
|
# Gitea 伺服器 URL,供程式組出 API 或資源路徑。
|
||||||
GITEA_SERVER_URL: ${{ gitea.server_url }}
|
GITEA_SERVER_URL: ${{ gitea.server_url }}
|
||||||
|
# 目前倉庫識別資訊。
|
||||||
GITEA_REPOSITORY: ${{ gitea.repository }}
|
GITEA_REPOSITORY: ${{ gitea.repository }}
|
||||||
|
# Gitea token,供程式讀取受保護資源。
|
||||||
GITEA_TOKEN: ${{ gitea.token }}
|
GITEA_TOKEN: ${{ gitea.token }}
|
||||||
|
# runner_token 的優先來源是輸入值,其次是 secrets.GITEA_TOKEN,再其次是 secrets.RUNNER_TOKEN。
|
||||||
RUNNER_TOKEN: ${{ inputs.runner_token || secrets.GITEA_TOKEN || secrets.RUNNER_TOKEN }}
|
RUNNER_TOKEN: ${{ inputs.runner_token || secrets.GITEA_TOKEN || secrets.RUNNER_TOKEN }}
|
||||||
|
# 將呼叫端的 beta 設定直接傳入容器。
|
||||||
IS_BETA: ${{ inputs.is_beta }}
|
IS_BETA: ${{ inputs.is_beta }}
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
# --------------------------------------------------
|
||||||
|
# 用途:啟動 calculate-version action,並將所有參數直接轉交給 Node 主程式。
|
||||||
|
# 更新日期:2026/07/11 21:08:44(Asia/Taipei)
|
||||||
|
# --------------------------------------------------
|
||||||
|
|
||||||
|
# 啟用嚴格模式,讓未定義變數與任一命令失敗都能立即中止流程。
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
|
# 直接以 exec 取代 shell 行程,避免多一層 shell 包裝,並把所有參數原封不動傳給 Node。
|
||||||
exec node /action/src/index.js "$@"
|
exec node /action/src/index.js "$@"
|
||||||
|
|||||||
+159
-6
@@ -6,23 +6,76 @@ const { URL } = require('url');
|
|||||||
const RELEASES_PER_PAGE = 10;
|
const RELEASES_PER_PAGE = 10;
|
||||||
let currentStage = null;
|
let currentStage = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 設定目前訊息輸出的階段名稱。
|
||||||
|
*
|
||||||
|
* @param {string} title 階段名稱,通常是流程區塊名稱。
|
||||||
|
* @remarks
|
||||||
|
* 供 `info()` 與錯誤輸出使用,讓訊息可以帶上統一前綴。
|
||||||
|
*/
|
||||||
function section(title) {
|
function section(title) {
|
||||||
currentStage = title;
|
currentStage = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
function info(message) {
|
/**
|
||||||
const timestamp = new Date()
|
* 產生統一格式的時間戳記字串。
|
||||||
|
*
|
||||||
|
* @returns {string} Asia/Taipei 時區格式化後的時間戳記。
|
||||||
|
* @remarks
|
||||||
|
* 由 `info()` 與錯誤輸出共用,避免不同輸出路徑各自拼出不同格式。
|
||||||
|
*/
|
||||||
|
function formatTimestamp() {
|
||||||
|
return new Date()
|
||||||
.toLocaleString('sv-SE', { timeZone: 'Asia/Taipei', hour12: false })
|
.toLocaleString('sv-SE', { timeZone: 'Asia/Taipei', hour12: false })
|
||||||
.replace(/-/g, '/');
|
.replace(/-/g, '/');
|
||||||
const stagePrefix = currentStage ? `[${currentStage}]` : '';
|
|
||||||
|
|
||||||
process.stdout.write(`${stagePrefix}[INF][${timestamp}]: ${message}\n`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 以統一格式組裝單行 log。
|
||||||
|
*
|
||||||
|
* @param {string} level 訊息等級。
|
||||||
|
* @param {string} message 要輸出的訊息內容。
|
||||||
|
* @returns {string} 已格式化完成且含換行的 log 字串。
|
||||||
|
* @remarks
|
||||||
|
* 讓一般資訊與錯誤訊息共用同一套前綴格式,降低未來調整格式時的維護成本。
|
||||||
|
*/
|
||||||
|
function formatLogLine(level, message) {
|
||||||
|
const stagePrefix = currentStage ? `[${currentStage}]` : '';
|
||||||
|
|
||||||
|
return `${stagePrefix}[${level}][${formatTimestamp()}]: ${message}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 以統一格式輸出資訊訊息。
|
||||||
|
*
|
||||||
|
* @param {string} message 要輸出的訊息內容。
|
||||||
|
* @remarks
|
||||||
|
* 會附加目前階段與 Asia/Taipei 時區時間戳記,適合用於流程進度與狀態輸出。
|
||||||
|
*/
|
||||||
|
function info(message) {
|
||||||
|
process.stdout.write(formatLogLine('INF', message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 以例外方式終止流程。
|
||||||
|
*
|
||||||
|
* @param {string} message 錯誤訊息。
|
||||||
|
* @remarks
|
||||||
|
* 當輸入參數缺失或流程無法繼續時使用,呼叫後會直接拋出 `Error`。
|
||||||
|
*/
|
||||||
function fail(message) {
|
function fail(message) {
|
||||||
throw new Error(message);
|
throw new Error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 驗證必要環境變數是否有值。
|
||||||
|
*
|
||||||
|
* @param {string} name 環境變數名稱,用於錯誤訊息。
|
||||||
|
* @param {string} value 環境變數值。
|
||||||
|
* @returns {string} 驗證通過後的原始值。
|
||||||
|
* @remarks
|
||||||
|
* 適合用在 action 啟動時檢查 GITEA 相關必要設定。若值缺失,會直接拋出例外。
|
||||||
|
*/
|
||||||
function requireEnv(name, value) {
|
function requireEnv(name, value) {
|
||||||
if (!value || value === 'null') {
|
if (!value || value === 'null') {
|
||||||
fail(`${name} 未設定`);
|
fail(`${name} 未設定`);
|
||||||
@@ -31,6 +84,14 @@ function requireEnv(name, value) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 將 beta 旗標正規化成字串。
|
||||||
|
*
|
||||||
|
* @param {string} [value='false'] 原始 beta 旗標。
|
||||||
|
* @returns {string} 正規化後的字串,空值會變成 `false`。
|
||||||
|
* @remarks
|
||||||
|
* 用於 action 入口參數,避免 `undefined`、空字串或字串 `null` 進入後續判斷。
|
||||||
|
*/
|
||||||
function normalizeBetaFlag(value = 'false') {
|
function normalizeBetaFlag(value = 'false') {
|
||||||
if (!value || value === 'null') {
|
if (!value || value === 'null') {
|
||||||
return 'false';
|
return 'false';
|
||||||
@@ -39,6 +100,13 @@ function normalizeBetaFlag(value = 'false') {
|
|||||||
return String(value);
|
return String(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 將計算結果寫入 action output。
|
||||||
|
*
|
||||||
|
* @param {string} version 要輸出的版本號。
|
||||||
|
* @remarks
|
||||||
|
* 若執行環境提供 `GITHUB_OUTPUT`,會寫入檔案;否則退回標準輸出,方便本機除錯。
|
||||||
|
*/
|
||||||
function writeOutput(version) {
|
function writeOutput(version) {
|
||||||
const line = `version=${version}\n`;
|
const line = `version=${version}\n`;
|
||||||
const outputPath = process.env.GITHUB_OUTPUT;
|
const outputPath = process.env.GITHUB_OUTPUT;
|
||||||
@@ -51,6 +119,14 @@ function writeOutput(version) {
|
|||||||
process.stdout.write(line);
|
process.stdout.write(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 將版本字串拆成數字陣列。
|
||||||
|
*
|
||||||
|
* @param {string|number} version 版本字串。
|
||||||
|
* @returns {number[]} 由 major、minor、patch 等片段組成的數字陣列。
|
||||||
|
* @remarks
|
||||||
|
* 非數字片段會被轉成 `0`,適合用於後續比較與遞增計算。
|
||||||
|
*/
|
||||||
function parseVersionParts(version) {
|
function parseVersionParts(version) {
|
||||||
return String(version)
|
return String(version)
|
||||||
.split('.')
|
.split('.')
|
||||||
@@ -60,6 +136,15 @@ function parseVersionParts(version) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比較兩組版本片段的大小。
|
||||||
|
*
|
||||||
|
* @param {number[]} left 左側版本片段。
|
||||||
|
* @param {number[]} right 右側版本片段。
|
||||||
|
* @returns {number} 左小於右回傳負值,左大於右回傳正值,相等回傳 0。
|
||||||
|
* @remarks
|
||||||
|
* 可直接搭配 `Array.prototype.sort()` 使用,用來找出最新穩定版本。
|
||||||
|
*/
|
||||||
function compareVersionParts(left, right) {
|
function compareVersionParts(left, right) {
|
||||||
const maxLength = Math.max(left.length, right.length);
|
const maxLength = Math.max(left.length, right.length);
|
||||||
|
|
||||||
@@ -75,6 +160,14 @@ function compareVersionParts(left, right) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 從 release tag 解析穩定版版本資訊。
|
||||||
|
*
|
||||||
|
* @param {string} tagName release tag 名稱。
|
||||||
|
* @returns {number[]|null} 解析成功時回傳版本片段,否則回傳 `null`。
|
||||||
|
* @remarks
|
||||||
|
* 只接受純數字與點號組成的穩定版標籤,例如 `v1.2.3` 或 `1.2.3`。
|
||||||
|
*/
|
||||||
function stableVersionFromTag(tagName) {
|
function stableVersionFromTag(tagName) {
|
||||||
if (typeof tagName !== 'string' || tagName.includes('-beta.')) {
|
if (typeof tagName !== 'string' || tagName.includes('-beta.')) {
|
||||||
return null;
|
return null;
|
||||||
@@ -88,6 +181,14 @@ function stableVersionFromTag(tagName) {
|
|||||||
return parseVersionParts(versionText);
|
return parseVersionParts(versionText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取得最新的穩定版版本號。
|
||||||
|
*
|
||||||
|
* @param {Array<object>} releaseJson release API 回傳資料。
|
||||||
|
* @returns {string} 最新穩定版版本號;找不到時回傳 `0.0.0`。
|
||||||
|
* @remarks
|
||||||
|
* 主要用於計算下一版版本號的基礎值,會忽略 beta 標籤與不合法版本字串。
|
||||||
|
*/
|
||||||
function latestStableVersion(releaseJson) {
|
function latestStableVersion(releaseJson) {
|
||||||
if (!Array.isArray(releaseJson) || releaseJson.length === 0) {
|
if (!Array.isArray(releaseJson) || releaseJson.length === 0) {
|
||||||
return '0.0.0';
|
return '0.0.0';
|
||||||
@@ -106,6 +207,14 @@ function latestStableVersion(releaseJson) {
|
|||||||
return `${latest[0] ?? 0}.${latest[1] ?? 0}.${latest[2] ?? 0}`;
|
return `${latest[0] ?? 0}.${latest[1] ?? 0}.${latest[2] ?? 0}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 計算下一個正式版版本號。
|
||||||
|
*
|
||||||
|
* @param {string} latestVersion 目前最新的正式版版本號。
|
||||||
|
* @returns {string} 下一個正式版版本號。
|
||||||
|
* @remarks
|
||||||
|
* 進位規則以 10 為界,適合與 `latestStableVersion()` 搭配使用。
|
||||||
|
*/
|
||||||
function nextReleaseVersion(latestVersion) {
|
function nextReleaseVersion(latestVersion) {
|
||||||
const [majorRaw, minorRaw, patchRaw] = parseVersionParts(latestVersion);
|
const [majorRaw, minorRaw, patchRaw] = parseVersionParts(latestVersion);
|
||||||
let major = majorRaw ?? 0;
|
let major = majorRaw ?? 0;
|
||||||
@@ -126,6 +235,15 @@ function nextReleaseVersion(latestVersion) {
|
|||||||
return `${major}.${minor}.${patch}`;
|
return `${major}.${minor}.${patch}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 計算下一個 beta 編號。
|
||||||
|
*
|
||||||
|
* @param {Array<object>} releaseJson release API 回傳資料。
|
||||||
|
* @param {string} version 目標正式版版本號。
|
||||||
|
* @returns {number} 下一個 beta 編號,最小為 1。
|
||||||
|
* @remarks
|
||||||
|
* 用於 beta 發版流程,會忽略不符合命名格式或無法解析成整數的 tag。
|
||||||
|
*/
|
||||||
function nextBetaNumber(releaseJson, version) {
|
function nextBetaNumber(releaseJson, version) {
|
||||||
if (!Array.isArray(releaseJson) || releaseJson.length === 0) {
|
if (!Array.isArray(releaseJson) || releaseJson.length === 0) {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -145,6 +263,15 @@ function nextBetaNumber(releaseJson, version) {
|
|||||||
return Math.max(...values) + 1;
|
return Math.max(...values) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 計算目前最新版本與下一個版本。
|
||||||
|
*
|
||||||
|
* @param {Array<object>} releaseJson release API 回傳資料。
|
||||||
|
* @param {string} isBeta 是否計算 beta 版本,`true` 代表 beta。
|
||||||
|
* @returns {string[]} 回傳 `[latestVersion, nextVersion]`。
|
||||||
|
* @remarks
|
||||||
|
* 這是 action 的核心邏輯,通常由 `main()` 取得 release 後再呼叫。
|
||||||
|
*/
|
||||||
function calculateVersion(releaseJson, isBeta) {
|
function calculateVersion(releaseJson, isBeta) {
|
||||||
if (!Array.isArray(releaseJson) || releaseJson.length === 0) {
|
if (!Array.isArray(releaseJson) || releaseJson.length === 0) {
|
||||||
return isBeta === 'true'
|
return isBeta === 'true'
|
||||||
@@ -163,6 +290,15 @@ function calculateVersion(releaseJson, isBeta) {
|
|||||||
return [baseVersion, nextVersion];
|
return [baseVersion, nextVersion];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 以 HTTP/HTTPS 取得 JSON 回應。
|
||||||
|
*
|
||||||
|
* @param {URL} url 請求目標。
|
||||||
|
* @param {string} token 驗證 token;空值或字串 `null` 會被忽略。
|
||||||
|
* @returns {Promise<unknown>} 成功時解析為 JSON 物件或空字串。
|
||||||
|
* @remarks
|
||||||
|
* 失敗時會拋出錯誤,適合拿來包裝 release API 的低階請求。
|
||||||
|
*/
|
||||||
function requestJson(url, token) {
|
function requestJson(url, token) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const client = url.protocol === 'http:' ? http : https;
|
const client = url.protocol === 'http:' ? http : https;
|
||||||
@@ -208,6 +344,16 @@ function requestJson(url, token) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 逐頁抓取 repository 的 release 清單。
|
||||||
|
*
|
||||||
|
* @param {string|URL} baseUrl Gitea API 基底網址。
|
||||||
|
* @param {string} repository repository 路徑。
|
||||||
|
* @param {string} token API 存取 token。
|
||||||
|
* @returns {Promise<Array<object>>} 合併後的 release 清單。
|
||||||
|
* @remarks
|
||||||
|
* 會依 `RELEASES_PER_PAGE` 分頁,當 API 回傳空資料或最後一頁不足數量時停止。
|
||||||
|
*/
|
||||||
async function fetchReleases(baseUrl, repository, token) {
|
async function fetchReleases(baseUrl, repository, token) {
|
||||||
const combined = [];
|
const combined = [];
|
||||||
let page = 1;
|
let page = 1;
|
||||||
@@ -240,6 +386,13 @@ async function fetchReleases(baseUrl, repository, token) {
|
|||||||
return combined;
|
return combined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 執行 calculate-version action 的主流程。
|
||||||
|
*
|
||||||
|
* @returns {Promise<void>} 完成時不回傳值,失敗時會拋出例外。
|
||||||
|
* @remarks
|
||||||
|
* 需要在 Gitea action 環境中執行,並依賴 `GITEA_SERVER_URL`、`GITEA_REPOSITORY` 與 token 相關環境變數。
|
||||||
|
*/
|
||||||
async function main() {
|
async function main() {
|
||||||
section('參數檢查');
|
section('參數檢查');
|
||||||
|
|
||||||
@@ -268,7 +421,7 @@ async function main() {
|
|||||||
|
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
main().catch((error) => {
|
main().catch((error) => {
|
||||||
process.stderr.write(`[error] ${error.message}\n`);
|
process.stderr.write(formatLogLine('ERR', error.message));
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
const assert = require('node:assert/strict');
|
||||||
|
const { spawnSync } = require('node:child_process');
|
||||||
|
const path = require('node:path');
|
||||||
|
const test = require('node:test');
|
||||||
|
|
||||||
|
test('主流程失敗時會輸出階段前綴與錯誤碼', () => {
|
||||||
|
const result = spawnSync(
|
||||||
|
process.execPath,
|
||||||
|
[path.join(__dirname, 'index.js')],
|
||||||
|
{
|
||||||
|
cwd: path.join(__dirname, '..'),
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
GITEA_SERVER_URL: '',
|
||||||
|
GITEA_REPOSITORY: 'owner/repo',
|
||||||
|
RUNNER_TOKEN: 'token',
|
||||||
|
IS_BETA: 'false',
|
||||||
|
},
|
||||||
|
encoding: 'utf8',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(result.status, 1);
|
||||||
|
assert.match(result.stderr, /^\[參數檢查\]\[ERR\]\[\d{4}\/\d{2}\/\d{2} /);
|
||||||
|
assert.match(result.stderr, /GITEA_SERVER_URL 未設定/);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user