Серверні хуки виконуються на сервері, що приймає push, і можуть відхилити його. На відміну від клієнтських, їх не можна пропустити через --no-verify - розробник їх не контролює.
Основні серверні хуки:
| Хук | Коли | Що може |
|---|---|---|
pre-receive |
один раз на весь push, до оновлення посилань | відхилити весь push |
update |
для кожного оновлюваного посилання окремо | відхилити окрему гілку чи тег |
post-receive |
після успішного оновлення | сповіщення, запуск деплою; відхилити вже не може |
pre-receive отримує на стандартний ввід рядки <старий SHA> <новий SHA> <посилання>:
#!/bin/sh
zero=0000000000000000000000000000000000000000
while read old new ref; do
# заборонити force push у main: старий коміт має бути предком нового
if [ "$ref" = "refs/heads/main" ] && [ "$old" != "$zero" ]; then
if ! git merge-base --is-ancestor "$old" "$new"; then
echo "Force push у main заборонено"
exit 1
fi
fi
done
Вивід хука повертається клієнту з префіксом remote:.
Де це доступно:
- власний сервер Git, GitLab self-managed, GitHub Enterprise Server - так;
- github.com - власні серверні хуки встановити не можна. Їхню роль виконують rulesets (заборона force push, обов'язкові підписи, обмеження на шляхи й розмір файлів) і push protection для секретів.
Серверні хуки проти CI:
| Серверний хук | CI | |
|---|---|---|
| коли | синхронно, під час push | асинхронно, після push |
| результат | push відхилено, коду на сервері немає | код уже на сервері, PR позначено червоним |
| час | секунди - інакше push «зависає» | хвилини, без обмежень |
| що перевіряти | політики: формат, заборонені файли, права, підписи | збирання, тести, аналіз |
Правило: у хуки - швидкі й безумовні політики, порушення яких не має з'явитися на сервері навіть у гілці (секрети, величезні бінарні файли, заборонені операції). Усе, що довге чи потребує середовища, - в CI. Хук, що запускає тести, робить кожен push хвилинним і ламає роботу всієї команди при збоях.