Git : L’utilisation des hooks avec Husky

hooks de git

La mise en place des hooks de git et le partage de ceux-ci avec l’ensemble de l’équipe d’un projet peut parfois s’avérer compliqué.  Nous avons vu brièvement dans un précédent article que l’utilisation de librairie husky pouvait grandement nous faciliter cette mise en place. C’est ce que nous allons voir aujourd’hui.

Un hook c’est quoi ?

Avant de s’attaquer à la librairie husky, voyons voir ce qu’est un hook. Un hook est simplement un script qui s’exécute automatiquement lorsqu’un événement particulier se produit dans un dépôt git. On distingue deux types de hooks, ceux s’exécutant côté client et ceux s’exécutant côté serveur.

Côté client

Les hooks côté client s’exécutent uniquement sur les machines des utilisateurs et ne sont pas partagés avec les membres de l’équipe d’un projet, nous reviendrons sur ce point lorsque nous parlerons de la librairie husky.

On distingue trois catégories de hooks côté client :

  • Les hooks concernant les commits;
  • Les hooks concernant l’application de correctifs;
  • Les hooks concernant les autres opérations.

Les hooks concernant les commits

Les hooks concernant les commits permettent d’effectuer certaines actions telles que la vérification des tests unitaires, le pré-remplissage d’un message de commit, la vérification du respect des conventions de nommage des messages de commit comme nous l’avons vu dans le précédent article ou même l’envoie de notification aux autres membres de l’équipe avec par exemple les changements effectués par le commit.

Les principaux hooks concernant les commits sont les suivants :

  • pre-commit : Ce hook se déclenche en premier avant même de saisir le message du commit;
  • prepare-commit-msg : Ce hook se déclenche avant que l’éditeur de message ne soit lancé;
  • commit-msg : Ce hook se déclenche juste après l’édition du message du commit, mais avant la création de celui-ci;
  • post-commit : Ce hook se déclenche après la création du commit.
Hooks concernant les commits
Hooks concernant les commits

Les hooks concernant l’application de correctifs

Cette catégorie de hooks concerne les correctifs envoyés par email. Voici les principaux hooks concernant cette catégorie :

  • applypatch-msg : Ce hook se déclenche avant l’application du correctif;
  • pre-applypatch : Ce hook se déclenche après l’application du correctif, mais avant la création du commit associé;
  • post-applypatch : Ce hook se déclenche une fois le correctif appliqué et le commit associé crée.
Hooks concernant l'application de correctifs
Hooks concernant l’application de correctifs

Les hooks concernant les autres opérations

Il existe également d’autres hooks qui ne rentrent pas dans les deux premières catégories. Voici les principaux :

  • pre-rebase : Ce hook se déclenche avant l’exécution de la commande git rebase;
  • post-checkout : Ce hook se déclenche après l’exécution de la commande git checkout ou git clone ;
  • post-merge : Ce hook se déclenche après l’exécution réussie de la commande git merge;
  • pre-push : Ce hook se déclenche avant l’exécution de la commande git push.

Côté serveur

Ces hooks contrairement à ceux vus précédemment sont uniquement exécutés par le serveur qui héberge le dépôt git. 

Les principaux hooks serveur sont les suivants :

  • pre-receive : Ce hook se déclenche lorsqu’une personne effectue la commande git push. Il s’exécute juste avant la réception des objets et des références;
  • update : Ce hook est similaire au hook pre-receive, mais contrairement à celui-ci qui s’exécute une seule fois quelque soit le nombre de branches concernées par la modification, update s’exécute pour chacune des branches devant être modifiées;
  • post-receive : Ce hook se déclenche une fois l’ensemble des objets et références ont été mis à jour.
Les hooks côté serveur
Les hooks côté serveur

Pour les plus curieux d’entre vous, la liste complète des hooks est disponible sur la documentation officielle de git : https://git-scm.com/docs/githooks.

Comment mettre en place les hooks ?

Après avoir vu ce qu’était un hook, voyons comment mettre en place ceux-ci.

Pour ajouter un hook côté client, il suffit de se rendre dans le dossier caché .git de votre projet puis le sous-dossier .hooks et de créer un script ayant le même nom que le  hook que vous souhaité ajouter.

Git fournit, pour chaque dépôt, des scripts d’exemples possédant l’extension .sample. N’hésitez surtout pas à aller voir leur contenu. Pour les activer, retirer simplement l’extension .sample.

L’un des soucis avec les hooks côté client et le partage de ceux-ci avec les autres membres de l’équipe. En effet, ceux-ci ne sont pas versionnés avec votre code et sont uniquement disponibles sur les machines des utilisateurs. 

