feat(webhook): ADR-059 GitHub → Gitea Webhook 遷移完成

- gitea_webhook.py: Header 全部改 X-Gitea-*,移除 workflow_run handler
- gitea_webhook_service.py: _fetch_pr_diff 改直接 httpx,不依賴 github_api_service
- 清除兩個檔案的所有殘留 github_ log key,review_id prefix 改 gitea-
- test_gitea_webhook.py: 10/10 通過,docstring 修正
- 03-secrets.yaml: 新增 GITEA_WEBHOOK_SECRET 佔位
- cd.yaml: 新增 GITEA_WEBHOOK_SECRET 注入步驟
- ADR-059: 建立架構決策文件

待統帥操作: Gitea Actions secret + Gitea UI Webhook 設定

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-04-05 14:44:32 +08:00
parent b2c0148f2b
commit 23364423fa
7 changed files with 218 additions and 1771 deletions

View File

@@ -0,0 +1,110 @@
# ADR-059: Gitea Webhook 整合 (GitHub → Gitea 遷移)
**日期**: 2026-04-05 (台北時區)
**狀態**: ✅ 已批准
**決策者**: 首席架構師 + 統帥
---
## 背景
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 常數替換,業務邏輯層完全不動。
---
## 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 欄位 | — | — ← **幾乎相同** |
---
## 支援事件
| 事件 | 說明 |
|------|------|
| `pull_request` | PR 代碼審查 (opened/synchronize/reopened) |
| `push` | 主分支推送審查 |
| `ping` | 連線測試 |
| `workflow_run` | **廢棄** (CD pipeline 已有 Telegram 通知,重複覆蓋無必要) |
---
## 變更範圍
| 檔案 | 動作 |
|------|------|
| `src/api/v1/github_webhook.py` | 保留(歷史參考),不刪除 |
| `src/api/v1/gitea_webhook.py` | 新建Header 改 Gitea移除 workflow_run handler |
| `src/services/github_webhook_service.py` | 保留(歷史參考),不刪除 |
| `src/services/gitea_webhook_service.py` | 新建_fetch_pr_diff 改用直接 httpx不依賴 github_api_service |
| `src/main.py` | 掛載 gitea_webhook_router路徑 `/api/v1/webhooks/gitea` |
| `src/core/config.py` | 新增 `GITEA_WEBHOOK_SECRET``GITEA_ALLOWED_REPOS` |
| `k8s/awoooi-prod/03-secrets.yaml` | 新增 `GITEA_WEBHOOK_SECRET` 佔位 |
| `.gitea/workflows/cd.yaml` | 新增 `GITEA_WEBHOOK_SECRET` 注入步驟 |
| `tests/test_gitea_webhook.py` | 新建Header 改 Gitea |
| `tests/conftest.py` | `GITEA_WEBHOOK_SECRET``GITEA_ALLOWED_REPOS` 環境變數 |
---
## API 端點
```
新: POST /api/v1/webhooks/gitea
新: GET /api/v1/webhooks/gitea/reviews/{review_id}
舊: POST /api/v1/webhooks/github ← 仍掛載但未用
```
---
## 安全設計
- HMAC-SHA256 簽章驗證 (X-Gitea-Signature)
- Fail-Closed: 生產環境未設 `GITEA_WEBHOOK_SECRET` → 直接拒絕
- 倉庫白名單: `GITEA_ALLOWED_REPOS`(預設 `wooo/awoooi`
- 所有欄位存取使用 `.get()` chain防止 Gitea nullable 欄位 KeyError
---
## Gitea UI 設定
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. **Content Type**: `application/json` ← 必須明確選擇
4. **Secret**: 與 `GITEA_WEBHOOK_SECRET` K8s Secret 值相同
5. **Trigger On**: Pull Request events + Push events
---
## 後置待辦
- [ ] Gitea Actions secret `GITEA_WEBHOOK_SECRET` 設定(統帥操作)
- [ ] Gitea UI Webhook 設定(統帥操作)
- [ ] K8s Secret 手動 patch 首次注入
- [ ] E2E 驗證:觸發一次 PR → 收到 Telegram 代碼審查通知
---
## 參考
- ADR-039: Gitea CI/CD 遷移
- ADR-029: CI/CD AI 整合架構
- Phase 13.1: GitHub PR Review 原始實作