簡介
這是一個 AI Code Review Action。Gitea Workflow 可以使用此 Action 讓 AI 助理根據不同面向分析 Push Request 中變更的內容後,將問題分級 Commnet 到 Push Request 中。
流程(新 Push Request、新 Commit 觸發;若偵測到 AI 助理的自動提交則直接跳過)
- 服務名稱、模型名稱、角色資訊(個性、符合個性的英文名稱、工作內容),Comment 到 Push Request
- 每個角色個別分析 Git Diff 的內容產生新問題表格(問題等級、角色名稱、問題位置或行數、修改建議)
- 讀取來源分支中的所有未解決舊問題(問題檔案
.gitea/ai-review/findings.json)加上新問題後,去除重複產生本次 Push Request 的問題表格(PR問題表格)覆蓋問題檔案 - 讀取來源分支中的排除問題檔案(
.gitea/ai-review/exclusions.json),用來過濾PR問題表格中不需要處理的問題 - 從PR問題表格中取出所有舊問題,依照等級排序後 Comment 到 Push Request
- 從PR問題表格中取出所有新問題,排除嚴重等級的問題後 Comment 到 Push Request
- 從PR問題表格中取出所有新問題,將每個嚴重等級的問題 Comment 到 Push Request
- Commit 問題檔案,將 workspace 中實際存在的同步檔覆蓋到記憶區;workspace 沒有的同步檔就略過,不會刪除記憶區既有內容。自動提交的 commit message 會帶上
[ai-review-bot],供 workflow 判斷是否要跳過重跑 - 如果 PR 問題表格中有嚴重問題,則不要讓 workflow 執行成功(exit 1)
設計
- Gitea 的相關參數如果 inputs 沒有定義,則從 ${{ gitea.* }} 取得
- BASE_URL 如果 inputs 沒有定義,則使用預設值
- Comment 加上些許 emoji 讓資訊有點活力
- 盡量將應用程式放在 ./app,修改 entrypoint.sh 與 Dockerfile 讓程式可以正常運行
- 將提示詞放到 ./app/prompts 內供程式讀取
- API Key 支援逗號分隔傳入多個,隨機順序各嘗試一次,全部失敗則 exit 1
- 讀取 Git Diff 時排除
.gitea/、.amazonq/、.claude/、.codex/、.gemini/、.github/資料夾,以及CLAUDE.md、GEMINI.md、TODO.md、README.md,避免 AI 分析 workflow 設定、skill 入口與文件等非業務程式碼 - 階段七驗證來源分支中的
findings.json與exclusions.json是否為合法 JSON 格式,格式錯誤時先嘗試透過 AI 修正內容,再重新驗證;修正後仍不合法才 exit 1;之後才檢查檔案是否存在,不存在則建立並寫入[] - 傳給 AI 的 findings 只保留必要欄位(level、role、location、suggestion),排除
is_new等內部欄位;system prompt 精簡為指令核心;exclusions hint 只傳 location 與 suggestion,減少 token 用量 - 執行時會額外記錄來源分支狀態、
findings.json/exclusions.json的檔案路徑、大小、mtime 與 raw/normalized 筆數,方便追查讀檔與分支內容不一致的問題
使用說明
- 在 Gitea 專案中建立
.gitea/workflows資料夾 - 在
.gitea/workflows資料夾中建立 `ai-review.yaml' - 在
ai-review.yaml中填入以下內容(選擇一個使用):
自動提交排除說明:此 Action 會將自己的 commit message 標記為
[ai-review-bot][success]或[ai-review-bot][failure],而且 action 執行時會先透過 Gitea API 檢查這次觸發的 PR head commit(優先用pull_request.head.sha)是否含有這個 marker,若有就直接成功結束,避免 bot commit 造成重複觸發。若外層 workflow 也能先檢查一次,效果最好。
權限說明:此 Action 需要
contents: write(寫入 findings.json)、pull-requests: write(發佈 PR comment)、issues: write(發佈 issue comment)三項權限,為正常運作所必要,無法縮減。若你想讓 comment 用不同權限的 token,可額外傳GITEA_COMMENT_TOKEN,其餘 Gitea 操作仍使用GITEA_TOKEN。
1. OpenAI
name: AI
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
cancel-in-progress: true
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 }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} # 支援逗號分隔多個 Key
OPENAI_BASE_URL: https://api.openai.com/v1
OPENAI_MODEL: ${{ vars.OPENAI_MODEL }}
permissions:
contents: write
pull-requests: write
issues: write
2. OpenRouter
name: AI
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
cancel-in-progress: true
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 }}
OPENAI_API_KEY: ${{ secrets.OPENROUTER_API_KEY }},${{ secrets.OPENROUTER_API_KEY_1 }}
OPENAI_BASE_URL: https://openrouter.ai/api/v1
OPENAI_MODEL: ${{ vars.OPENROUTER_MODEL }}
permissions:
contents: write
pull-requests: write
issues: write
3. Anthropic Claude
name: AI
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
cancel-in-progress: true
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 }}
CLAUDE_API_KEY: ${{ secrets.CLAUDE_API_KEY }} # 支援逗號分隔多個 Key
CLAUDE_BASE_URL: https://api.anthropic.com/v1
permissions:
contents: write
pull-requests: write
issues: write
4. Google Gemini
name: AI
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
cancel-in-progress: true
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 }}
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
5. Amazon Q
name: AI
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
cancel-in-progress: true
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 }}
AMAZONQ_API_KEY: ${{ secrets.AMAZONQ_API_KEY }} # 支援逗號分隔多個 Key
AMAZONQ_BASE_URL: https://q.api.aws
permissions:
contents: write
pull-requests: write
issues: write
- Ollama
name: AI
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
cancel-in-progress: true
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 }}
OLLAMA_BASE_URL: https://ollama.jsc.idv.me/v1
OLLAMA_MODEL: ${{ vars.OLLAMA_MODEL }}
permissions:
contents: write
pull-requests: write
issues: write
Skill:Triage Findings
這份 skill 用來處理 review 問題清單。
規則
- 合併問題。
- 依嚴重度排序:
critical->warning->info。 - 重新編號。
- 真問題就修。
- 誤判就加到
.gitea/ai-review/exclusions.json。 - 有變更就補測試。
使用方式
Codex:$triage-findings 問題原始檔(文字或截圖)
Copilot:/triage-findings 問題原始檔(文字或截圖)
Claude:直接輸入 triage-findings 問題原始檔(文字或截圖)
Gemini:直接輸入 triage-findings 問題原始檔(文字或截圖)
Amazon Q:直接輸入 triage-findings 問題原始檔(文字或截圖)
適用情境
triage-findings 問題原始檔(文字或截圖) 用在 review 問題整併、排序、修正、排除誤判。
版本包含
提交時一併包含 triage-findings skill 與各平台入口檔;已存在檔案一律覆蓋,同步到最新內容;若 workspace 沒有某個同步檔,記憶區會保留原檔,不做刪除。findings.json 與 exclusions.json 都從使用此 action 的存取庫來源分支讀取,而不是從 action 本地 workspace 讀取。寫入 .gitea/ai-review/exclusions.json 時,盡量保留原始問題文字的語言與語意,避免過度改寫。未來若新增任何 skill 或新增其他平台的 skill 入口,必須同時把對應檔案複製進 Docker image,並把同步清單更新到會使用此 action 的目標專案,避免 action 與目標專案內容脫節。