Rewrite: Gitea Webhook AI Review 記事リライト
All checks were successful
Deploy Docusaurus Site / deploy (push) Successful in 34s

This commit is contained in:
koide 2026-03-02 02:53:57 +00:00
parent 9567c5149b
commit bdab8f3d8a

View File

@ -1,127 +1,122 @@
--- ---
sidebar_position: 2 sidebar_position: 2
title: ローカルGitea × Webhook連携で、AIとの開発をもっと楽にしよう title: Issue 立てるだけで AI がコードレビュー&修正してくれる仕組みを作った
description: GiteaのIssue/PR WebhookとOpenClawを連携し、実運用で壊れにくく回す開発プロセスを構築する実践記録 description: ローカルGiteaにWebhookブリッジを噛ませて、Issue/PRをトリガーにAIエージェントが自動でコードレビュー・修正・pushまでやってくれる環境を構築した話。
hide_table_of_contents: false hide_table_of_contents: false
displayed_sidebar: null displayed_sidebar: null
image: ./banner.png image: ./banner.png
--- ---
# ローカルGitea × Webhook連携で、AIとの開発をもっと楽にしよう # Issue 立てるだけで AI がコードレビュー&修正してくれる仕組みを作った
## はじめに ## きっかけ
「Issue を立てるだけで、AI がレビューして修正提案まで返してくれたら最高なのに…」 GitHub だと Copilot や GitHub Actions を使って、PR にレビューコメントつけたり自動テスト回したりできるよね。Devin みたいに Issue を投げたら勝手にコード書いてくれるサービスもある。
そんな願望から始めたのが、**Gitea Webhook → OpenClaw** の自動レビュー連携です。 でもうちの開発環境は **ローカルの Gitea**。GitHub のエコシステムはそのままじゃ使えない。
最初は「Issue 作成でAIを呼べればOK」と思っていたのですが、実運用に入るとすぐに壁に当たりました。
- `EOF` でWebhookが落ちる 「じゃあ同じことをローカルで再現すればいいじゃん」ということで、Gitea の Webhook と OpenClaw の AI エージェントを繋げて、**Issue 立てたら AI が勝手にレビューして修正して push してくれる** 仕組みを作った。
- PRを投げても `OK (ignored event)`
- ブリッジの別機能改修で本線が壊れる
- Gitが苦手なメンバーがブランチ運用で詰まる
この記事は、その失敗込みで最終的に安定した **運用可能な形** をまとめたものです。 ## 何ができるようになったか
## この記事でわかること こんな感じの開発フローが回ってる:
- Issue / PR の両方をトリガーにする Webhook 設計 1. Gitea で Issue を立てる(「この関数のエラーハンドリングがザルだから直して」とか)
- bridge.py の実装で絶対外せない防御ポイント 2. Webhook が飛んで、AI エージェントGPT-5.3-codexが起動
- systemd での安定運用 3. リポジトリをクローンして、Issue の内容に沿ってコードレビュー
- 壊れにくいブランチ運用Git弱者向け手順を毎回添える 4. 修正ブランチを切って、コード修正、push
- 機能混在で壊れたときの再発防止(リポジトリ分離 5. Issue にコメントで結果報告(ブランチ名、何を直したか、マージ手順
## 全体構成(最新版) PR が来た時も同じようにレビューが走る。人間がやるのは **Issue を書くことと、最後にマージするかどうか判断するだけ**
## 全体の構成
``` ```
┌─────────┐ Webhook (issues / pull_request) ┌────────────────────┐ Gitea (Issue/PR作成)
│ Gitea │ ────────────────────────────────────→ │ gitea-webhook-bridge │
└─────────┘ │ bridge.py │
└────────┬──────────┘
openclaw agent │ Webhook (POST /webhook/gitea)
gitea-webhook-bridge (Python, port 9876)
code-review-loop │ openclaw agent --agent codex
OpenClaw Codex エージェント (GPT-5.3-codex)
Issue/PRコメントで返却 │ code-review-loop スキル
レビュー → 修正 → push → Issue にコメント
``` ```
## なぜ最初に壊れたのか(実話) 登場人物は3つだけ
### 1) `EOF` でDelivery失敗 - **Gitea** — セルフホストの Git サーバー
- **Webhook Bridge** — Gitea のイベントを受けて AI を起動する Python スクリプト
- **OpenClaw + Codex エージェント** — 実際にコードを読んで直す AI
原因は、Gitea側ではなく受信側でした。`do_POST` 内で例外が出ているのに、HTTPレスポンスを返さず接続が閉じる。 ## Webhook Bridge の中身
Giteaから見ると `Post ... EOF` です。
**対策:** ブリッジ自体はシンプルな Python の HTTP サーバー。Gitea からの Webhook を受けて、OpenClaw の codex エージェントにタスクを投げるだけ。
- `do_POST` 全体を `try/except` で囲む
- 例外時も `500` を必ず返す
### 2) PRが無視される ```python title="bridge.py抜粋"
class WebhookHandler(BaseHTTPRequestHandler):
def do_POST(self):
if self.path == "/webhook/gitea":
return self.handle_gitea_webhook()
Issue対応だけ先に作ると、PRイベントは素通りします。 def handle_gitea_webhook(self):
その結果 `OK (ignored event)` # 1. 署名検証
# 2. イベント種別チェック (issues / pull_request / issue_comment)
# 3. タスク文を組み立て
# 4. openclaw agent を非同期で起動
# 5. すぐに 200 OK を返す
```
**対策:** ### 対応しているイベント
- `issues` だけでなく `pull_request` も受理
- `opened / reopened / synchronize` を最低限処理
### 3) 別用途改修でブリッジが壊れる | イベント | アクション | やること |
|---------|-----------|---------|
| Issue 作成 | `opened` | コードレビュー&修正 |
| Issue コメント | `created` | コメントの依頼に対応 |
| PR 作成/更新 | `opened` / `reopened` / `synchronize` | PR レビュー |
Discord通知などを同じブリッジに混ぜると、修正の副作用でGitea連携が壊れやすい。 Issue へのコメントも拾えるようにしてるから、「ここもう少し直して」みたいな追加指示もそのまま通る
**対策:** ### ボットのコメントは無視する
- 役割ごとにリポジトリを分離
- `gitea-webhook-bridge`
- `discord-notify-bridge`
- systemdサービスも分離
## bridge.py の実装指針 これ忘れると無限ループになる。AI がコメント → Webhook 発火 → AI がまたコメント → ...
### 受けるイベント ```json title="config.json"
{
"bot_user": "koide",
"ignore_comment_users": ["koide"]
}
```
- `issues` AI エージェントが使う Gitea アカウント名を `ignore_comment_users` に入れておけば OK。
- `opened`
- `pull_request`
- `opened`
- `reopened`
- `synchronize`
### 最低限の処理順
1. 署名検証(`X-Gitea-Signature`
2. イベント種別チェック
3. アクションチェック
4. タスク本文を整形
5. `openclaw agent` を非同期起動
6. すぐに `200 OK` を返す
### 署名検証は必須
:::warning
ローカルネットワークでも署名検証は省略しない方が安全です。
Webhook URLを知っているだけで叩ける状態は避けましょう。
:::
## Gitea 側の設定 ## Gitea 側の設定
### `ALLOWED_HOST_LIST` を忘れない ### Webhook の登録
リポジトリの Settings → Webhooks → Add Webhook:
- **URL**: `http://<bridge-host>:9876/webhook/gitea`
- **Content Type**: `application/json`
- **Secret**: bridge 側の `.env` と一致させる
- **Trigger**: Issues / Pull Request にチェック
### プライベート IP への Webhook を許可する
デフォルトだと Gitea はプライベート IP への Webhook をブロックする。ローカル環境では `app.ini` に以下を追加:
```ini title="app.ini" ```ini title="app.ini"
[webhook] [webhook]
ALLOWED_HOST_LIST = private ALLOWED_HOST_LIST = private
``` ```
これを忘れると、プライベートIP向けWebhookがブロックされます。 これを忘れると Webhook が一切飛ばないから、最初にやっておくこと
### Webhookの基本値 ## systemd で常駐させる
- URL: `http://<bridge-host>:9876/webhook/gitea`
- Content-Type: `application/json`
- Secret: bridgeと一致
- Trigger: `issues`, `pull_request`
## systemd常駐再起動に強い構成
```ini title="/etc/systemd/system/gitea-webhook-bridge.service" ```ini title="/etc/systemd/system/gitea-webhook-bridge.service"
[Unit] [Unit]
@ -133,7 +128,7 @@ Type=simple
User=swallow User=swallow
WorkingDirectory=/home/swallow/gitea-webhook-bridge WorkingDirectory=/home/swallow/gitea-webhook-bridge
EnvironmentFile=/home/swallow/gitea-webhook-bridge/.env EnvironmentFile=/home/swallow/gitea-webhook-bridge/.env
ExecStart=/usr/bin/python3 /home/swallow/gitea-webhook-bridge/bridge.py ExecStart=/usr/bin/python3 bridge.py
Restart=always Restart=always
RestartSec=5 RestartSec=5
@ -142,85 +137,88 @@ WantedBy=multi-user.target
``` ```
```bash ```bash
sudo systemctl daemon-reload
sudo systemctl enable --now gitea-webhook-bridge sudo systemctl enable --now gitea-webhook-bridge
sudo systemctl status gitea-webhook-bridge
``` ```
## 開発プロセス(ここが本体) `Restart=always` にしてるから、万が一落ちても勝手に復帰する。
単にWebhookを動かすだけだと、チーム運用では破綻します。 ## ハマったところ
最終的に安定したのは、以下のルールを固定したからです。
### ルール1: ブランチ命名を固定 ### Webhook Bridge の実装
- `fix/issue-<番号>-<要約>` 正直、ブリッジ自体も vibe コーディングで AI に作ってもらった。「Gitea の Webhook 受けて OpenClaw のエージェント起動するブリッジ書いて」って投げたらだいたい動くものが出てきた。
- `feat/issue-<番号>-<要約>`
- `docs/issue-<番号>-<要約>`
### ルール2: Issueコメントに毎回「3点セット」 ただ、いくつかハマりポイントはあった:
- ブランチ切替手順 **1. EOF で Webhook が失敗する**
`do_POST` 内で例外が出た時に HTTP レスポンスを返さないと、Gitea 側から見ると `EOF` エラーになる。`try/except` で囲んで、例外時も必ず `500` を返すようにする。
```python
def do_POST(self):
try:
# 処理
except Exception as e:
self.send_response(500)
self.end_headers()
```
**2. PR イベントが無視される**
最初 Issue だけ対応して満足してたら、PR のレビューが走らなくて「あれ?」ってなった。`pull_request` イベントも明示的に受理する必要がある。
**3. 署名検証**
ローカルネットワークだからいいかと思って最初は省略してたけど、Webhook URL を知ってるだけで叩けちゃう状態はさすがにまずいので追加した。HMAC-SHA256 で検証してる。
## AI エージェントの動き
OpenClaw の codex エージェント(うちでは「小出君」と呼んでる)が実際にやってくれることは:
1. リポジトリを clone
2. Issue/PR の内容を読んで問題を把握
3. コードを読んでレビュー
4. 修正が必要ならブランチを切ってコード修正
5. push して Issue にコメント
コメントには毎回こういう情報を含めてくれる:
- 何を修正したか
- ブランチの切替手順(`git fetch && git switch fix/issue-123-xxx`
- 検証コマンド - 検証コマンド
- mainへの反映手順 - main へのマージ手順
これを毎回書くだけで、Gitに不慣れな人の詰まりが激減しました。 Git に不慣れでも、コメントをコピペすれば OK な状態になってるのが地味にありがたい
### ルール3: PRイベントでも同じフローでレビュー ## 実際の使用感
IssueだけでなくPRでもレビューが走ると、 普段の開発では、ちょっとした修正や改善は Issue を立てるだけで回ってる。人間がやるのは:
「修正は出たが最終反映前チェックが抜ける」問題を防げます。
## Git弱者向けテンプレコピペ用 - Issue を書く(日本語で OK
- 修正結果を確認する
- マージするかどうか判断する
### 1) 修正ブランチへ切替 体感として、**コードレビュー+修正の作業時間が 8 割くらい減った**。特に「このへん直して」みたいなざっくりした指示でもちゃんとコード読んで対応してくれるのがいい。
```bash もちろん的外れなこともあるけど、その時は Issue にコメントで「そうじゃなくてこうして」って返せばまた対応してくれる。
git fetch origin
git switch fix/issue-123-xxx
# 古いgitなら: git checkout fix/issue-123-xxx
```
### 2) 検証 ## 今後やりたいこと
```bash - `ai-review` ラベルが付いた Issue だけ処理する(全 Issue に反応するのは過剰)
python3 -m py_compile src/*.py app/*.py - レビュー結果の品質スコアリング
``` - 失敗時の自動リトライと通知
### 3) mainへ反映
```bash
git switch main
git pull origin main
git merge --no-ff fix/issue-123-xxx
git push origin main
```
### 4) 後片付け(任意)
```bash
git branch -d fix/issue-123-xxx
git push origin --delete fix/issue-123-xxx
```
## 今後の拡張
- ラベル付きIssueのみ処理`ai-review` など)
- PRへの自動レビューコメント整形
- 失敗時の自動再試行と通知
- レビュー結果のダッシュボード化
## まとめ ## まとめ
Gitea × OpenClaw 連携は、作るだけなら簡単です。 GitHub の Copilot や Devin みたいな「AI が開発を手伝ってくれる」体験を、ローカルの Gitea 環境でも再現できた。仕組み自体はシンプルで、Webhook Bridge の Python スクリプト 1 本と、OpenClaw のエージェント設定だけ。
でも、**壊れずに回す**には運用設計がすべてでした。
- Issue + PR イベント対応 ローカル AI 開発に興味がある人は、まず Issue → AI レビューの一本道から始めてみるといいと思う。それだけでも十分便利。
- EOF対策例外時も必ず応答
- ブリッジの責務分離
- ブランチ/手順テンプレの固定
この4点を押さえると、AI連携は実務で使えるレベルまで安定します。 ## 参考リンク
- [Gitea 公式ドキュメント](https://docs.gitea.com/)
- [OpenClaw](https://github.com/openclaw/openclaw)
--- ---
*この記事は2026年2月時点の情報です。*
*この記事は2026年3月時点の情報です。*