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