Files
awoooi/docs/superpowers/specs/2026-04-05-gitea-webhook-migration-design.md
OG T 5cd67d372f docs(spec): ADR-059 Gitea Webhook 遷移設計規格
從 GitHub Webhook (Phase 13.1) 遷移至 Gitea Webhook
最少改動策略:Header 常數替換,業務邏輯層不動
廢棄 workflow_run CI 診斷(CD pipeline 已有 TG 通知覆蓋)
整合首席架構師護欄:防禦性 payload 解析 + Content-Type 設定

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 14:17:13 +08:00

6.0 KiB
Raw Blame History

Gitea Webhook 整合設計規格

日期: 2026-04-05 (台北時區)
作者: Claude Code + 首席架構師 Review
狀態: 已批准,待實作
ADR: ADR-059 (待建立)
關聯: ADR-039 (Gitea CI/CD 遷移), ADR-029 (CI/CD AI 整合架構)


背景

Phase 13.1 實作了 GitHub Webhook → OpenClaw AI 代碼審查整合,但:

  1. CI/CD 已於 ADR-039 全面遷移至 GiteaGitHub 只剩唯讀備份
  2. GITHUB_WEBHOOK_SECRET 從未注入 K8s Secrets功能實際上處於死路狀態
  3. 代碼審查的觸發源應改為 Gitea實際開發倉庫

決策:遷移至 Gitea Webhook廢棄 GitHub Webhook 整合。


設計原則

最少改動策略 (Minimal Viable Change)

Gitea 與 GitHub 的 webhook payload 欄位幾乎相同,差異只在 HTTP header 名稱。 因此策略是:重命名 + Header 常數替換業務邏輯層OpenClaw 呼叫、Redis 儲存、Telegram 通知、Approval 建立)完全不動。


Header 差異對照

項目 GitHub (廢棄) Gitea (新)
事件類型 Header X-GitHub-Event X-Gitea-Event
簽章 Header X-Hub-Signature-256 X-Gitea-Signature
投遞 ID Header X-GitHub-Delivery X-Gitea-Delivery
簽章格式 sha256=<hex> sha256=<hex>相同
Payload 欄位 — ← 幾乎相同

Gitea 會同時送出 X-GitHub-Event 相容 header但我們應讀取原生的 X-Gitea-Event 語意清晰,未來不依賴相容層。


遷移範圍

支援事件

事件 GitHub (舊) Gitea (新) 說明
pull_request 遷移 PR 代碼審查
push 遷移 主分支推送審查
workflow_run 廢棄 CD pipeline 已有 TG 通知,重複覆蓋無必要
ping 遷移 連線測試

檔案變更清單

檔案 動作 說明
src/api/v1/github_webhook.py 重命名 → gitea_webhook.py Header 常數改 Gitea移除 workflow_run handler
src/services/github_webhook_service.py 重命名 → gitea_webhook_service.py 移除 diagnose_ci_failure()class 改名
src/main.py 修改 更新 import掛載路徑改 /webhooks/gitea
src/core/config.py 修改 GITHUB_WEBHOOK_SECRETGITEA_WEBHOOK_SECRETGITHUB_ALLOWED_REPOSGITEA_ALLOWED_REPOS
k8s/awoooi-prod/03-secrets.yaml 修改 新增 GITEA_WEBHOOK_SECRET,移除 GITHUB_WEBHOOK_SECRET
tests/conftest.py 修改 更新 env var 名稱
tests/test_github_webhook.py 重命名 → test_gitea_webhook.py Header 常數改 Gitea
docs/adr/ADR-059-gitea-webhook-integration.md 新增 決策記錄

API 端點

舊: POST /api/v1/webhooks/github
新: POST /api/v1/webhooks/gitea

舊: GET  /api/v1/webhooks/github/reviews/{review_id}
新: GET  /api/v1/webhooks/gitea/reviews/{review_id}

Config 變更

# 舊 (廢棄)
GITHUB_WEBHOOK_SECRET: str = Field(default="")
GITHUB_ALLOWED_REPOS: str = Field(default="")

# 新
GITEA_WEBHOOK_SECRET: str = Field(
    default="",
    description="Gitea Webhook secret for HMAC-SHA256 signature verification (X-Gitea-Signature)",
)
GITEA_ALLOWED_REPOS: str = Field(
    default="wooo/awoooi",
    description="Comma-separated list of allowed Gitea repositories (e.g., 'wooo/awoooi')",
)

防禦性 Payload 解析(首席架構師護欄 #1

Gitea 部分欄位為 nullable 或可能缺失。所有欄位存取使用 .get() chain禁止直接 key access

# ❌ 禁止
repo_name = payload["repository"]["full_name"]

# ✅ 正確
repo_name = payload.get("repository", {}).get("full_name", "")
pr_number = payload.get("pull_request", {}).get("number", 0)
head_sha = payload.get("pull_request", {}).get("head", {}).get("sha", "")

現有 github_webhook_service.py 中已部分採用此模式,遷移時需全面審查確認。


Gitea UI 設定步驟(首席架構師護欄 #2

部署完成後在 Gitea 設定 Webhook

  1. 進入 http://192.168.0.110:3001/wooo/awoooi → Settings → Webhooks → Add Webhook → Gitea
  2. Target URL: https://awoooi.wooo.work/api/v1/webhooks/gitea
  3. HTTP Method: POST
  4. Content Type: application/json必須明確選擇,否則 FastAPI 無法解析
  5. Secret: 與 GITEA_WEBHOOK_SECRET K8s Secret 值相同
  6. Trigger On: Pull Request events + Push events
  7. Active: 勾選

⚠️ Content-Type 若選 application/x-www-form-urlencodedFastAPI 的 Request.json() 將無法解析,導致所有 webhook 請求失敗。


簽章驗證邏輯

驗證邏輯與 GitHub 完全相同,只需更換 header 名稱:

# 舊 header
x_hub_signature_256: str | None = Header(default=None, alias="X-Hub-Signature-256")

# 新 header
x_gitea_signature: str | None = Header(default=None, alias="X-Gitea-Signature")

HMAC-SHA256 計算方式不變:sha256=<hmac_sha256(secret, body).hexdigest()>


K8s Secrets 注入

k8s/awoooi-prod/03-secrets.yaml 新增:

GITEA_WEBHOOK_SECRET: "CHANGE_ME"  # CD 自動注入

cd.yamlInject K8s Secrets step 需新增注入:

kubectl patch secret awoooi-secrets \
  --patch "{\"stringData\": {\"GITEA_WEBHOOK_SECRET\": \"${{ secrets.GITEA_WEBHOOK_SECRET }}\"}}"

Gitea Actions secrets 需新增 GITEA_WEBHOOK_SECRET


測試策略

test_gitea_webhook.py 複用現有 8 個測試案例,更新:

  1. Header 名稱:X-Hub-Signature-256X-Gitea-SignatureX-GitHub-EventX-Gitea-Event
  2. Router importfrom src.api.v1.gitea_webhook import router as gitea_webhook_router
  3. conftest.pyGITHUB_WEBHOOK_SECRETGITEA_WEBHOOK_SECRETGITHUB_ALLOWED_REPOSGITEA_ALLOWED_REPOS

不在此 Scope

  • Gitea 端實際 webhook secret 的生成與管理(統帥決定)
  • workflow_run 等值替代方案(未來 Phase 規劃)
  • GitHub mirror repo 的 webhook 設定清除(可手動處理)