git hook: Не пускаем в репозиторий ошибки

Настраивая систему разворачивания проекта с репозитория, мы задумались над вопросом чистоты кода репозитория, ибо тесты на самом сервере – это хорошо, но в системе контроля версий также совсем не помешает держать рабочий код, особенно в “стабильной” ветке.

Как вариант решения:  сделать git-hook, который бы проверял каждый push на репозиторий и не давал заливать “плохой” код. (Под “плохой” мы будем понимать код, который не прошел юнит-тестов либо валидации JSHint)

О самом  git hook можно почитать подробно на официальном сайте. Расскажу только некоторые детали реализации.

Все хуки лежат в директории ./git/hooks/. Там же есть уже готовые примеры реализованные на shell-скрипте(с расширением .sample).

Список возможных действий, на которые можно повесить обработчик:

  • applypatch-msg
  • post-commit
  • post-update
  • pre-commit
  • update
  • commit-msg
  • post-receive
  • pre-applypatch
  • pre-rebase

– подробное описание можно посмотреть тут.

Все перехватчики(hooks) можно разделить по месту их выполнения на клиентские и серверные. В нашем случае мы можем проверять код как на стороне клиента перед отправкой, так и на стороне сервера после получения. В первом случае решение будет менее строгим, т.к. позволит разработчику отключить или изменить его в случае чего. Для этого создаем файл pre-commit, где будет описание действия нашего перехватчика.

Теперь стоит подумать как лучше реализовать код перехватчика. Сначала была мысль написать shell-скрипт, но потом мы вспомнили о grunt, который уже прекрасно работал с проектом, и просто добавили еще одно задание(task) в него – pre-commit-test, в котором описали все необходимые проверки. Осталось только вызывать сборщик из hook-скрипта. Вот весь код:

#!/bin/sh

GRUNTJS_DIR='/path_to_project/project_dir'
GRUNT_CMD=grunt
cd $GRUNTJS_DIR
$GRUNT_CMD pre-commit-test
EXIT_CODE=$?
[ $EXIT_CODE -gt 0 ] && echo && echo validation fail! && echo
exit $EXIT_CODE

Немного комментариев:

GRUNT_CMD=grunt

пусть к команде grunt(в случае, если она не глобальная)

[ $EXIT_CODE -gt 0 ]

проверяем выдал ли что-то валидатор и в случае чего – прерываем выполнение.