Merge pull request 'feat: 加入 AI Code Review 工作流' (#18) from feat/ai_code_review into develop
Reviewed-on: #18
This commit is contained in:
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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."
|
||||
@@ -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.
|
||||
@@ -0,0 +1,56 @@
|
||||
[
|
||||
{
|
||||
"level": "critical",
|
||||
"role": "Maya",
|
||||
"location": "Dockerfile 或 entrypoint.sh",
|
||||
"suggestion": "此 Git Diff 引入了 Dockerfile 和 entrypoint.sh 的重要變更,但沒有包含任何整合測試或端到端測試來驗證 Docker 映像檔的行為。應建立一個測試套件,能夠建構此 Docker 映像檔,並在容器中執行 `entrypoint.sh`,透過設定不同的環境變數來驗證其輸出、日誌和退出碼是否符合預期。這是確保整個系統功能正確運作的關鍵。"
|
||||
},
|
||||
{
|
||||
"level": "critical",
|
||||
"role": "Maya",
|
||||
"location": "entrypoint.sh",
|
||||
"suggestion": "此 Git Diff 引入了多項邏輯改動,但未見任何新增或修改的測試檔案。對於核心的 `entrypoint.sh` 腳本,應引入一個專用的測試框架(例如 Bats 或 shUnit2),並建立一套全面的單元測試與整合測試,以確保所有功能按預期運作,特別是對於錯誤處理和邊界條件的驗證。"
|
||||
},
|
||||
{
|
||||
"level": "warning",
|
||||
"role": "Zara",
|
||||
"location": "entrypoint.sh:56",
|
||||
"suggestion": "目前的健康檢查機制中,`curl` 的最大等待時間 (`--max-time 60`) 和重試間隔 (`sleep 60`) 都固定為 60 秒。這導致每次檢查失敗後,至少需要 120 秒才能進行下一次嘗試,大幅降低了健康檢查的響應速度。建議將這些時間參數設定為可配置的環境變數 (例如 `CURL_TIMEOUT` 和 `RETRY_INTERVAL`),以便根據實際應用場景調整。對於需要快速偵測服務狀態變化的情境,應考慮縮短這些時間。"
|
||||
},
|
||||
{
|
||||
"level": "warning",
|
||||
"role": "Rex",
|
||||
"location": "Dockerfile:10",
|
||||
"suggestion": "Dockerfile 中複製了 `rootCA.pem` 和 `jsc.idv.me+4.pem` 到容器中。請確保這些檔案僅包含公開的憑證資料,不包含任何私鑰或其他敏感資訊。若這些檔案包含私鑰,則會構成嚴重的安全漏洞。建議在 CI/CD 流程中增加檢查,確保這些檔案的內容符合預期。"
|
||||
},
|
||||
{
|
||||
"level": "warning",
|
||||
"role": "Leo",
|
||||
"location": "entrypoint.sh",
|
||||
"suggestion": "建議在檔案末尾添加一個空行。這是一個常見的 Unix 慣例,可以避免某些工具在處理檔案時產生非預期的行為。"
|
||||
},
|
||||
{
|
||||
"level": "warning",
|
||||
"role": "Aria",
|
||||
"location": "Dockerfile:15",
|
||||
"suggestion": "檔案末尾應包含一個空行,以符合 POSIX 規範並避免某些工具處理時產生問題。"
|
||||
},
|
||||
{
|
||||
"level": "info",
|
||||
"role": "Rex",
|
||||
"location": "entrypoint.sh:70",
|
||||
"suggestion": "將變數寫入 `$GITHUB_OUTPUT` 時,雖然此處 `status_code` 為數字,風險較低,但一般而言,應確保寫入的內容經過適當的清理或編碼,以防止潛在的命令注入風險。如果變數內容來自不受信任的輸入或包含特殊字元(例如換行符),可能會被 GitHub Actions 解釋為新的輸出變數或指令。"
|
||||
},
|
||||
{
|
||||
"level": "info",
|
||||
"role": "Leo",
|
||||
"location": "Dockerfile",
|
||||
"suggestion": "在 Dockerfile 中,部分描述性註解被移除。雖然指令本身清晰且符合 Dockerfile 簡潔的趨勢,但對於不熟悉此映像檔用途或 Dockerfile 最佳實踐的開發者來說,簡潔的註解(例如說明為何複製特定憑證或更新 CA 證書的目的)可以提高首次閱讀時的理解性。建議考慮在關鍵步驟旁添加簡要註解,以平衡簡潔性與可讀性。"
|
||||
},
|
||||
{
|
||||
"level": "info",
|
||||
"role": "Maya",
|
||||
"location": "Dockerfile",
|
||||
"suggestion": "雖然 Dockerfile 本身不是應用程式程式碼,但其建置過程和最終映像檔的品質對整體系統至關重要。建議導入 Docker 映像檔建置測試工具(例如 Hadolint 進行靜態分析,或 Container Structure Test 進行運行時驗證),以確保映像檔的安全性、效率和正確性,例如檢查是否安裝了所有必要的工具,以及證書是否正確配置。"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
- 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:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
name: AI
|
||||
on:
|
||||
pull_request:
|
||||
branches-ignore:
|
||||
- master
|
||||
types: [opened, synchronize]
|
||||
jobs:
|
||||
code-review:
|
||||
@@ -10,6 +12,8 @@ jobs:
|
||||
- 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 }}
|
||||
|
||||
@@ -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`.
|
||||
@@ -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`.
|
||||
@@ -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`.
|
||||
+4
-10
@@ -1,21 +1,15 @@
|
||||
FROM ubuntu:latest
|
||||
FROM ubuntu:24.04
|
||||
|
||||
# 更新並安裝必要的工具後清理暫存檔案以減小映像檔大小
|
||||
RUN apt update \
|
||||
&& apt install -y curl \
|
||||
&& apt clean \
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 複製私人證書到容器中
|
||||
COPY rootCA.pem /usr/local/share/ca-certificates/rootCA.crt
|
||||
COPY jsc.idv.me+4.pem /usr/local/share/ca-certificates/jsc.idv.me+4.crt
|
||||
|
||||
# 複製入口腳本到容器中
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
# 更新 CA 證書以確保系統信任新的證書
|
||||
RUN update-ca-certificates
|
||||
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
|
||||
@@ -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`.
|
||||
+59
-25
@@ -1,46 +1,80 @@
|
||||
#!/bin/bash
|
||||
set -u
|
||||
|
||||
# 當 GitHub Actions 手動取消 workflow 時,Runner 會對容器送出終止訊號。
|
||||
# 透過 trap 可在收到訊號時立即退出,避免無限迴圈持續重試。
|
||||
timestamp() {
|
||||
date -u +"%Y-%m-%dT%H:%M:%SZ"
|
||||
}
|
||||
|
||||
log() {
|
||||
printf '[%s] %s\n' "$(timestamp)" "$1"
|
||||
}
|
||||
|
||||
section() {
|
||||
printf '\n==================================================\n'
|
||||
printf '%s\n' "$1"
|
||||
printf '%s\n' '--------------------------------------------------'
|
||||
}
|
||||
|
||||
fail() {
|
||||
log "[ERROR] $1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 當 workflow 被取消時,立即結束,避免健康檢查持續重試。
|
||||
on_terminate() {
|
||||
echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] 收到取消訊號,停止健康檢查。"
|
||||
log "[WARN] 收到取消訊號,停止健康檢查。"
|
||||
exit 130
|
||||
}
|
||||
|
||||
trap on_terminate TERM INT
|
||||
|
||||
echo "=================================================="
|
||||
HEALTH_CODE="${HEALTH_CODE:-200}"
|
||||
|
||||
echo "參數檢查"
|
||||
section "參數檢查"
|
||||
if [ -z "${CHECK_URL:-}" ] || [ "$CHECK_URL" = "null" ]; then
|
||||
fail "CHECK_URL 不可為空。"
|
||||
fi
|
||||
|
||||
echo "--------------------------------------------------"
|
||||
if [ -z "$HEALTH_CODE" ] || [ "$HEALTH_CODE" = "null" ]; then
|
||||
fail "HEALTH_CODE 不可為空。"
|
||||
fi
|
||||
|
||||
# 顯示 CHECK_URL 參數,並檢查是否為空或 "null",如果是則輸出錯誤訊息並退出
|
||||
echo "CHECK_URL=$CHECK_URL" && ([ -z "$CHECK_URL" ] || [ "$CHECK_URL" = "null" ]) && exit 1
|
||||
case "$CHECK_URL" in
|
||||
http://*|https://*) ;;
|
||||
*)
|
||||
fail "CHECK_URL 只允許 http:// 或 https://。"
|
||||
;;
|
||||
esac
|
||||
|
||||
# 顯示 HEALTH_CODE 參數,並檢查是否為空或 "null",如果是則輸出錯誤訊息並退出
|
||||
echo "HEALTH_CODE=$HEALTH_CODE" && ([ -z "$HEALTH_CODE" ] || [ "$HEALTH_CODE" = "null" ]) && exit 1
|
||||
log "[INFO] CHECK_URL=$CHECK_URL"
|
||||
log "[INFO] HEALTH_CODE=$HEALTH_CODE"
|
||||
|
||||
echo "=================================================="
|
||||
section "取得狀態碼"
|
||||
log "[INFO] 開始檢查:$CHECK_URL"
|
||||
|
||||
echo "取得狀態碼"
|
||||
|
||||
echo "--------------------------------------------------"
|
||||
|
||||
# 使用無窮迴圈持續嘗試,直到成功取得有效狀態碼
|
||||
while true; do
|
||||
echo -n "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] $CHECK_URL ... "
|
||||
printf '[%s] [INFO] GET %s ... ' "$(timestamp)" "$CHECK_URL"
|
||||
|
||||
# 使用 curl 取得狀態碼,最長等待 60 秒,並將結果輸出到環境變數 STATUS_CODE
|
||||
STATUS_CODE=$(curl -s --max-time 60 -o /dev/null -w "%{http_code}" "$CHECK_URL")
|
||||
status_code="$(curl -sS --proto '=http,https' --proto-redir '=http,https' --max-time 60 --url "$CHECK_URL" -o /dev/null -w '%{http_code}' || true)"
|
||||
if [ -z "$status_code" ]; then
|
||||
status_code="000"
|
||||
fi
|
||||
|
||||
echo "$STATUS_CODE" && [ "$STATUS_CODE" == "$HEALTH_CODE" ] && break
|
||||
printf '%s\n' "$status_code"
|
||||
|
||||
# 如果狀態碼為 "000",表示連線失敗,等待 60 秒後重試
|
||||
if [ "$status_code" = "$HEALTH_CODE" ]; then
|
||||
log "[OK] 狀態碼符合預期:$status_code"
|
||||
break
|
||||
fi
|
||||
|
||||
log "[WARN] 目前狀態碼 $status_code,預期 $HEALTH_CODE,60 秒後重試。"
|
||||
sleep 60
|
||||
done
|
||||
|
||||
echo "=================================================="
|
||||
|
||||
# 將狀態碼輸出到環境變數
|
||||
echo "status_code=$STATUS_CODE" >> "$GITHUB_OUTPUT"
|
||||
section "完成"
|
||||
log "[INFO] 輸出 status_code=$status_code"
|
||||
if [ -n "${GITHUB_OUTPUT:-}" ]; then
|
||||
echo "status_code=$status_code" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
log "[WARN] GITHUB_OUTPUT 未設定,略過寫入輸出檔。"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user