diff --git a/.gitea/ai-review/findings.json b/.gitea/ai-review/findings.json new file mode 100644 index 0000000..7fad757 --- /dev/null +++ b/.gitea/ai-review/findings.json @@ -0,0 +1,41 @@ +[ + { + "level": "warning", + "role": "Bard", + "location": "action.yml:1", + "problem": "檔案頭部充斥著過度冗長、瑣碎且描述基礎 YAML 語法的註解,破壞了設定檔應有的簡潔層次,且增加了維護負擔。", + "suggestion": "建議大幅精簡檔案頭部註解,僅保留必要的業務邏輯摘要,移除過細的步驟解說與基礎語法定義。" + }, + { + "level": "warning", + "role": "Leo", + "location": "action.yml:25", + "problem": "參數 `files` 的 `description` 為空,使得呼叫方在查閱使用說明時缺乏必要的上下文,未來維護者也難以快速掌握此參數的具體用途。", + "suggestion": "補上具體說明,例如 `description: '要釋出的成品檔案路徑或 glob'`。", + "is_new": true + }, + { + "level": "warning", + "role": "Mage", + "location": "action.yml:47", + "problem": "Step 2 將 version_value 直接寫入 GITHUB_OUTPUT 而未進行格式驗證。若上游 calculate-version 輸出的內容包含換行符或其他特殊字元,可能會導致 GITHUB_OUTPUT 格式損壞,甚至產生環境變數注入風險。", + "suggestion": "在寫入 GITHUB_OUTPUT 前,應使用 regex 驗證 version_value 是否符合預期的版本號格式(例如僅包含數字與點號)。", + "is_new": true + }, + { + "level": "warning", + "role": "Mage", + "location": "action.yml:107", + "problem": "Step 4 直接使用 gitea.ref 作為 target_commitish。若此 Action 被 Tag 事件觸發,gitea.ref 可能為 refs/tags/...,這在某些 Gitea release 工具中可能無法正確對應到 Commit,導致發布失敗。", + "suggestion": "建議將 target_commitish 改為使用 ${{ gitea.sha }},以確保 Release 錨定在正確的 Commit SHA 上,避免因 Ref 格式問題導致執行失敗。", + "is_new": true + }, + { + "level": "info", + "role": "Bard", + "location": "action.yml:43", + "problem": "檔案中充斥著過度細節的區塊註解(例如 Step 1, Step 2...),對於熟悉 YAML 與 Actions 的開發者而言,這些註解顯得冗餘且干擾了閱讀的流暢節奏。", + "suggestion": "移除這些描述顯而易見行為的步驟區塊註解,讓程式碼結構一目瞭然,僅在 shell 腳本的複雜邏輯處加入關鍵註解即可。", + "is_new": true + } +] diff --git a/.gitea/workflows/cd.yaml b/.gitea/workflows/cd.yaml index f7195fb..c67d31c 100644 --- a/.gitea/workflows/cd.yaml +++ b/.gitea/workflows/cd.yaml @@ -1,14 +1,52 @@ +# ============================================================================= +# 檔案用途:Gitea CD(Continuous Delivery)workflow 設定檔 +# +# 本檔定義一條名為 CD 的 Gitea Actions workflow,負責在程式碼推送到 +# master 分支時,自動執行「釋出並標註成品版本」的流程。實際的版本標註 +# 邏輯由本 repo 根目錄的 composite action(action.yml)提供,此 workflow +# 僅負責觸發與串接該 composite action。 +# +# 更新日期:2026/06/26 10:14:14(Asia/Taipei) +# ============================================================================= + +# workflow 的顯示名稱,會出現在 Gitea Actions 的執行列表中。 name: CD + +# on:定義觸發本 workflow 的事件。 on: + # push:當有 commit 被推送到 repository 時觸發。 push: + # branches:限制只有特定分支的 push 才會觸發。 branches: + # 僅限 master 分支;推送到其他分支不會啟動本 CD workflow。 + # 這確保版本釋出只在正式主線(master)發生,避免在開發分支誤觸發發版。 - master + +# jobs:本 workflow 包含的工作(job)集合。 jobs: + # release-tag-version:唯一的 job,負責釋出並標註成品版本。 release-tag-version: + # job 的顯示名稱,會出現在 Gitea Actions 的執行畫面上。 name: Release Tag Version + # runs-on:指定執行此 job 的 runner 標籤(label)。 + # 此處使用 ubuntu,代表會在標記為 ubuntu 的 Gitea runner 上執行。 + # 需人工確認:通常 GitHub Actions 慣例為 ubuntu-latest;此處為 ubuntu, + # 請確認 Gitea runner 確實有註冊 "ubuntu" 這個 label,否則 job 不會被排程。 runs-on: ubuntu + # steps:此 job 依序執行的步驟清單。 steps: + # 步驟一:取得(checkout)程式碼,讓後續步驟能存取 repo 內容。 - name: 取得程式碼 + # uses:引用官方 actions/checkout action 來簽出原始碼。 + # 版本號透過 Gitea 變數 vars.ACTION_CHECKOUT_VERSION 動態帶入, + # 便於集中管理 checkout 版本,不必逐檔硬編碼版本字串。 + # 副作用:未取得程式碼前,下一步的本地 composite action(./)將無法被解析。 + # 需人工確認:請確認 repository / organization 層級已設定 + # ACTION_CHECKOUT_VERSION 這個變數,否則 uses 會解析成空版本而失敗。 uses: actions/checkout@${{ vars.ACTION_CHECKOUT_VERSION }} + # 步驟二:釋出並標註成品版本,為本 workflow 的核心動作。 - name: 釋出並標註成品版本 + # uses: ./ 代表引用「本 repo 根目錄」的 composite action(即 action.yml)。 + # 必須先完成步驟一的 checkout,根目錄的 action.yml 才存在於 runner 上而可被引用。 + # 此 composite action 內含實際的版本標註與發版邏輯(請見根目錄 action.yml)。 uses: ./ diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index b9d4eed..a0176e0 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -1,19 +1,63 @@ +# ============================================================================= +# 檔案用途(Purpose): +# 這是一份 Gitea Actions 的 CI workflow 設定檔。 +# 它的主要目的是:當開發者在本 repo 對「非 master」分支發起 Pull Request 時, +# 自動觸發一個名為「AI Code Review」的 job,呼叫共用的 composite action +# 「opencode-code-review」對該 PR 的程式碼變更做 AI 自動審查,並把審查意見 +# 以留言(comment)方式回貼到該 PR。 +# +# 更新日期(Last Updated):2026/06/26 10:14:14 (Asia/Taipei) +# ============================================================================= + +# workflow 顯示名稱,會出現在 Gitea Actions 的執行清單上,方便辨識這條流程。 name: CI + +# on:定義此 workflow 的觸發事件區塊。 on: + # pull_request:當有 Pull Request 相關事件時觸發。 pull_request: + # branches-ignore:被列出的「目標分支(PR base/目的分支)」不會觸發此 workflow。 branches-ignore: + # 忽略目標分支為 master 的 PR;亦即合併進 master 的 PR 不跑此 AI 審查 + # (通常 master 視為正式線上分支,審查在更早的開發分支階段完成)。 - master + # types:限定只在 PR 的「opened(首次開啟)」與「synchronize(後續推送新 commit 更新 PR)」 + # 這兩種事件時觸發;其他事件(如 closed、reopened、labeled 等)不觸發,避免重複或不必要的審查。 types: [opened, synchronize] + +# jobs:定義此 workflow 包含的工作(job)集合。 jobs: + # ai-code-review:job 的識別 id(在 needs、輸出引用等地方會用到此 id)。 ai-code-review: + # name:job 的顯示名稱,會出現在 Gitea Actions 介面上。 name: AI Code Review + # runs-on:指定此 job 執行所使用的 runner 標籤;此處為 ubuntu。 + # 需人工確認:請確認 Gitea 上確實有註冊標籤為 "ubuntu" 的 runner,否則 job 會排不到機器而卡住。 runs-on: ubuntu + # permissions:設定此 job 內 GITHUB_TOKEN/Gitea token 對 repo 的存取權限範圍。 permissions: + # contents: write —— 對 repo 內容(檔案、commit 等)有寫入權限。 + # AI 審查通常只需讀取程式碼;此處給 write,需人工確認是否確有寫入需求(最小權限原則)。 contents: write + # pull-requests: write —— 對 PR 有寫入權限,用於在 PR 上建立 / 更新審查留言。 pull-requests: write + # issues: write —— 對 issue 有寫入權限;Gitea/GitHub 中 PR 留言底層常走 issue comment API,故需此權限。 issues: write + # steps:此 job 依序執行的步驟清單。 steps: + # 第 1 個 step:呼叫外部共用 composite action 執行 AI 程式碼審查。 - name: AI 程式碼審查 by OpenCode + # uses:引用要執行的 composite action 來源與版本。 + # 來源:https://gitea.jsc.idv.tw/composite-actions/opencode-code-review + # 版本:@${{ vars.ACTION_OPENCODE_CODE_REVIEW_VERSION }} + # 版本號取自 repo/organization 設定的變數 vars.ACTION_OPENCODE_CODE_REVIEW_VERSION, + # 可集中管理升版,不需修改本檔。 + # 需人工確認:請確認該 vars 變數已在 Gitea 設定且值有效(例如 v1.0.0 / 分支名 / commit), + # 若變數為空,action 參照會解析失敗導致 step 執行錯誤。 uses: https://gitea.jsc.idv.tw/composite-actions/opencode-code-review@${{ vars.ACTION_OPENCODE_CODE_REVIEW_VERSION }} + # with:傳遞給該 composite action 的輸入參數。 with: + # comment_token:提供給 action 用來回貼審查留言到 PR 的存取權杖(token)。 + # 取自 secrets.COMMENT_TOKEN(機密,由 Gitea Secrets 管理,不應寫死在檔案中)。 + # 需人工確認:請確認 secrets.COMMENT_TOKEN 已設定,且該 token 具有對本 repo PR/issue 留言的權限。 comment_token: ${{ secrets.COMMENT_TOKEN }} diff --git a/README.md b/README.md index 651629c..4177d95 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Release Tag Version -更新時間:2026/06/26 00:48:28 +更新時間:2026/06/26 10:47:20 + +本專案為 Gitea Actions 的 **composite action**,用來自動計算版本號、建立 release 並標註對應 tag,最後清理舊成品。 ## 專案列表 @@ -8,7 +10,7 @@ | 專案名稱 | 專案描述 | | --- | --- | -| [Release Tag Version](https://gitea.jsc.idv.tw/composite-actions/release-tag-version/src/branch/develop) | Gitea composite action,負責計算版本號、建立 release tag,並清理舊成品。此專案未公開可列入 README 的程式方法。 | +| [Release Tag Version](https://gitea.jsc.idv.tw/composite-actions/release-tag-version/src/branch/develop) | Gitea composite action,依序呼叫 calculate-version 計算版本號、組合 release 參數、以 akkuman/gitea-release-action 建立 release 與 tag,再以 release-cleanup 清理舊成品。此專案未公開可列入 README 的程式方法。 | ### 參考專案 @@ -24,18 +26,56 @@ ## 功能列表 -目前未偵測到可列入 README 的 public method、public constructor、public extension method 或 public operator。 +本專案為 YAML 定義的 Gitea composite action 與 workflow,未包含任何可文件化的 public method、public constructor、public extension method 或 public operator,因此沒有可列入的功能項目。 ## 使用範例 -此專案提供 Gitea composite action,可在 workflow 中引用: +本專案不提供程式方法,而是提供一個可被其他 workflow 引用的 Gitea composite action。 + +### 在其他 repo 的 workflow 中引用 ```yaml steps: +- name: 取得程式碼 + uses: actions/checkout@${{ vars.ACTION_CHECKOUT_VERSION }} - name: 釋出並標註成品版本 - uses: https://gitea.jsc.idv.tw/composite-actions/release-tag-version@v0.0.4 + uses: https://gitea.jsc.idv.tw/composite-actions/release-tag-version@ with: + # files 為非必填;指定要隨 release 一起釋出(上傳)的成品檔案,可省略。 files: dist/* ``` -執行時會先計算版本號,再建立對應 release/tag,最後清理舊成品。需確認相關 action 版本變數與權限已在 Gitea workflow 環境中設定。 +### 本 repo 內的 CD workflow(`.gitea/workflows/cd.yaml`) + +```yaml +on: + push: + branches: + - master +jobs: + release-tag-version: + name: Release Tag Version + runs-on: ubuntu + steps: + - name: 取得程式碼 + uses: actions/checkout@${{ vars.ACTION_CHECKOUT_VERSION }} + - name: 釋出並標註成品版本 + # uses: ./ 引用本 repo 根目錄的 composite action(action.yml) + uses: ./ +``` + +### 執行流程與前置條件 + +引用後,composite action 會依序執行: + +1. **版本號計算**:呼叫 `docker-actions/calculate-version` 算出本次版本號。 +2. **組合釋出參數**:版本號非空時,組出 release 的 `name`(格式 ` v<版本>`)與 `tag_name`(格式 `v<版本>`)。 +3. **檢查版本號輸出**:版本號為空時輸出錯誤訊息並 `exit 1`,中止流程,避免建立錯誤的 release/tag。 +4. **釋出並標註成品版本**:以 `akkuman/gitea-release-action` 建立 release 並打 tag,附帶 `files` 指定的成品。 +5. **清理舊成品**:呼叫 `docker-actions/release-cleanup` 清理過舊的 release。 + +**前置條件**(需於 Gitea repo/organization 環境設定): + +- 變數 `vars.ACTION_CALCULATE_VERSION`、`vars.ACTION_GITEA_RELEASE_VERSION`、`vars.ACTION_RELEASE_CLEANUP_VERSION`、`vars.ACTION_CHECKOUT_VERSION` 皆需設定且值有效。 +- runner 需有 `ubuntu` label。 +- 預期結果:在 Gitea 上建立 `v<版本>` 的 release 與 tag,並清理舊成品。 diff --git a/action.yml b/action.yml index f5523c7..f1777fa 100644 --- a/action.yml +++ b/action.yml @@ -1,37 +1,122 @@ +# ============================================================================= +# 指令檔用途: +# 這是一個 Gitea composite action(複合動作),名稱為「Release Tag Version」。 +# 它被其他 workflow 引用,用來「自動計算版本號並釋出(release)標註成品版本」。 +# 完整流程: +# (1) 呼叫 calculate-version action 計算本次的版本號。 +# (2) 若版本號非空,組合 release 所需的 name 與 tag_name。 +# (3) 若版本號為空,輸出錯誤訊息並以 exit 1 中止整個 action。 +# (4) 呼叫 akkuman/gitea-release-action 在 Gitea 上建立 release 並打 tag, +# 同時可附帶要釋出的檔案(files)。 +# (5) 呼叫 release-cleanup action 清理舊的成品(release)。 +# +# 更新日期:2026/06/26 10:14:14(Asia/Taipei) +# ============================================================================= + +# action 的顯示名稱,會在 Gitea Actions 介面與被引用時呈現。 name: 'Release Tag Version' +# action 的說明文字,描述此 action 的目的:釋出並標註成品版本。 description: '釋出並標註成品版本' +# action 作者標註,僅作為 metadata,不影響執行行為。 author: 'Jeffery' + +# inputs 區塊:定義此 composite action 對外開放、可由呼叫方傳入的參數。 inputs: + # files 參數:指定要隨 release 一起釋出(上傳)的檔案。 files: + # 此參數的描述(原始檔留空)。 + # 需人工確認:description 為空字串,建議補上說明(例如「要釋出的成品檔案路徑或 glob」)以利維護, + # 但屬文件性質、不影響執行邏輯,故此處不逕自修改。 description: '' + # required: false 表示此參數非必填;呼叫方未傳入時,files 會是空值。 required: false + +# runs 區塊:定義此 action 的執行方式與步驟。 runs: + # using: 'composite' 表示這是「複合動作」,由下方多個 step 串接組成,而非單一 Docker/JS action。 using: 'composite' + # steps:依序執行的步驟清單,順序具有意義,不可調換。 steps: + # --------------------------------------------------------------------------- + # Step 1:版本號計算 + # 引用外部 calculate-version action 來計算本次要釋出的版本號, + # 其結果會以 output「version」提供給後續步驟(透過 step id 取用)。 + # --------------------------------------------------------------------------- - name: 版本號計算 + # id 設為 version-calculate,後續步驟以 steps.version-calculate.outputs.version 取得計算結果。 id: version-calculate + # uses:引用 Gitea 上 docker-actions/calculate-version action。 + # 版本(@ 後面)由 repository/organization 變數 vars.ACTION_CALCULATE_VERSION 決定, + # 便於集中管理被引用 action 的版本,不需改動本檔。 uses: https://gitea.jsc.idv.tw/docker-actions/calculate-version@${{ vars.ACTION_CALCULATE_VERSION }} + + # --------------------------------------------------------------------------- + # Step 2:組合釋出參數 + # 僅在版本號非空時執行,組出 release 需要的 name 與 tag_name, + # 並寫入 GITHUB_OUTPUT 供後續釋出步驟取用。 + # --------------------------------------------------------------------------- - name: 組合釋出參數 + # id 設為 release-params,後續步驟以 steps.release-params.outputs.* 取得組好的 name / tag_name。 id: release-params + # if 條件:只有當上一步算出的 version 不是空字串時才執行此步驟。 + # 這是「版本有效」的分支,與 Step 3「版本為空」的分支互斥。 if: ${{ steps.version-calculate.outputs.version != '' }} + # run:以 shell 執行下列指令來組合參數。 run: | + # 取得目前 repository 完整名稱(格式為 owner/repo),存入 repository 變數。 repository="${{ gitea.repository }}" + # 取得 Step 1 計算出的版本號,存入 version_value 變數。 version_value="${{ steps.version-calculate.outputs.version }}" + # 組出 release 的顯示名稱並寫入 GITHUB_OUTPUT: + # ${repository##*/} 為 bash 參數展開,去掉最長前綴「*/」,即取 owner/repo 的最後一段 repo 名稱。 + # 最終格式為「 v<版本>」(注意 v 前有一個空白)。 echo "name=${repository##*/} v${version_value}" >> "$GITHUB_OUTPUT" + # 組出 release 的 tag 名稱並寫入 GITHUB_OUTPUT:格式為「v<版本>」(v 緊接版本,無空白)。 echo "tag_name=v${version_value}" >> "$GITHUB_OUTPUT" + # shell: bash 明確指定以 bash 執行(${repository##*/} 等參數展開語法需 bash 支援)。 shell: bash + + # --------------------------------------------------------------------------- + # Step 3:檢查版本號輸出 + # 僅在版本號為空時執行;視為錯誤狀況,輸出訊息到 stderr 並中止 action。 + # --------------------------------------------------------------------------- - name: 檢查版本號輸出 + # if 條件:只有當 version 為空字串時才執行;與 Step 2 的條件互斥,為「版本無效」分支。 if: ${{ steps.version-calculate.outputs.version == '' }} + # run:輸出錯誤訊息並以非零結束碼中止流程。 run: | + # 將錯誤訊息寫到 stderr(>&2),表示 calculate-version 沒有產出有效版本號。 echo "version-calculate output version is empty" >&2 + # 以 exit 1 結束此步驟並讓整個 action 失敗,避免後續用空版本去建立錯誤的 release/tag。 exit 1 + # shell: bash 明確指定以 bash 執行此步驟。 shell: bash + + # --------------------------------------------------------------------------- + # Step 4:釋出並標註成品版本 + # 引用 akkuman/gitea-release-action,在 Gitea 上建立 release 並打 tag。 + # 依賴 Step 2 組好的 name / tag_name;若 Step 3 已 exit 1,本步驟不會執行。 + # --------------------------------------------------------------------------- - name: 釋出並標註成品版本 + # uses:引用第三方 akkuman/gitea-release-action,負責實際的 release 建立與 tag 標註。 + # 版本由 vars.ACTION_GITEA_RELEASE_VERSION 控制,集中管理被引用版本。 uses: akkuman/gitea-release-action@${{ vars.ACTION_GITEA_RELEASE_VERSION }} + # with:傳入 release action 所需的參數。 with: + # name:release 的顯示名稱,來自 Step 2 組出的 outputs.name(格式「 v<版本>」)。 name: ${{ steps.release-params.outputs.name }} + # tag_name:release 對應的 tag 名稱,來自 Step 2 組出的 outputs.tag_name(格式「v<版本>」)。 tag_name: ${{ steps.release-params.outputs.tag_name }} + # target_commitish:release/tag 要指向的 ref(分支或 commit),這裡使用觸發此次執行的 gitea.ref。 target_commitish: ${{ gitea.ref }} + # files:要附加到 release 的成品檔案,來自本 action 的 inputs.files(呼叫方傳入,可為空)。 files: ${{ inputs.files }} + + # --------------------------------------------------------------------------- + # Step 5:清理舊成品 + # 引用 release-cleanup action,清理過舊的 release/成品,避免無限累積。 + # --------------------------------------------------------------------------- - name: 清理舊成品 + # uses:引用 Gitea 上 docker-actions/release-cleanup action 執行清理。 + # 版本由 vars.ACTION_RELEASE_CLEANUP_VERSION 控制。 uses: https://gitea.jsc.idv.tw/docker-actions/release-cleanup@${{ vars.ACTION_RELEASE_CLEANUP_VERSION }}