Pour résoudre ce problème, nous allons utiliser la librairie husky.

Note : Il existe bien entendu d’autres solutions. Par exemple l’utilisation d’un dossier partagé avec les membres de l’équipe contenant vos hooks configurable via l’option core.hooksPath.

Husky à la rescousse

Husky est une librairie permettant de faciliter la création et le partage des hooks au sein d’un projet. Commençons par l’installer :

Pour ajouter des hooks avec husky, rien de plus simple, il suffit d’éditer le fichier package.json :

Il est également possible de créer un fichier .huskyrc si vous souhaitez séparer les configurations :

Pour éviter de surcharger le fichier package.json, je vous recommande cette dernière méthode.

Exemples d’utilisation

Voyons voir maintenant quelques exemples d’utilisations.

Respecter une convention d’écriture des messages de commit

Nous avons vu, dans le précédent article sur git, une convention de nommage concernant les messages de commit. Nous avons également vu comment mettre en place un hook avec husky permettant de vérifier le respect de cette convention, je vous invite donc à aller lire cet article.

Respecter une convention de nommage de nos branches

Nous avons uniquement mis en place une vérification des messages de commit dans le précédent article. Il est possible également de vérifier le nommage de nos branches avant d’envoyer celles-ci sur le dépôt distant. Pour cela installons la librairie validate-branch-name

Configurons ensuite le modèle pour nos noms de branche. Nous pouvons soit configurer celui-ci via le fichier package.json :

Soit en créant un fichier .validate-branch-namerc :

L’expression régulière s’assure juste que le nom des branches respecte le format <type>/<name>/<issue_ID> comme vu dans le précédent article.

Je sais que vous maîtrisez les expressions régulières, il est donc inutile de vous expliquer en détail (#troll). Si jamais vous ne comprenez pas et j’en doute fortement, il y a le site regex101 qui peut vous aider. 

Il nous reste plus qu’à créer le hook. Éditons pour cela le fichier .huskyrc :

Formater son code et vérifier les erreurs avant un commit

Afin d’éviter de vous faire engueuler en envoyant du code qui de toute façon va être rejeter par votre outil d’intégration continue, car celui-ci ne respecte pas les conventions de codage ou comporte des erreurs de syntaxe, il est peut être intéressant de faire une vérification avant chaque commit.

Nous allons donc utiliser prettier et eslint pour cet exemple, mais vous pouvez également utilisé standard. Tout dépend des règles de formatage que vous utilisez c’est pourquoi nous n’allons pas rentrer dans les détails concernant la configuration de ces outils, qui pourrait faire l’objet d’un article à eux seuls, mais plutôt nous concentrer sur la mise en place du hook.

Pour vérifier uniquement les fichiers indexés plutôt que l’intégralité de notre projet, nous allons utiliser la librairie lint-staged. Installons celle-ci :

Passons ensuite à la configuration de lint-staged et ajoutons nos commandes permettant de vérifier et formater notre code. Nous pouvons soit directement ajouter la configuration dans le fichier package.json :

Soit passer par un fichier .lintstagedrc :

La première commande prettier --write formate les fichiers dont l’extension se terminent par js, html, ou css. La seconde commande quant à elle corrige les erreurs eslint des fichiers dont l’extension se termine par js.

Mettons maintenant en place le hook qui va lancer ses deux commandes avec husky lors d’un git commit, pour cela éditons le fichier .huskyrc :

Vérifier les tests avant d’envoyer ses modifications

Il peut être également intéressant de vérifier que les tests passent avant d’autoriser l’envoi de votre code sur votre dépôt distant. Mettons en place cette vérification avec husky, pour cela éditons le fichier .huskyrc :

Eh oui ! c’est tout, si les tests échouent, il est impossible d’envoyer du code sur votre dépôt distant.

D’autres exemples

Il existe tout un tas d’autres cas d’utilisation des hooks :

Contourner les hooks

Il est possible de contourner l’utilisation des hooks via l’option --no-verify de la plupart des commandes git, n’hésitez pas à aller lire la documentation de chacune des commandes pour en savoir plus.

Pour finir…

Les hooks de git sont un outil très puissant, mais souvent peu connu des développeurs. Ils permettent par exemple de s’assurer de la qualité de son code avant l’envoi sur le dépôt distant. Leur mise en place et leur partage deviennent un jeu d’enfant avec l’utilisation de la librairie husky, on aurait donc tort de s’en priver.

Développeur back (nodejs & php), je fais aussi du front (react). Je partage mes connaissances et ma passion au travers de mes articles. N'hésitez pas à me suivre sur Twitter.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.