Во время работы над веб-проектами нередко используется тестовый сервер. На нем можно устранить недоработки или продемонстрировать клиентам ход работы и текущее состояние проекта. Но для содержания тестового сервера необходимо регулярно развертывать на нем актуальные изменения. Часто этот процесс, помимо обновления файлов, требует дополнительных операций: компиляция less- и sass-стилей или их аналогов, склеивание и минификация скриптов, оптимизация изображений. Все это можно и нужно автоматизировать с помощью инструментов вроде grunt, но для его запуска нужно регулярно выполнять команду запуска в командной строке сервера.

Для решения этой проблемы у таких сервисов, как GitHub и Bitbucket, существуют web hooks. Работают они очень просто: когда кто-то обновляет код в репозитории, сервис отправляет на указанный при настройке хука HTTP-адрес запрос с данными об обновлении. Есть подобный функционал и в GitLab.

Страница настройки хуков в GitLab

Используя GitLab Web Hook, напишем простенький скриптик, обновляющий исходный код проекта. Нам понадобится возможность выполнять произвольные команды в командной строке, поэтому сам PHP-скрипт будет вызывать shell-скрипт. Позаботимся также и о защите от несанкционированного запуска нашего скрипта. Для этого спрячем сам shell-скрипт за пределы досягаемости веб-сервера, а в PHP-скрипт встроим поддержку паролей. Каждый раз при запуске хука, GitLab передает в него данные о событии, вызвавшем активацию хука. У каждого события свой набор данных, но нас интересует событие push. Среди прочего, среди передаваемых данных есть ветка, которая была обновлена. Используя эту информацию, добавим возможность выполнения shell-скрипта только в случае обновления конкретной ветки.

В итоге у меня получился достаточно простенький скриптик, который я разместил на GitLab. Для установки нужно закинуть его в корень сайта, настроить и добавить в репозитории GitLab. Все настройки прописываются в шапке PHP-скрипта. Доступны следующие настройки:

Настройка Тип Описание Пример
$hookfile Необходимая, string путь к исполняемому файлу — shell-скрипту
$hookfile = '../.hooks/gitlab-webhook-push.sh';
$logfile Необходимая, string путь к файлу логов PHP- и shell-скриптов
$logfile = '../.hooks/gitlab-webhook-push.log';
$password Рекомендуемая, string пароль на исполнения хука; если пароль установлен но не передан при вызове, скрипт не сработает
$password = 'my_strong_password';
$ref string или array здесь можно указать ветку, при обновлении которой будет выполняться хук. Для того, чтобы фильтр работал, название нужно указывать полностью
$ref = 'refs/heads/master';
$ref = array('refs/heads/master', 'refs/heads/develop');

После, того как скрипт будет настроен, нужно перейти в раздел Web Hooks настроек GitLab и создать новый хук для события push:

Пример настроенного хука в GitLab

Если все настроено правильно, после следующего обновления GitLab отправит на указанный адрес запрос, который и запустит наш хук. По-умолчанию, хук выполняет команду git pull в корне сайта. Это поведение можно легко изменить настроить, внеся изменения в shell-скрипт. Для запуска shell-скрипта в PHP-скрипте используется PHP-функция exec(), поэтому убедитесь что ее использование не запрещено конфигурацией сервера.

Используя веб-хуки, можно наладить чудесный цикл разработки, где самые свежие изменения автоматически попадают на тестовый сервер, стили и скрипты автоматически сжимаются. Это промежуточный шаг перед использованием полноценного CI-сервера (сервера непрерывной интеграции). Но настройка такого сервера уже выходит за рамки этой статьи.