Автоматические комментарии к PR на GitHub с помощью Webhook
Это руководство проведёт вас через подключение VibeOS к GitHub, чтобы она автоматически получала diff пул-реквеста, анализировала изменения кода и оставляла комментарий — запускаемый событием вебхука без ручного ввода команд.
Когда PR открывается или обновляется, GitHub отправляет POST-запрос вебхука на ваш экземпляр VibeOS. VibeOS запускает агента с промптом, который предписывает ему получить diff через CLI gh, а ответ публикуется обратно в тред PR.
Если у вас нет публичного URL или вы просто хотите быстро начать, ознакомьтесь с разделом Создание агента ревью PR на GitHub — использует cron-задачи для опроса PR по расписанию, работает за NAT и файрволами.
Полную справку по платформе вебхуков (все опции конфигурации, типы доставки, динамические подписки, модель безопасности) см. в разделе Вебхуки.
Полезные данные вебхука содержат данные, контролируемые атакующим — заголовки PR, сообщения коммитов и описания могут содержать вредоносные инструкции. Когда ваш эндпоинт вебхука доступен из интернета, запускайте шлюз в изолированной среде (Docker, SSH-бэкенд). См. раздел о безопасности ниже.
Предварительные требования
- VibeOS установлен и запущен (
vibeos gateway) ghCLI установлен и аутентифицирован на хосте шлюза (gh auth login)- Публично доступный URL для вашего экземпляра VibeOS (см. Локальное тестирование с ngrok, если запускаете локально)
- Административный доступ к репозиторию GitHub (требуется для управления вебхуками)
Шаг 1 — Включите платформу вебхуков
Добавьте следующее в ваш ~/.vibeos/config.yaml:
platforms:
webhook:
enabled: true
extra:
port: 8644 # по умолчанию; измените, если этот порт занят другим сервисом
rate_limit: 30 # макс. запросов в минуту на маршрут (не глобальный лимит)
routes:
github-pr-review:
secret: "ваш-секрет-вебхука-здесь" # должен точно совпадать с секретом вебхука GitHub
events:
- pull_request
# Агенту предписано получить актуальный diff перед ревью.
# {number} и {repository.full_name} извлекаются из полезной нагрузки GitHub.
prompt: |
Получено событие пул-реквеста (действие: {action}).
PR #{number}: {pull_request.title}
Автор: {pull_request.user.login}
Ветка: {pull_request.head.ref} → {pull_request.base.ref}
Описание: {pull_request.body}
URL: {pull_request.html_url}
Если действие — "closed" или "labeled", остановитесь и не публикуйте комментарий.
В противном случае:
1. Выполните: gh pr diff {number} --repo {repository.full_name}
2. Проверьте изменения кода на корректность, проблемы безопасности и ясность.
3. Напишите краткий, конструктивный комментарий к ревью и опубликуйте его.
deliver: github_comment
deliver_extra:
repo: "{repository.full_name}"
pr_number: "{number}"
Ключевые поля:
| Поле | Описание |
|---|---|
secret (на уровне маршрута) | HMAC-секрет для этого маршрута. Если опущен, используется глобальный extra.secret. |
events | Список значений заголовка X-GitHub-Event для приёма. Пустой список = принимать все. |
prompt | Шаблон; {field} и {nested.field} извлекаются из полезной нагрузки GitHub. |
deliver | github_comment публикует через gh pr comment. log просто записывает в лог шлюза. |
deliver_extra.repo | Извлекается, например, как org/repo из полезной нагрузки. |
deliver_extra.pr_number | Извлекается как номер PR из полезной нагрузки. |
Полезная нагрузка вебхука GitHub включает метаданные PR (заголовок, описание, имена веток, URL), но не diff. Промпт выше предписывает агенту выполнить gh pr diff для получения актуальных изменений. Инструмент terminal включён в стандартный набор инструментов vibeos-webhook, поэтому дополнительная настройка не требуется.
Шаг 2 — Запустите шлюз
vibeos gateway
Вы должны увидеть:
[webhook] Listening on 0.0.0.0:8644 — routes: github-pr-review
Проверьте, что он работает:
curl http://localhost:8644/health
# {"status": "ok", "platform": "webhook"}
Шаг 3 — Зарегистрируйте вебхук на GitHub
- Перейдите в ваш репозиторий → Settings → Webhooks → Add webhook
- Заполните:
- Payload URL:
https://ваш-публичный-url.example.com/webhooks/github-pr-review - Content type:
application/json - Secret: то же значение, которое вы указали для
secretв конфигурации маршрута - Which events? → Выберите отдельные события → отметьте Pull requests
- Payload URL:
- Нажмите Add webhook
GitHub немедленно отправит событие ping для подтверждения соединения. Оно безопасно игнорируется — ping нет в вашем списке events — и возвращает {"status": "ignored", "event": "ping"}. Оно логируется только на уровне DEBUG, поэтому не появится в консоли при стандартном уровне логирования.
Шаг 4 — Откройте тестовый PR
Создайте ветку, отправьте изменение и откройте PR. В течение 30–90 секунд (в зависимости от размера PR и модели) VibeOS должен опубликовать комментарий к ревью.
Чтобы следить за прогрессом агента в реальном времени:
tail -f "${VIBEOS_HOME:-$HOME/.vibeos}/logs/gateway.log"
Локальное тестирование с ngrok
Если VibeOS запущен на вашем ноутбуке, используйте ngrok для его публикации:
ngrok http 8644
Скопируйте URL вида https://...ngrok-free.app и используйте его как Payload URL на GitHub. На бесплатном тарифе ngrok URL меняется при каждом перезапуске ngrok — обновляйте вебхук GitHub в каждом сеансе. Платные аккаунты ngrok получают статический домен.
Вы можете протестировать статический маршрут напрямую с помощью curl — без учётной записи GitHub или реального PR.
deliver: log при локальном тестированииИзмените deliver: github_comment на deliver: log в вашей конфигурации во время тестирования. В противном случае агент попытается опубликовать комментарий в фиктивный репозиторий org/repo#99 из тестовой полезной нагрузки, что приведёт к ошибке. Верните deliver: github_comment, когда будете удовлетворены выводом промпта.
SECRET="ваш-секрет-вебхука-здесь"
BODY='{"action":"opened","number":99,"pull_request":{"title":"Test PR","body":"Adds a feature.","user":{"login":"testuser"},"head":{"ref":"feat/x"},"base":{"ref":"main"},"html_url":"https://github.com/org/repo/pull/99"},"repository":{"full_name":"org/repo"}}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print "sha256="$2}')
curl -s -X POST http://localhost:8644/webhooks/github-pr-review \
-H "Content-Type: application/json" \
-H "X-GitHub-Event: pull_request" \
-H "X-Hub-Signature-256: $SIG" \
-d "$BODY"
# Ожидается: {"status":"accepted","route":"github-pr-review","event":"pull_request","delivery_id":"..."}
Затем наблюдайте за работой агента:
tail -f "${VIBEOS_HOME:-$HOME/.vibeos}/logs/gateway.log"
vibeos webhook test <имя> работает только для динамических подписок, созданных с помощью vibeos webhook subscribe. Он не читает маршруты из config.yaml.
Фильтрация по конкретным действиям
GitHub отправляет события pull_request для многих действий: opened, synchronize, reopened, closed, labeled и т.д. Список events фильтрует только по значению заголовка X-GitHub-Event — он не может фильтровать по подтипу действия на уровне маршрутизации.
Промпт из Шага 1 уже обрабатывает это, предписывая агенту остановиться для событий closed и labeled.
Инструкция «остановитесь» предотвращает содержательное ревью, но агент всё равно выполняется до конца для каждого события pull_request независимо от действия. Вебхуки GitHub могут фильтровать только по типу события (pull_request, push, issues и т.д.) — не по подтипу действия (opened, closed, labeled). Фильтра на уровне маршрутизации для поддействий нет. Для репозиториев с высокой активностью примите эту стоимость или фильтруйте вышестоящим образом с помощью рабочего процесса GitHub Actions, который условно вызывает URL вашего вебхука.
Синтаксиса Jinja2 или условных шаблонов нет.
{field}и{nested.field}— единственные поддерживаемые подстановки. Всё остальное передаётся агенту как есть.
Использование навыка для единообразного стиля ревью
Загрузите навык VibeOS, чтобы дать агенту единообразную персону ревьюера. Добавьте skills в ваш маршрут внутри platforms.webhook.extra.routes в config.yaml:
platforms:
webhook:
enabled: true
extra:
routes:
github-pr-review:
secret: "ваш-секрет-вебхука-здесь"
events: [pull_request]
prompt: |
Получено событие пул-реквеста (действие: {action}).
PR #{number}: {pull_request.title} от {pull_request.user.login}
URL: {pull_request.html_url}
Если действие — "closed" или "labeled", остановитесь и не публикуйте комментарий.
В противном случае:
1. Выполните: gh pr diff {number} --repo {repository.full_name}
2. Проверьте diff, используя ваши рекомендации по ревью.
3. Напишите краткий, конструктивный комментарий к ревью и опубликуйте его.
skills:
- review
deliver: github_comment
deliver_extra:
repo: "{repository.full_name}"
pr_number: "{number}"
Примечание: Загружается только первый найденный навык из списка. VibeOS не накладывает несколько навыков — последующие записи игнорируются.
Отправка ответов в Slack или Discord вместо GitHub
Замените поля deliver и deliver_extra внутри вашего маршрута на целевую платформу:
# Внутри platforms.webhook.extra.routes.<имя-маршрута>:
# Slack
deliver: slack
deliver_extra:
chat_id: "C0123456789" # ID канала Slack (опустите для использования настроенного домашнего канала)
# Discord
deliver: discord
deliver_extra:
chat_id: "987654321012345678" # ID канала Discord (опустите для использования домашнего канала)
Целевая платформа также должна быть включена и подключена в шлюзе. Если chat_id опущен, ответ отправляется в настроенный домашний канал этой платформы.
Допустимые значения deliver: log · github_comment · telegram · discord · slack · signal · sms
Поддержка GitLab
Тот же адаптер работает с GitLab. GitLab использует X-Gitlab-Token для аутентификации (простое сравнение строк, не HMAC) — VibeOS обрабатывает оба варианта автоматически.
Для фильтрации событий GitLab устанавливает заголовок X-GitLab-Event со значениями типа Merge Request Hook, Push Hook, Pipeline Hook. Используйте точное значение заголовка в events:
events:
- Merge Request Hook
Поля полезной нагрузки GitLab отличаются от GitHub — например, {object_attributes.title} для заголовка MR и {object_attributes.iid} для номера MR. Самый простой способ узнать полную структуру полезной нагрузки — кнопка Test в настройках вебхука GitLab в сочетании с журналом Recent Deliveries. Альтернативно, опустите prompt из конфигурации маршрута — VibeOS тогда передаст полную полезную нагрузку в виде форматированного JSON напрямую агенту, и ответ агента (видимый в логе шлюза с deliver: log) опишет её структуру.
Заметки по безопасности
- Никогда не используйте
INSECURE_NO_AUTHв продакшене — это полностью отключает проверку подписи. Только для локальной разработки. - Периодически меняйте секрет вебхука и обновляйте его как в GitHub (настройки вебхука), так и в вашем
config.yaml. - Ограничение скорости — 30 запросов/мин на маршрут по умолчанию (настраивается через
extra.rate_limit). Превышение возвращает429. - Дублирующиеся доставки (повторные попытки вебхука) дедуплицируются через кэш идемпотентности на 1 час. Ключ кэша —
X-GitHub-Delivery, если присутствует, затемX-Request-ID, затем метка времени в миллисекундах. Если ни один заголовок ID доставки не установлен, повторные попытки не дедуплицируются. - Инъекция в промпт: Заголовки PR, описания и сообщения коммитов контролируются атакующим. Вредоносные PR могут попытаться манипулировать действиями агента. Запускайте шлюз в изолированной среде (Docker, ВМ) при публичном доступе из интернета.
Устранение неполадок
| Симптом | Проверка |
|---|---|
401 Invalid signature | Секрет в config.yaml не совпадает с секретом вебхука GitHub |
404 Unknown route | Имя маршрута в URL не совпадает с ключом в routes: |
429 Rate limit exceeded | Превышен лимит 30 запросов/мин на маршрут — часто при повторной доставке тестовых событий из интерфейса GitHub; подождите минуту или увеличьте extra.rate_limit |
| Комментарий не опубликован | gh не установлен, не в PATH или не аутентифицирован (gh auth login) |
| Агент запускается, но комментария нет | Проверьте лог шлюза — если вывод агента был пустым или содержал только «SKIP», доставка всё равно будет предпринята |
| Порт уже занят | Измените extra.port в config.yaml |
| Агент запускается, но ревьюит только описание PR | В промпте нет инструкции gh pr diff — diff отсутствует в полезной нагрузке вебхука |
| Не вижу событие ping | Игнорируемые события возвращают {"status":"ignored","event":"ping"} только на уровне DEBUG — проверьте журнал доставки GitHub (репозиторий → Settings → Webhooks → ваш вебхук → Recent Deliveries) |
Вкладка Recent Deliveries на GitHub (репозиторий → Settings → Webhooks → ваш вебхук) показывает точные заголовки запроса, полезную нагрузку, HTTP-статус и тело ответа для каждой доставки. Это самый быстрый способ диагностировать сбои без обращения к логам сервера.
Полная справка по конфигурации
platforms:
webhook:
enabled: true
extra:
host: "0.0.0.0" # адрес привязки (по умолчанию: 0.0.0.0)
port: 8644 # порт прослушивания (по умолчанию: 8644)
secret: "" # опциональный глобальный запасной секрет
rate_limit: 30 # запросов в минуту на маршрут
max_body_bytes: 1048576 # лимит размера полезной нагрузки в байтах (по умолчанию: 1 МБ)
routes:
<имя-маршрута>:
secret: "обязательно-для-каждого-маршрута"
events: [] # [] = принимать все; иначе список значений X-GitHub-Event
prompt: "" # {field} / {nested.field} извлекаются из полезной нагрузки
skills: [] # загружается первый подходящий навык (только один)
deliver: "log" # log | github_comment | telegram | discord | slack | signal | sms
deliver_extra: {} # repo + pr_number для github_comment; chat_id для остальных
Что дальше?
- Ревью PR по расписанию (Cron) — опрашивайте PR по расписанию, без публичного эндпоинта
- Справочник по вебхукам — полная справка по конфигурации платформы вебхуков
- Создание плагина — упакуйте логику ревью в распространяемый плагин
- Профили — запустите выделенный профиль ревьюера с собственной памятью и конфигурацией