All checks were successful
Deploy Docusaurus Site / deploy (push) Successful in 34s
225 lines
8.6 KiB
Markdown
225 lines
8.6 KiB
Markdown
---
|
||
sidebar_position: 2
|
||
title: Issue 立てるだけで AI がコードレビュー&修正してくれる仕組みを作った
|
||
description: ローカルGiteaにWebhookブリッジを噛ませて、Issue/PRをトリガーにAIエージェントが自動でコードレビュー・修正・pushまでやってくれる環境を構築した話。
|
||
hide_table_of_contents: false
|
||
displayed_sidebar: null
|
||
image: ./banner.png
|
||
---
|
||
|
||
# Issue 立てるだけで AI がコードレビュー&修正してくれる仕組みを作った
|
||
|
||
## きっかけ
|
||
|
||
GitHub だと Copilot や GitHub Actions を使って、PR にレビューコメントつけたり自動テスト回したりできるよね。Devin みたいに Issue を投げたら勝手にコード書いてくれるサービスもある。
|
||
|
||
でもうちの開発環境は **ローカルの Gitea**。GitHub のエコシステムはそのままじゃ使えない。
|
||
|
||
「じゃあ同じことをローカルで再現すればいいじゃん」ということで、Gitea の Webhook と OpenClaw の AI エージェントを繋げて、**Issue 立てたら AI が勝手にレビューして修正して push してくれる** 仕組みを作った。
|
||
|
||
## 何ができるようになったか
|
||
|
||
こんな感じの開発フローが回ってる:
|
||
|
||
1. Gitea で Issue を立てる(「この関数のエラーハンドリングがザルだから直して」とか)
|
||
2. Webhook が飛んで、AI エージェント(GPT-5.3-codex)が起動
|
||
3. リポジトリをクローンして、Issue の内容に沿ってコードレビュー
|
||
4. 修正ブランチを切って、コード修正、push
|
||
5. Issue にコメントで結果報告(ブランチ名、何を直したか、マージ手順)
|
||
|
||
PR が来た時も同じようにレビューが走る。人間がやるのは **Issue を書くことと、最後にマージするかどうか判断するだけ**。
|
||
|
||
## 全体の構成
|
||
|
||
```
|
||
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つだけ:
|
||
|
||
- **Gitea** — セルフホストの Git サーバー
|
||
- **Webhook Bridge** — Gitea のイベントを受けて AI を起動する Python スクリプト
|
||
- **OpenClaw + Codex エージェント** — 実際にコードを読んで直す AI
|
||
|
||
## Webhook Bridge の中身
|
||
|
||
ブリッジ自体はシンプルな Python の HTTP サーバー。Gitea からの Webhook を受けて、OpenClaw の codex エージェントにタスクを投げるだけ。
|
||
|
||
```python title="bridge.py(抜粋)"
|
||
class WebhookHandler(BaseHTTPRequestHandler):
|
||
def do_POST(self):
|
||
if self.path == "/webhook/gitea":
|
||
return self.handle_gitea_webhook()
|
||
|
||
def handle_gitea_webhook(self):
|
||
# 1. 署名検証
|
||
# 2. イベント種別チェック (issues / pull_request / issue_comment)
|
||
# 3. タスク文を組み立て
|
||
# 4. openclaw agent を非同期で起動
|
||
# 5. すぐに 200 OK を返す
|
||
```
|
||
|
||
### 対応しているイベント
|
||
|
||
| イベント | アクション | やること |
|
||
|---------|-----------|---------|
|
||
| Issue 作成 | `opened` | コードレビュー&修正 |
|
||
| Issue コメント | `created` | コメントの依頼に対応 |
|
||
| PR 作成/更新 | `opened` / `reopened` / `synchronize` | PR レビュー |
|
||
|
||
Issue へのコメントも拾えるようにしてるから、「ここもう少し直して」みたいな追加指示もそのまま通る。
|
||
|
||
### ボットのコメントは無視する
|
||
|
||
これ忘れると無限ループになる。AI がコメント → Webhook 発火 → AI がまたコメント → ...
|
||
|
||
```json title="config.json"
|
||
{
|
||
"bot_user": "koide",
|
||
"ignore_comment_users": ["koide"]
|
||
}
|
||
```
|
||
|
||
AI エージェントが使う Gitea アカウント名を `ignore_comment_users` に入れておけば OK。
|
||
|
||
## Gitea 側の設定
|
||
|
||
### 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"
|
||
[webhook]
|
||
ALLOWED_HOST_LIST = private
|
||
```
|
||
|
||
これを忘れると Webhook が一切飛ばないから、最初にやっておくこと。
|
||
|
||
## systemd で常駐させる
|
||
|
||
```ini title="/etc/systemd/system/gitea-webhook-bridge.service"
|
||
[Unit]
|
||
Description=Gitea Webhook Bridge for OpenClaw
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=swallow
|
||
WorkingDirectory=/home/swallow/gitea-webhook-bridge
|
||
EnvironmentFile=/home/swallow/gitea-webhook-bridge/.env
|
||
ExecStart=/usr/bin/python3 bridge.py
|
||
Restart=always
|
||
RestartSec=5
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
```bash
|
||
sudo systemctl enable --now gitea-webhook-bridge
|
||
```
|
||
|
||
`Restart=always` にしてるから、万が一落ちても勝手に復帰する。
|
||
|
||
## ハマったところ
|
||
|
||
### Webhook Bridge の実装
|
||
|
||
正直、ブリッジ自体も vibe コーディングで AI に作ってもらった。「Gitea の Webhook 受けて OpenClaw のエージェント起動するブリッジ書いて」って投げたらだいたい動くものが出てきた。
|
||
|
||
ただ、いくつかハマりポイントはあった:
|
||
|
||
**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 へのマージ手順
|
||
|
||
Git に不慣れでも、コメントをコピペすれば OK な状態になってるのが地味にありがたい。
|
||
|
||
## 実際の使用感
|
||
|
||
普段の開発では、ちょっとした修正や改善は Issue を立てるだけで回ってる。人間がやるのは:
|
||
|
||
- Issue を書く(日本語で OK)
|
||
- 修正結果を確認する
|
||
- マージするかどうか判断する
|
||
|
||
体感として、**コードレビュー+修正の作業時間が 8 割くらい減った**。特に「このへん直して」みたいなざっくりした指示でもちゃんとコード読んで対応してくれるのがいい。
|
||
|
||
もちろん的外れなこともあるけど、その時は Issue にコメントで「そうじゃなくてこうして」って返せばまた対応してくれる。
|
||
|
||
## 今後やりたいこと
|
||
|
||
- `ai-review` ラベルが付いた Issue だけ処理する(全 Issue に反応するのは過剰)
|
||
- レビュー結果の品質スコアリング
|
||
- 失敗時の自動リトライと通知
|
||
|
||
## まとめ
|
||
|
||
GitHub の Copilot や Devin みたいな「AI が開発を手伝ってくれる」体験を、ローカルの Gitea 環境でも再現できた。仕組み自体はシンプルで、Webhook Bridge の Python スクリプト 1 本と、OpenClaw のエージェント設定だけ。
|
||
|
||
ローカル AI 開発に興味がある人は、まず Issue → AI レビューの一本道から始めてみるといいと思う。それだけでも十分便利。
|
||
|
||
## 参考リンク
|
||
|
||
- [Gitea 公式ドキュメント](https://docs.gitea.com/)
|
||
- [OpenClaw](https://github.com/openclaw/openclaw)
|
||
|
||
---
|
||
|
||
*この記事は2026年3月時点の情報です。*
|