6.7 KiB
sidebar_position, title, description, hide_table_of_contents, displayed_sidebar
| sidebar_position | title | description | hide_table_of_contents | displayed_sidebar |
|---|---|---|---|---|
| 2 | ローカルGitea × Webhook連携で、AIとの開発をもっと楽にしよう! | GiteaのIssue/PR WebhookとOpenClawを連携し、実運用で壊れにくく回す開発プロセスを構築する実践記録 | false | null |
ローカルGitea × Webhook連携で、AIとの開発をもっと楽にしよう!
はじめに
「Issue を立てるだけで、AI がレビューして修正提案まで返してくれたら最高なのに…」
そんな願望から始めたのが、Gitea Webhook → OpenClaw の自動レビュー連携です。 最初は「Issue 作成でAIを呼べればOK」と思っていたのですが、実運用に入るとすぐに壁に当たりました。
EOFでWebhookが落ちる- PRを投げても
OK (ignored event) - ブリッジの別機能改修で本線が壊れる
- Gitが苦手なメンバーがブランチ運用で詰まる
この記事は、その失敗込みで最終的に安定した 運用可能な形 をまとめたものです。
この記事でわかること
- Issue / PR の両方をトリガーにする Webhook 設計
- bridge.py の実装で絶対外せない防御ポイント
- systemd での安定運用
- 壊れにくいブランチ運用(Git弱者向け手順を毎回添える)
- 機能混在で壊れたときの再発防止(リポジトリ分離)
全体構成(最新版)
┌─────────┐ Webhook (issues / pull_request) ┌────────────────────┐
│ Gitea │ ────────────────────────────────────→ │ gitea-webhook-bridge │
└─────────┘ │ bridge.py │
└────────┬──────────┘
│
openclaw agent
│
code-review-loop
│
Issue/PRコメントで返却
なぜ最初に壊れたのか(実話)
1) EOF でDelivery失敗
原因は、Gitea側ではなく受信側でした。do_POST 内で例外が出ているのに、HTTPレスポンスを返さず接続が閉じる。
Giteaから見ると Post ... EOF です。
対策:
do_POST全体をtry/exceptで囲む- 例外時も
500を必ず返す
2) PRが無視される
Issue対応だけ先に作ると、PRイベントは素通りします。
その結果 OK (ignored event)。
対策:
issuesだけでなくpull_requestも受理opened / reopened / synchronizeを最低限処理
3) 別用途改修でブリッジが壊れる
Discord通知などを同じブリッジに混ぜると、修正の副作用でGitea連携が壊れやすい。
対策:
- 役割ごとにリポジトリを分離
gitea-webhook-bridgediscord-notify-bridge
- systemdサービスも分離
bridge.py の実装指針
受けるイベント
issuesopened
pull_requestopenedreopenedsynchronize
最低限の処理順
- 署名検証(
X-Gitea-Signature) - イベント種別チェック
- アクションチェック
- タスク本文を整形
openclaw agentを非同期起動- すぐに
200 OKを返す
署名検証は必須
:::warning ローカルネットワークでも署名検証は省略しない方が安全です。 Webhook URLを知っているだけで叩ける状態は避けましょう。 :::
Gitea側の設定
ALLOWED_HOST_LIST を忘れない
[webhook]
ALLOWED_HOST_LIST = private
これを忘れると、プライベートIP向けWebhookがブロックされます。
Webhookの基本値
- URL:
http://<bridge-host>:9876/webhook/gitea - Content-Type:
application/json - Secret: bridgeと一致
- Trigger:
issues,pull_request
systemd常駐(再起動に強い構成)
[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 /home/swallow/gitea-webhook-bridge/bridge.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now gitea-webhook-bridge
sudo systemctl status gitea-webhook-bridge
開発プロセス(ここが本体)
単にWebhookを動かすだけだと、チーム運用では破綻します。 最終的に安定したのは、以下のルールを固定したからです。
ルール1: ブランチ命名を固定
fix/issue-<番号>-<要約>feat/issue-<番号>-<要約>docs/issue-<番号>-<要約>
ルール2: Issueコメントに毎回「3点セット」
- ブランチ切替手順
- 検証コマンド
- mainへの反映手順
これを毎回書くだけで、Gitに不慣れな人の詰まりが激減しました。
ルール3: PRイベントでも同じフローでレビュー
IssueだけでなくPRでもレビューが走ると、 「修正は出たが最終反映前チェックが抜ける」問題を防げます。
Git弱者向けテンプレ(コピペ用)
1) 修正ブランチへ切替
git fetch origin
git switch fix/issue-123-xxx
# 古いgitなら: git checkout fix/issue-123-xxx
2) 検証
python3 -m py_compile src/*.py app/*.py
3) mainへ反映
git switch main
git pull origin main
git merge --no-ff fix/issue-123-xxx
git push origin main
4) 後片付け(任意)
git branch -d fix/issue-123-xxx
git push origin --delete fix/issue-123-xxx
今後の拡張
- ラベル付きIssueのみ処理(
ai-reviewなど) - PRへの自動レビューコメント整形
- 失敗時の自動再試行と通知
- レビュー結果のダッシュボード化
まとめ
Gitea × OpenClaw 連携は、作るだけなら簡単です。 でも、壊れずに回すには運用設計がすべてでした。
- Issue + PR イベント対応
- EOF対策(例外時も必ず応答)
- ブリッジの責務分離
- ブランチ/手順テンプレの固定
この4点を押さえると、AI連携は実務で使えるレベルまで安定します。
この記事は2026年2月時点の情報です。