Перейти до вмісту
На сайт

Як надійно отримувати вебхуки GitHub

GitHub надсилає вебхуки на джерело Railhook. Джерело перевіряє підпис, зберігає кожну доставку такою, якою вона надійшла, і пересилає її у ваш сервіс із повторними спробами. Поки сервіс лежить, вебхуки чекають у Railhook.

Чому вебхукам GitHub потрібен буфер

Section titled “Чому вебхукам GitHub потрібен буфер”

GitHub не доставляє невдалі вебхуки повторно автоматично. Повторити доставку можна вручну або через API, але лише за останні 3 дні. (GitHub: Handling failed webhook deliveries, Redelivering webhooks) Ваш сервер має відповісти 2xx протягом 10 секунд. (Best practices for using webhooks)

Деплой, падіння чи повільний обробник у невдалий момент губить подію push, pull request чи issue. Коли попереду стоїть Railhook:

  • Railhook відповідає GitHub, щойно збереже доставку, задовго до спливу 10 секунд.
  • Ваш сервіс отримує до 5 спроб на кожне пересилання з інтервалами від 1 хвилини до 1 години.
  • Те, що так і не вдалося доставити, потрапляє в «Недоставлені пересилання», а будь-яку збережену доставку можна відтворити, доки зберігаються події.
  • Повторна доставка від GitHub має той самий ідентифікатор X-GitHub-Delivery. Railhook його розпізнає, відповідає 202 зі збереженою копією і вдруге її не пересилає.

Знадобляться проєкт Railhook і API-ключ. Ті самі кроки є в панелі керування, у розділі «Вхідні».

Terminal window
export RAILHOOK_URL=https://railhook.io # or your own instance
export RAILHOOK_API_KEY=...
export PROJECT_ID=...
  1. Виберіть секрет. У GitHub секрет вебхука ви задаєте самі:

    Terminal window
    export GITHUB_WEBHOOK_SECRET=$(openssl rand -hex 32)
  2. Створіть джерело з цим секретом:

    Terminal window
    curl -X POST "$RAILHOOK_URL/api/v1/projects/$PROJECT_ID/incoming-sources" \
    -H "X-API-Key: $RAILHOOK_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name":"GitHub","providerType":"GITHUB","verificationMode":"PROVIDER","hmacSecret":"'"$GITHUB_WEBHOOK_SECRET"'"}'

    Збережіть id і ingressUrl із відповіді.

  3. Зареєструйте вебхук у GitHub. У репозиторії чи організації відкрийте Settings → Webhooks → Add webhook. Вставте ingressUrl у поле Payload URL, у Content type виберіть application/json, у Secret вставте той самий секрет і позначте потрібні події.

  4. Додайте призначення, URL вашого сервісу:

    Terminal window
    curl -X POST "$RAILHOOK_URL/api/v1/projects/$PROJECT_ID/incoming-sources/$SOURCE_ID/destinations" \
    -H "X-API-Key: $RAILHOOK_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"url":"https://api.example.com/webhooks/github","authType":"BEARER","authConfig":"{\"token\":\"...\"}","enabled":true}'
  5. Перевірте ping. Під час створення вебхука GitHub надсилає подію ping. Вона з’явиться в Railhook у розділі «Вхідні» → «Отримані».

Як перевіряється підпис

Section titled “Як перевіряється підпис”

Railhook читає X-Hub-Signature-256 (sha256=, а за ним HMAC-SHA256 необробленого тіла в hex) і порівнює його з підписом, який сам обчислив із секретом джерела. На запит, що не збігається, Railhook відповідає 401 і не зберігає його. Підпис, який уже траплявся в межах вікна захисту від повторного використання (типово 5 хвилин), теж відхиляється, якщо тільки запит не є повторною доставкою того, що Railhook уже зберіг.

Тіло точно таке, яким його надіслав GitHub, байт у байт. Оскільки push та issue за тілом не розрізнити, Railhook передає далі заголовки подій GitHub: X-GitHub-Event, X-GitHub-Delivery, X-GitHub-Hook-ID, X-GitHub-Hook-Installation-Target-Type і X-GitHub-Hook-Installation-Target-ID. X-Hub-Signature-256 не пересилається: ваш сервіс автентифікує Railhook за обліковими даними призначення, тож секрет GitHub йому не потрібен. Див. Призначення.

  1. Встановіть CLI й увійдіть, як описано в CLI, а потім відкрийте тунель до порту вашого застосунку:

    Terminal window
    railhook listen 3000
  2. Додайте джерелу друге призначення: публічну адресу, яку вивела команда, з вашим маршрутом у кінці, наприклад https://<host>/tunnel/<slug>/webhooks/github. Запит потрапить на http://localhost:3000/webhooks/github.

  3. Зробіть push або відтворіть збережений ping у Railhook. Повторна доставка з боку GitHub тут не спрацює: вона має той самий X-GitHub-Delivery, тож Railhook відповість збереженою копією і не перешле її. Перевірений вебхук надійде у ваш локальний застосунок із заголовком X-GitHub-Event. Коли закриєте тунель, вимкніть це призначення.

Відтворення після збою

Section titled “Відтворення після збою”

Кожна відтворена доставка піде на кожне призначення джерела як нове пересилання:

Terminal window
curl -X POST "$RAILHOOK_URL/api/v1/projects/$PROJECT_ID/incoming-events/bulk-replay" \
-H "X-API-Key: $RAILHOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sourceId":"'"$SOURCE_ID"'","from":"2026-09-18T10:00:00Z","to":"2026-09-18T14:00:00Z","verified":true}'

Тут немає обмеження в 3 дні: відтворити можна все, що ще зберігається: 7 днів у Railhook Cloud і скільки налаштуєте на власному сервері. Зробіть обробник ідемпотентним за X-GitHub-Delivery, бо відтворення може надіслати доставки, які ваш сервіс уже обробив. Див. Відтворення.