Обработка событий в GIT
Git отличная распределенная система управления версиями. Помимо возможности нескольким пользователям разрабатывать код, она позволяет быстро и легко откатывать внесенные неудачные изменения обратно. Особенно это актуально, если были закомичены какие-то фатальные правки и код выкачен в продакшн.
Но все же лучше предотвращать попадание таких комитов в центральный репозиторий, нежели поспешно откатываться на предыдущую стабильную версию. Для реализации этой возможности в системе управления версиями GIT существуют хуки (hooks). Под катом приведен пример систем использующейся в одном из наших проектов.
Общее
В рамках данной статьи рассмотрим «pre-receive« хук. Он является наиболее интересным для нас, поскольку позволяет, при попытке разработчиком закомитить свои изменения, просмотреть их и отклонить, если не будет выполнятся какое-то из условий. Благодаря этому можно реализовать две простые, но очень полезные вещи:
- Проверка синтаксиса.
- Запрет комитита миграций БД, которые содержат в себе операции типа «ALTER», «DELETE», «DROP», «TRUNCATE».
Обработчик «pre-receive» события
#!/bin/sh
# Pre-receive hook executer
if [ -z "$GIT_DIR" ]; then
echo «Don’t run this script from the command line.» >&2
exit 1
fi
while read OLDREV NEWREV REFNAME ; do
for script in find $PWD/hooks/pre-receive.d/ -perm -100 ! -type d
do
$script «$OLDREV» «$NEWREV» «$REFNAME» || exit $?
done
done
exit 0
Проверка синтаксиса PHP
#!/bin/sh
# A pre-receive hook to disallow php syntax errors to be
# committed by running php -l (lint) on them.
EXT=»0″
NOREV=»0000000000000000000000000000000000000000″
OLDREV=$1
NEWREV=$2
REFNAME=$3
TMP_DT=$(mktemp /tmp/git.php-syntax-check.XXXXXX)
git diff-tree -r «$OLDREV» «$NEWREV» > $TMP_DT
while read old_mode new_mode old_sha1 new_sha1 status name
do
# Skip lines showing parent commit
if [ -z "$new_sha1" ]; then continue; fi
# Skip deletions
if [ "$new_sha1" = "$NOREV" ]; then continue; fi
# Check only .php files
if [ echo $name | grep "\.php$" | wc -l
-ne 0 ]
then
CHK=git cat-file blob $new_sha1 | /usr/local/bin/php -l
RET=$?
if [ $RET -ne 0 ]
then
echo
echo «!!!! PUSH REJECTED !!!!»
echo
echo «Errors parsing $name.»
echo «LOL! Check your syntax.»
echo
EXT=»1″
fi
fi
done < $TMP_DT
rm -f $TMP_DT
exit «$EXT»
Проверка миграций mysql
#!/bin/sh
# Pre-receive hook discarding DELETE, ALTER, DROP and TRUNCATE table migrations
EXT=»0″
NOREV=»0000000000000000000000000000000000000000″
OLDREV=$1
NEWREV=$2
REFNAME=$3
TMP_DT=$(mktemp /tmp/git.discard-alter-table.XXXXXX)
git diff-tree -r «$OLDREV» «$NEWREV» > $TMP_DT
while read old_mode new_mode old_sha1 new_sha1 status name
do
# Skip lines showing parent commit
if [ -z "$new_sha1" ]; then continue; fi
# Skip deletions
if [ "$new_sha1" = "$NOREV" ]; then continue; fi
# Check only .sql files
if [ echo $name | grep "\.sql$" | wc -l
-ne 0 ]
then
if [ git cat-file blob $new_sha1 | egrep -i "delete|alter|drop|truncate" | wc -l
-ne 0 ]
then
echo
echo «!!!! PUSH REJECTED !!!!»
echo
echo «DELETE, ALTER, DROP & TRUNCATE TABLE operations are not allowed.»
echo «Please contact system administrator.»
echo
EXT=»1″
fi
fi
done < $TMP_DT
rm -f $TMP_DT
exit «$EXT»
Источник: highload.com.ua