# ADR-059: Gitea Webhook 整合 (GitHub → Gitea 遷移)

**日期**: 2026-04-05 (台北時區)
**狀態**: ✅ 已批准
**決策者**: 首席架構師 + 統帥

---

## 背景

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

1. CI/CD 已於 ADR-039 全面遷移至 Gitea，GitHub 只剩唯讀備份
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 原始實作
