Перейти к основному содержимому

Автоматические комментарии к 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)
  • gh CLI установлен и аутентифицирован на хосте шлюза (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.
delivergithub_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​

  1. Перейдите в ваш репозиторий → Settings → Webhooks → Add webhook
  2. Заполните:
    • Payload URL: https://ваш-публичный-url.example.com/webhooks/github-pr-review
    • Content type: application/json
    • Secret: то же значение, которое вы указали для secret в конфигурации маршрута
    • Which events? → Выберите отдельные события → отметьте Pull requests
  3. Нажмите 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 для остальных

Что дальше?​