Gérez facilement et partagez vos hooks avec husky
Par Maxime Bréhin • Publié le 6 septembre 2021
• 3 min
Les hooks sont tout bonnement géniaux quand il s’agit de nous assister et d’automatiser la qualité du travail qu’on produit. Malheureusement l’architecture de Git fait défaut en ne facilitant pas le partage des hooks et de leur configuration.
C’est là qu’intervient husky !
Husky : quoi et pourquoi ?
Husky est un module npm (JavaScript) dont le but est de se greffer “par-dessus” les hooks Git pour que ces derniers soient automatiquement intégrés et partagés au sein d’un projet.
Il existe de nombreuses alternatives mais très peu couvrent l’intégralité des hooks disponibles (la plupart ne traitent que du pre-commit). D’autre part husky possède un avantage non négligeable : il est portable car Node.js est disponible à peu près partout (principe du JavaScript universel).
Avant de commencer : la version de husky traitée ici est la version 7 produite en juillet 2021 mais le fonctionnement décrit était présent dès la version 6.
Le principe de fonctionnement de husky est plutôt simple :
- il crée un répertoire
.husky
à la racine du projet, - il renseigne ce répertoire dans notre configuration Git locale (
git config core.hooksPath '.husky'
) - il y place, à notre demande, des fichiers en équivalence des scripts de hooks (fichiers
pre-commit
,prepare-msg
,commit-msg
etc).
Ces fichiers suivent le même format. Ils possèdent un en-tête particulier et listent ensuite les appels aux scripts demandés :
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# Script directement intégré
echo 'Tu verras ce message dans ton terminal quand ce hook sera executé'
# Appel à un script ailleurs dans le projet (attention, ils doivent être exécutables)
./say-hello.js
# Appel à un script tiers (exemple ici d’un module npm installé avec le projet)
npx --no-install lint-staged
Mise en place dans un projet
Sa mise en place est rapide :
# (Dans un terminal) on installe le module
npm install --save-dev husky
Pas de bol, npm n’existe pas sur ma machine
La commande npm
n’est pas disponible ? Assurez-vous d’avoir Node.js sur votre machine, au besoin installez-le (ça intègre automatiquement npm) :
# Est que node est installé ?
node -v
Retentez ensuite la commande (vous aurez peut-être besoin de relancer un terminal frais, avec un chemin (PATH
) à jour).
Astuce supplémentaire si vous n’utilisiez pas Node jusque-là dans le projet : pensez à dire à Git d’ignorer le répertoire node_modules
:
echo 'node_modules/' >> .gitignore
git add .gitignore
Configuration générale et ajout de hooks
# On partage l’initialisation des hooks (au cas où) en l’intégrant
# via le script de cycle de vie "prepare" du fichier `package.json`.
npm set-script prepare "husky install"
# On se prépare (création du sous-répertoire `.husky` et
# configuration Git `core.hooksPath`).
npm run prepare
À partir de là husky est intégré, sauf qu’on n’a renseigné aucun hook. Cette étape doit être faite au cas par cas, selon les hooks qu’on souhaite utiliser :
npx husky add .husky/<nom-du-hook> <script(s)-à-exécuter>
Voici un exemple pour afficher sur la sortie standard (terminal) un message de félicitation dès qu’un commit a été créé (ça ne sert à rien, mais ça fait du bien 🙃) :
npx husky add .husky/post-commit 'echo "🤜 Yeah, ton commit il est trop BG™ ! 🤛"'
Quand vous avez fini de configurer tout ça et d’ajouter les hooks qui vous semblent pertinents au projet, n’oubliez pas de partager tout ça en intégrant au projet :
git add .husky/ package-lock.json package.json
À l’usage ça donne quoi ?
Les cas pratiques sont nombreux et dépendront parfois des technologies que vous utilisez. Deux approches sont possibles et complémentaires :
- l’intégration de scripts au sein même du projet (préférable pour du “spécifique projet”) ;
- l’utilisation de scripts externes (propres à l’entreprise ou externes), facilement réutilisables d’un projet à l’autre.
Cette seconde approche est la plus répandue car il est rare de devoir réaliser des tâches spécifiques à un projet et qui n’ont pas d’utilité pour d’autres projets. Il est également plus aisé et rapide (donc moins coûteux) d’utiliser de l’outillage existant plutôt que de devoir développer ses propres scripts (et tant qu’à faire on évite de réinventer la roue ⚙).
Pour vous aider à mettre en place les automatisations qui vous intéressent, on vous a préparé une petite série d’articles par thème :
- Du code bien formaté sans effort avec husky et lint-staged
- Sauvez vos commits grâce à husky et git-precommit-checks
- Améliorez vos messages de commits avec husky et commitlint
- Normez vos branches avec husky et validate-branch-name
La ligne de commande c’est mignon, mais dans mon éditeur ça donne quoi ?
Tout dépend de la capacité de votre éditeur à vous transmettre l’information contenue dans la sortie d’erreur d’un hook (pour les hooks bloquants s’entend).
Par exemple pour VSCode, si on utilise son interface graphique pour créer notre commit, alors on obtiendra une modale d’erreur qui nous indiquera la première ligne de la sortie standard (très peu utile 😬) et un bouton nous permettant d’accéder à l’ensemble des informations affichées sur la sortie standard (donc tout ce qu’on aurait eu via le terminal en direct). On garde ainsi toute l’utilité de l’outillage.