Githooks
Les githooks sont des scripts lancés automatiquement par git. Ils prennent des paramètres d'entrée différents en fonction du nom du hook et du contexte d’exécution.
Vous pouvez consulter plusieurs exemples dans le répertoire .git/hooks
de chacun de vos repositories.
Il vous suffit de retirer l'extension .sample
des fichiers d'exemple pour les activer.
Partager les githooks
Le problème du répertoire .git
c'est qu'il est local. Il n'est jamais poussé sur le repo distant. Comment donc partager des hooks ?
La méthode la plus simple consiste a créer un répertoire dédié aux hooks (.githooks
par exemple) qui sera poussé avec les sources.
Pour qu'un hook soit exécutable, il faut ... le rendre exécutable:
chmod + x .githooks/commit-msg
Il faudra alors dire a git que ce répertoire contient des hooks pour que git les lance:
la commande serait alors:
git config core.hooksPath .githooks
Automatiser l'initialisation des hooks
La configuration de git étant locale, il faut pouvoir également la partager. Dans l'idéal, cela se fera de manière transparente pour s'assurer que tous les développeurs l'utilisent.
A partir d'ici, cela dépends surtout de votre environnement de development. Par exemple dans un contexte NodeJS, on pourrait utiliser le script pre-install (un hook lui aussi) pour automatiser la configuration lorsqu'un développeur installe les dépendances. Cela donnerait alors un fichier package.json
de ce type:
{
"script": {
"pre-install": "git config core.hooksPath .githooks"
}
}
Exemples de githooks
Ne pas permettre de push si les tests sont foireux
Le fichier sera nommé pre-push
pour se lancer avant un push afin de le stopper le cas échéant.
#!/bin/sh
# Prevent push when tests fail
# specific params for pre-push hook - see https://git-scm.com/docs/githooks
read local_ref local_sha remote_ref remote_sha
npm run test --workspaces
if [ $? -ne "0" ]; then
echo "\n\e[1;31m💥 Tests failed. You are not allowed to push ! 💥\033[0m\e[0m\n"
# exit with an error
exit 1
fi
Linter les messages de commit
Le fichier sera nommé commit-msg
pour se lancer avant un commit afin de le stopper le cas échéant.
#!/usr/bin/env bash
# SETTINGS
SCOPE_MAX_LENGTH=20
TITLE_MAX_LENGTH=60
TYPES=(build ci docs feat fix perf refactor revert style test)
commitRegexp="^("
# add type check
for type in ${TYPES[@]}; do
commitRegexp="$commitRegexp$type|"
done
commitRegexp="${commitRegexp%|})"
# add optional scope check
commitRegexp="${commitRegexp}(\((.{1,${SCOPE_MAX_LENGTH}})\))?"
# add optional breaking check
commitRegexp="${commitRegexp}!?: "
# add title check
commitRegexp="${commitRegexp}(.{1,$TITLE_MAX_LENGTH})$"
branchNameRegex="(.*)"
mergeRegexp="^(Merge( remote-tracking)? branch '${branchNameRegex}'( of .*)? into ${branchNameRegex})$"
# get first line of the commit message
commit_file=$1
commit_message=$(head -n1 $commit_file)
# run check
if [[ ! $commit_message =~ $commitRegexp && ! $commit_message =~ $mergeRegexp ]]; then
echo -e "\n\e[1;31m💥 Invalid Commit Message 💥\033[0m\e[0m\n"
echo -e "\e[37mActual commit message: \e[33m\"$commit_message\"\033[0m\n"
echo -e "-------- valid message format --------\e[36m"
echo -e "<type>[optional scope]: <description>\n"
echo -e "[optional body]\n"
echo -e "[optional footer(s)]\033[0m"
echo -e "--------------------------------------\n"
echo -e "valid types: \e[36m${TYPES[@]}\033[0m"
echo -e "max length (scope): \e[36m$SCOPE_MAX_LENGTH\033[0m"
echo -e "max length (title): \e[36m$TITLE_MAX_LENGTH\033[0m\n"
echo -e "\e[37mregex used: \e[33m$commitRegexp\033[0m"
echo -e "see https://www.conventionalcommits.org/en/v1.0.0/"
# exit with an error
exit 1
fi
Les limites
Les githooks peuvent accomplir de grandes choses. On pourrait par exemple imaginer (sur un petit projet perso) builder et publier notre site a chaque fois que l'on pousse les sources sur Git. Ce serait un peu comme une CI locale.
Les seules limites c'est:
- vous
- l'argument
--no-verify
du CLI Git qui bypass les githooks
Eh oui ! comme c'est du local, si on veut contourner la règle c'est easy. Les githooks c'est bien pour gagner du temps mais ça ne remplace pas une CI.
Aller plus loin
Le site githooks.com est une excellente référence.