diff --git a/.amazonq/rules/triage-findings.md b/.amazonq/rules/triage-findings.md new file mode 100644 index 0000000..4b65ce1 --- /dev/null +++ b/.amazonq/rules/triage-findings.md @@ -0,0 +1,14 @@ +# Triage Findings + +When the task is to triage review findings, follow this workflow: + +1. Merge all findings into one list. +2. Remove duplicates. +3. Sort by severity: `critical` -> `warning` -> `info`. +4. Renumber from 1 after sorting. +5. Fix real issues with the smallest safe change. +6. Add false positives to `.gitea/ai-review/exclusions.json`, preserving the original wording, language, and semantics as much as possible. +7. Add or update tests when behavior changes. +8. Re-check the issue after each fix. + +Use the repo-local `triage-findings` skill for the same workflow when running in Codex. diff --git a/.claude/skills/triage-findings/SKILL.md b/.claude/skills/triage-findings/SKILL.md new file mode 100644 index 0000000..c4ab450 --- /dev/null +++ b/.claude/skills/triage-findings/SKILL.md @@ -0,0 +1,29 @@ +--- +name: triage-findings +description: Triage findings, fix real issues, and exclude false positives. +--- + +# Triage Findings + +## Use + +直接輸入:`triage-findings 問題原始檔(文字或截圖)` + +## Workflow + +1. Merge all findings. +2. Sort by severity: + - critical + - warning + - info +3. Renumber from 1. +4. Fix real issues. +5. Put false positives into `.gitea/ai-review/exclusions.json`, preserving the original wording, language, and semantics as much as possible. +6. Add tests when behavior changes. + +## Output Rules + +- Keep the final list short. +- Keep numbering contiguous. +- Preserve file path, location, and fix. +- When writing exclusions, prefer the original issue text over paraphrased rewrites. diff --git a/.codex/skills/triage-findings/SKILL.md b/.codex/skills/triage-findings/SKILL.md new file mode 100644 index 0000000..21476cb --- /dev/null +++ b/.codex/skills/triage-findings/SKILL.md @@ -0,0 +1,45 @@ +--- +name: triage-findings +description: Merge code-review findings, sort and renumber them by severity, resolve real issues, and move false positives into exclusions. +--- + +# Triage Findings + +## When To Use + +Use this skill when you receive multiple review findings, screenshots, comments, or issue lists that need to become one final triaged list. +It is also used when some findings are false positives and should be moved into the exclusions list. + +## Workflow + +1. Collect all findings into one list. +2. Merge duplicates into a single finding when they describe the same issue. +3. Sort the final list by severity: + - critical + - warning + - info +4. Renumber the sorted list from 1 upward. +5. Rewrite each finding concisely so the final list reads cleanly and consistently. +6. If a finding is a false positive, do not keep it in the final list. +7. Add false positives to the exclusions list using the existing schema in the repo or task context, and preserve the original finding wording as much as possible, including language and semantics. + +## Resolution Flow + +After the list is merged and ordered, resolve the remaining findings one by one. + +1. Start from the highest severity item. +2. Identify the root cause in the relevant file or context. +3. Apply the smallest safe change that fixes the issue. +4. Add or update tests when behavior changes. +5. Re-check the issue after the change. +6. If the item is confirmed false positive, move it to exclusions instead of changing code. +7. Continue until the list is either fixed or explicitly excluded. + +## Output Rules + +- Keep the final findings list in severity order, then by any stable secondary order needed to make it readable. +- Keep numbering contiguous after filtering and merging. +- Preserve useful details like file path, location, and suggested fix. +- Keep exclusions entries minimal and consistent with the project schema. +- When writing exclusions, prefer the original issue text and language; only paraphrase if needed to fit the schema. +- If the source already provides a severity or title, keep it unless it conflicts with the final ordering. diff --git a/.codex/skills/triage-findings/agents/openai.yaml b/.codex/skills/triage-findings/agents/openai.yaml new file mode 100644 index 0000000..6f59e2c --- /dev/null +++ b/.codex/skills/triage-findings/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Triage Findings" + short_description: "Triage, sort, fix, and exclude review findings" + default_prompt: "Use $triage-findings to merge review findings, sort and renumber them by severity, resolve real issues one by one, and add false positives to exclusions." diff --git a/.gemini/skills/triage-findings/SKILL.md b/.gemini/skills/triage-findings/SKILL.md new file mode 100644 index 0000000..c4ab450 --- /dev/null +++ b/.gemini/skills/triage-findings/SKILL.md @@ -0,0 +1,29 @@ +--- +name: triage-findings +description: Triage findings, fix real issues, and exclude false positives. +--- + +# Triage Findings + +## Use + +直接輸入:`triage-findings 問題原始檔(文字或截圖)` + +## Workflow + +1. Merge all findings. +2. Sort by severity: + - critical + - warning + - info +3. Renumber from 1. +4. Fix real issues. +5. Put false positives into `.gitea/ai-review/exclusions.json`, preserving the original wording, language, and semantics as much as possible. +6. Add tests when behavior changes. + +## Output Rules + +- Keep the final list short. +- Keep numbering contiguous. +- Preserve file path, location, and fix. +- When writing exclusions, prefer the original issue text over paraphrased rewrites. diff --git a/.gitea/ai-review/exclusions.json b/.gitea/ai-review/exclusions.json new file mode 100644 index 0000000..279629a --- /dev/null +++ b/.gitea/ai-review/exclusions.json @@ -0,0 +1,121 @@ +[ + { + "level": "critical", + "role": "Maya", + "location": "entrypoint.sh:14-21", + "suggestion": "新引入的 `require_var` 函數是腳本核心參數驗證邏輯,但缺乏獨立的單元測試。請為此函數建立測試,確保它在變數為空字串、為 \"null\" 字串以及有效值時,都能正確地判斷並執行預期的行為(例如:在無效情況下退出並輸出錯誤訊息至 stderr)。", + "is_new": true + }, + { + "level": "critical", + "role": "Aria", + "location": "a/entrypoint.sh:56", + "suggestion": "舊版腳本缺少檔案結尾的換行符 (newline)。根據 POSIX 標準,文字檔案應以換行符結束。新版已修正此問題,這是重要的風格與相容性改進。", + "is_new": true + }, + { + "level": "warning", + "role": "Zara", + "location": "entrypoint.sh", + "suggestion": "舊版腳本缺少 `set -euo pipefail`。建議在腳本開頭加入此設定,以確保腳本在遇到錯誤時能立即終止,並避免使用未定義的變數,從而提高腳本的可靠性並防止因靜默失敗而浪費的計算資源。", + "is_new": true + }, + { + "level": "warning", + "role": "Rex", + "location": "entrypoint.sh:38", + "suggestion": "在組合 `RELEASE_URL` 時,`GITEA_SERVER_URL` 和 `GITEA_REPOSITORY` 變數應進行 URL 編碼。若這些變數包含特殊字元(如 `/`, `?`, `#`, `&`, 空格),可能會導致產生的 URL 無效或指向錯誤的資源,進而影響套件的元數據正確性或連結完整性。建議使用適當的工具或函數進行 URL 編碼,以確保 URL 的完整性。", + "is_new": true + }, + { + "level": "warning", + "role": "Rex", + "location": "entrypoint.sh:37", + "suggestion": "在組合 `RELEASE_COPYRIGHT` 時,`RELEASE_COMPANY` 變數若包含 XML/HTML 特殊字元(如 `<`, `>`, `&`, `'`, `\"`),可能會導致 NuGet 套件的 `.nuspec` 檔案中產生格式錯誤的 XML,或在顯示時被錯誤解析。建議對 `RELEASE_COMPANY` 進行 XML/HTML 實體編碼,以確保元數據的正確性及避免潛在的 XML 注入問題。", + "is_new": true + }, + { + "level": "warning", + "role": "Maya", + "location": "entrypoint.sh:37", + "suggestion": "變數 `WORKSPACE` 用於定義 `OUTPUT_DIR`,但它並未經過 `require_var` 函數的驗證。如果 `WORKSPACE` 為空或未設定,可能導致 `OUTPUT_DIR` 路徑不正確,進而影響後續的打包操作。請在參數檢查階段加入 `require_var WORKSPACE`。", + "is_new": true + }, + { + "level": "warning", + "role": "Maya", + "location": "entrypoint.sh:46-49", + "suggestion": "腳本新增了檢查 `RELEASE_PROJECT` 目錄是否存在的功能。這是一個重要的錯誤處理路徑,但目前沒有測試案例來驗證此功能。請設計測試情境,模擬 `RELEASE_PROJECT` 指向一個不存在的目錄,並確認腳本能正確地退出並輸出錯誤訊息。", + "is_new": true + }, + { + "level": "warning", + "role": "Maya", + "location": "entrypoint.sh:54-63", + "suggestion": "`dotnet pack` 命令是此腳本的核心功能,但腳本僅依賴其退出碼判斷成功與否。即使命令成功,也應進一步驗證是否確實產生了預期的 `.nupkg` 套件檔案。請在 `dotnet pack` 執行後,加入檢查 `$OUTPUT_DIR` 中是否存在 `.nupkg` 檔案的步驟,以確保打包結果的完整性。", + "is_new": true + }, + { + "level": "warning", + "role": "Aria", + "location": "a/entrypoint.sh:44-51", + "suggestion": "舊版腳本中的 `dotnet pack` 命令過長且未分行,降低了可讀性。新版將其拆分為多行並適當縮排,顯著提升了程式碼的可讀性與維護性,這是良好的風格改進。", + "is_new": true + }, + { + "level": "warning", + "role": "Aria", + "location": "a/entrypoint.sh:34-35", + "suggestion": "舊版腳本中 `RELEASE_COPYRIGHT` 變數的賦值方式較為混亂,先賦予年份再重新組合字串。新版直接在宣告時完成組合,並使用 `readonly` 標記,提升了程式碼的清晰度與變數管理的嚴謹性。", + "is_new": true + }, + { + "level": "info", + "role": "Aria", + "location": "entrypoint.sh:65", + "suggestion": "為了保持 `dotnet pack` 參數值引號使用的一致性,即使是簡單的字串值,也可以考慮將 `/p:RepositoryType=git` 修改為 `/p:RepositoryType=\"git\"`。", + "is_new": true + }, + { + "level": "info", + "role": "Maya", + "location": "entrypoint.sh:54-63", + "suggestion": "為確保 `dotnet pack` 命令在各種情況下都能穩定運行,建議增加測試案例來涵蓋傳遞給它的參數的邊界條件和特殊字元處理。例如,測試 `RELEASE_DESCRIPTION` 包含特殊符號或非常長的字串,以及 `RELEASE_AUTHOR` 或 `RELEASE_COMPANY` 包含非英文字元的情況,以驗證參數能正確地傳遞和解析。", + "is_new": true + }, + { + "level": "info", + "role": "Maya", + "location": "entrypoint.sh:34-36", + "suggestion": "腳本中 `RELEASE_COPYRIGHT` 和 `RELEASE_URL` 等變數是根據其他輸入參數動態生成的。建議在測試中明確驗證這些衍生變數的內容是否符合預期格式和邏輯,例如檢查 `RELEASE_COPYRIGHT` 的年份和公司名稱是否正確,以及 `RELEASE_URL` 的組合是否完整。", + "is_new": true + }, + { + "level": "info", + "role": "Maya", + "location": "entrypoint.sh", + "suggestion": "雖然腳本的模組化程度有所提升,但仍缺乏全面的端到端整合測試。建議建立一個完整的測試套件,模擬不同的環境變數設定(包括有效和無效的組合),並在一個模擬的 .NET 專案上運行此腳本。測試應涵蓋腳本的啟動、參數驗證、目錄操作、`dotnet pack` 執行以及最終輸出結果的驗證,以確保整個工作流程的穩定性和正確性。", + "is_new": true + }, + { + "level": "info", + "role": "Leo", + "location": "entrypoint.sh:39", + "suggestion": "考慮將 `RELEASE_URL` 中硬編碼的 `master` 分支名稱改為可配置的變數,例如 `GITEA_BRANCH`,以適應不同專案可能使用 `main` 或其他預設分支的情況,增加彈性。", + "is_new": true + }, + { + "level": "info", + "role": "Leo", + "location": "entrypoint.sh", + "suggestion": "雖然程式碼的可讀性已大幅提升,但考慮在檔案開頭添加簡要的腳本用途說明,以及預期環境變數的列表,將有助於新維護者快速理解其功能。", + "is_new": true + }, + { + "level": "info", + "role": "Aria", + "location": "b/entrypoint.sh:59", + "suggestion": "在 `dotnet pack` 命令中,參數 `/p:RepositoryType=git` 的值 'git' 未使用引號。雖然在此特定情況下沒有問題,但為了風格一致性,可以考慮對所有參數值使用引號,例如 `/p:RepositoryType=\"git\"`。", + "is_new": true + } +] diff --git a/.gitea/ai-review/findings.json b/.gitea/ai-review/findings.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/.gitea/ai-review/findings.json @@ -0,0 +1 @@ +[] diff --git a/.gitea/workflows/master.yaml b/.gitea/workflows/master.yaml index b54c903..b37b091 100644 --- a/.gitea/workflows/master.yaml +++ b/.gitea/workflows/master.yaml @@ -1,10 +1,11 @@ +name: CD on: push: branches: - master jobs: version: - name: "CD > 計算版本號" + name: 計算版本號 runs-on: ubuntu outputs: version: ${{ steps.version.outputs.version }} @@ -13,14 +14,14 @@ jobs: id: version uses: https://gitea.jsc.idv.tw/actions/calculate-version@${{ vars.ACTION_CALCULATE_VERSION }} release: - name: "CD > 發布專案" + name: 發布專案 runs-on: ubuntu needs: version steps: - name: 發布專案 uses: akkuman/gitea-release-action@${{ vars.ACTION_RELEASE_VERSION }} with: - tag_name: "v${{ needs.version.outputs.version }}" + tag_name: v${{ needs.version.outputs.version }} - name: 清理成品 uses: https://gitea.jsc.idv.tw/actions/cleanup-release@${{ vars.ACTION_CLEANUP_RELEASE_VERSION }} with: diff --git a/.gitea/workflows/review.yaml b/.gitea/workflows/review.yaml new file mode 100644 index 0000000..b81ac76 --- /dev/null +++ b/.gitea/workflows/review.yaml @@ -0,0 +1,23 @@ +name: AI +on: + pull_request: + branches-ignore: + - master + types: [opened, synchronize] +jobs: + code-review: + name: Code Review + runs-on: ubuntu + steps: + - name: AI Code Review + uses: https://gitea.jsc.idv.tw/actions/code-review@${{ vars.ACTION_CODE_REVIEW_VERSION }} + with: + GITEA_TOKEN: ${{ secrets.RUNNER_TOKEN }} + GITEA_COMMENT_TOKEN: ${{ secrets.GITEA_TOKEN }} + GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }},${{ secrets.GEMINI_API_KEY_1 }},${{ secrets.GEMINI_API_KEY_2 }},${{ secrets.GEMINI_API_KEY_3 }},${{ secrets.GEMINI_API_KEY_4 }},${{ secrets.GEMINI_API_KEY_5 }},${{ secrets.GEMINI_API_KEY_6 }},${{ secrets.GEMINI_API_KEY_7 }},${{ secrets.GEMINI_API_KEY_8 }},${{ secrets.GEMINI_API_KEY_9 }},${{ secrets.GEMINI_API_KEY_10 }},${{ secrets.GEMINI_API_KEY_11 }},${{ secrets.GEMINI_API_KEY_12 }},${{ secrets.GEMINI_API_KEY_13 }},${{ secrets.GEMINI_API_KEY_14 }},${{ secrets.GEMINI_API_KEY_15 }},${{ secrets.GEMINI_API_KEY_16 }},${{ secrets.GEMINI_API_KEY_17 }},${{ secrets.GEMINI_API_KEY_18 }},${{ secrets.GEMINI_API_KEY_19 }} + GEMINI_BASE_URL: https://generativelanguage.googleapis.com/v1beta + GEMINI_MODEL: ${{ vars.GEMINI_MODEL }} + permissions: + contents: write + pull-requests: write + issues: write \ No newline at end of file diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..f1a77ef --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,14 @@ +# Triage Findings + +Use the triage-finding workflow for review issue lists: + +1. Merge findings into one list. +2. Remove duplicates. +3. Sort by severity: `critical` -> `warning` -> `info`. +4. Renumber from 1. +5. Fix real issues with the smallest safe change. +6. Put false positives into `.gitea/ai-review/exclusions.json`, preserving the original wording, language, and semantics as much as possible. +7. Add or update tests when behavior changes. +8. Re-check after each fix. + +The full reusable skill lives in `.claude/skills/triage-findings/SKILL.md`. diff --git a/.github/skills/triage-findings/SKILL.md b/.github/skills/triage-findings/SKILL.md new file mode 100644 index 0000000..8ca4117 --- /dev/null +++ b/.github/skills/triage-findings/SKILL.md @@ -0,0 +1,14 @@ +# Triage Findings + +Use the triage-finding workflow for review issue lists: + +1. Merge findings into one list. +2. Remove duplicates. +3. Sort by severity: `critical` -> `warning` -> `info`. +4. Renumber from 1. +5. Fix real issues with the smallest safe change. +6. Put false positives into `.gitea/ai-review/exclusions.json`, preserving the original wording, language, and semantics as much as possible. +7. Add or update tests when behavior changes. +8. Re-check after each fix. + +The reusable skill lives in `.gemini/skills/triage-findings/SKILL.md`. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..fa2403d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,16 @@ +# Triage Findings + +When the task is to triage review findings, follow this workflow: + +1. Merge all findings into one list. +2. Remove duplicates. +3. Sort by severity: `critical` -> `warning` -> `info`. +4. Renumber from 1 after sorting. +5. Fix real issues with the smallest safe change. +6. Add false positives to `.gitea/ai-review/exclusions.json`, preserving the original wording, language, and semantics as much as possible. +7. Add or update tests when behavior changes. +8. Re-check the issue after each fix. + +Use the repo-local `triage-findings` skill for the same workflow when running in Codex. + +Trigger it with `/triage-findings`. diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000..8ca4117 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,14 @@ +# Triage Findings + +Use the triage-finding workflow for review issue lists: + +1. Merge findings into one list. +2. Remove duplicates. +3. Sort by severity: `critical` -> `warning` -> `info`. +4. Renumber from 1. +5. Fix real issues with the smallest safe change. +6. Put false positives into `.gitea/ai-review/exclusions.json`, preserving the original wording, language, and semantics as much as possible. +7. Add or update tests when behavior changes. +8. Re-check after each fix. + +The reusable skill lives in `.gemini/skills/triage-findings/SKILL.md`. diff --git a/entrypoint.sh b/entrypoint.sh index 55db888..b16a4ef 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,56 +1,72 @@ -#!/bin/bash +#!/usr/bin/env bash -echo "==================================================" +set -euo pipefail -echo "參數檢查" +separator() { + printf '%s\n' "==================================================" +} -echo "--------------------------------------------------" +section() { + printf '\n%s\n' "$1" + printf '%s\n' "--------------------------------------------------" +} -# 顯示 GITEA_SERVER_URL 參數,並檢查是否為空或 "null",如果是則輸出錯誤訊息並退出 -echo "GITEA_SERVER_URL=$GITEA_SERVER_URL" && ([ -z "$GITEA_SERVER_URL" ] || [ "$GITEA_SERVER_URL" = "null" ]) && exit 1 +require_var() { + local name="$1" + local value="${!name:-}" -# 顯示 GITEA_REPOSITORY 參數,並檢查是否為空或 "null",如果是則輸出錯誤訊息並退出 -echo "GITEA_REPOSITORY=$GITEA_REPOSITORY" && ([ -z "$GITEA_REPOSITORY" ] || [ "$GITEA_REPOSITORY" = "null" ]) && exit 1 + printf '%s=%s\n' "$name" "$value" + if [ -z "$value" ] || [ "$value" = "null" ]; then + printf '錯誤: %s 不可為空或 null\n' "$name" >&2 + exit 1 + fi +} -# 顯示 CONFIGURATION 參數,並檢查是否為空或 "null",如果是則輸出錯誤訊息並退出 -echo "CONFIGURATION=$CONFIGURATION" && ([ -z "$CONFIGURATION" ] || [ "$CONFIGURATION" = "null" ]) && exit 1 +separator +section "參數檢查" -# 顯示 RELEASE_PROJECT 參數,並檢查是否為空或 "null",如果是則輸出錯誤訊息並退出 -echo "RELEASE_PROJECT=$RELEASE_PROJECT" && ([ -z "$RELEASE_PROJECT" ] || [ "$RELEASE_PROJECT" = "null" ]) && exit 1 +require_var GITEA_SERVER_URL +require_var GITEA_REPOSITORY +require_var CONFIGURATION +require_var RELEASE_PROJECT +require_var RELEASE_VERSION +require_var RELEASE_AUTHOR +require_var RELEASE_COMPANY +require_var RELEASE_DESCRIPTION -# 顯示 RELEASE_VERSION 參數,並檢查是否為空或 "null",如果是則輸出錯誤訊息並退出 -echo "RELEASE_VERSION=$RELEASE_VERSION" && ([ -z "$RELEASE_VERSION" ] || [ "$RELEASE_VERSION" = "null" ]) && exit 1 +readonly RELEASE_COPYRIGHT="Copyright (c) $(date +%Y) ${RELEASE_COMPANY}" +readonly RELEASE_URL="${GITEA_SERVER_URL}/${GITEA_REPOSITORY}/src/branch/master" +readonly OUTPUT_DIR="${WORKSPACE}/output" -# 顯示 RELEASE_AUTHOR 參數,並檢查是否為空或 "null",如果是則輸出錯誤訊息並退出 -echo "RELEASE_AUTHOR=$RELEASE_AUTHOR" && ([ -z "$RELEASE_AUTHOR" ] || [ "$RELEASE_AUTHOR" = "null" ]) && exit 1 +printf 'RELEASE_COPYRIGHT=%s\n' "$RELEASE_COPYRIGHT" +printf 'RELEASE_URL=%s\n' "$RELEASE_URL" +printf 'OUTPUT_DIR=%s\n' "$OUTPUT_DIR" -# 顯示 RELEASE_COMPANY 參數,並檢查是否為空或 "null",如果是則輸出錯誤訊息並退出 -echo "RELEASE_COMPANY=$RELEASE_COMPANY" && ([ -z "$RELEASE_COMPANY" ] || [ "$RELEASE_COMPANY" = "null" ]) && exit 1 +section "打包 NUGET 套件" -# 組合 RELEASE_COPYRIGHT 參數並顯示 -RELEASE_COPYRIGHT=$(date +%Y) -RELEASE_COPYRIGHT="Copyright©$RELEASE_COPYRIGHT $RELEASE_COMPANY" && echo "RELEASE_COPYRIGHT=$RELEASE_COPYRIGHT" +if [ ! -d "$RELEASE_PROJECT" ]; then + printf '錯誤: 找不到專案目錄 %s\n' "$RELEASE_PROJECT" >&2 + exit 1 +fi -# 顯示 RELEASE_DESCRIPTION 參數,並檢查是否為空或 "null",如果是則輸出錯誤訊息並退出 -echo "RELEASE_DESCRIPTION=$RELEASE_DESCRIPTION" && ([ -z "$RELEASE_DESCRIPTION" ] || [ "$RELEASE_DESCRIPTION" = "null" ]) && exit 1 +mkdir -p "$OUTPUT_DIR" -echo "==================================================" +printf '專案目錄=%s\n' "$RELEASE_PROJECT" +printf '組建配置=%s\n' "$CONFIGURATION" +printf '版本號=%s\n' "$RELEASE_VERSION" -echo "打包 NUGET 套件" - -echo "--------------------------------------------------" - -# 組合來源連結 -RELEASE_URL="$GITEA_SERVER_URL/$GITEA_REPOSITORY/src/branch/master" - -# 打包 NUGET 套件 -cd $RELEASE_PROJECT && dotnet pack -c "$CONFIGURATION" -o "$WORKSPACE/output" \ +cd "$RELEASE_PROJECT" +dotnet pack \ + -c "$CONFIGURATION" \ + -o "$OUTPUT_DIR" \ /p:PackageVersion="$RELEASE_VERSION" \ /p:RepositoryUrl="$RELEASE_URL" \ - /p:RepositoryType="git" \ + /p:RepositoryType=git \ /p:Authors="$RELEASE_AUTHOR" \ /p:Company="$RELEASE_COMPANY" \ /p:Copyright="$RELEASE_COPYRIGHT" \ /p:Description="$RELEASE_DESCRIPTION" -echo "==================================================" \ No newline at end of file +section "完成" +printf '輸出位置=%s\n' "$OUTPUT_DIR" +separator