Hook SVN et Git pour Maven sous Windows

logo-mavenDésormais ancrées dans le quotidien des développeurs, les plateformes d’intégration continue permettent de détecter rapidement tout problème de compilation, de tests en erreur ou même d’ajout de défauts remontés par SonarQube. L’objectif fixé par le team leader est de ne pas faire échouer le build et, si c’est malheureusement le cas, tout arrêter pour le réparer. Sur certains projets, le gage donné au développeur ayant cassé le build est de ramener les viennoiseries le lendemain.
Pour être certain de ne pas faire chauffer sa carte de paiement, une bonne pratique consiste à exécuter une ligne de commande maven (ou gradle) avant chaque commit dans le gestionnaire de code source. Cependant, sur certains changements que l’on juge mineur, il peut être tentant de passer outre. Aujourd’hui, les PC ou les Mac multi-coeurs avec SSD permettent de lancer un build sans freezer le poste de développement. C’est donc davantage par excès de confiance qu’à cause du temps d’attente qu’il arrive de casser Jenkins, Bamboo ou bien encore TeamCity.

Pour contrer tout oubli, il est possible de systématiser l’exécution du build Maven avant de commiter. Les outils de gestion de configuration SVN et Git offrent un mécanisme de hook. Lors de la phase de pre-commit, on va demander au SCM d’exécuter un script de hook chargé de vérifier le code source. En cas d’erreur, le commit est refusé.
Ecrire de tels scripts n’est pas compliqué sous Linux car beaucoup d’exemples existent. Par contre, sous Windows, c’est plus rare. L’objet de cet article est donc de vous donner des exemples de scripts de hook de pre-commit et de vous expliquer comment les configurer dans Tortoise SVN et Git.

Hook SVN

logo-svnDeux types de hook existent dans Subversion : des hooks clients et des hooks serveurs.
Pour ne pas transformer le serveur SVN en serveur d’intégration continue, ce sont les hooks clients qui vont ici nous intéresser.
Le script appelé par le hook n’est rien d’autre qu’un .bat.
L’exemple de script pre-commit.bat ci-dessous est localisé dans le même répertoire que le POM reactor du projet. Un pré-requis est que Maven et Java sont dans le PATH de Windows.

@echo on
call mvn clean –f myapp-parent\pom.xml  > target\pre-commit.log
if not exist target mkdir target
call mvn install sonar:sonar -Dsonar.analysis.mode=preview -Dsonar.issuesReport.html.enable=true -Dsonar.buildbreaker.skip=false –f myapp-parent\pom.xml > target\pre-commit.log
echo Maven error code: %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

Afin de pouvoir être consultée en cas d’échec du build, la sortie console est redirigée dans un fichier de logs. Le code d’erreur de maven est retourné à SVN qui sait l’interpréter. Tout code différent de 0 fait échouer le commit.
Exécuté dans à la racine de l’arborescence, le paramètre –f myapp-parent\pom.xml permet de spécifier à maven où se trouve le POM parent (structure de type flat module). Nul besoin d’ajouter ce paramètre lorsque le POM parent se situe à la racine du projet.

TortoiseSVN permet de configurer un hook client à 2 niveaux :

  1. De manière globale pour tous les repos SVN du poste de dév. Chaque développeur doit individuellement configurer TortoiseSVN. Cette configuration peut être problématique lorsqu’un développeur est amené à travailler sur plusieurs repos et que le script de hook n’est pas assez générique. Le script précédent devra être généralisé pour fonctionner avec l’ensemble des projets.
  2. De manière unitaire pour chaque repo SVN. A l’instar d’une propriété svn:ignore, TortoiseSVN ajoute récursivement une propriété tsn:precommithook au niveau du repository SVN. Tous les développeurs bénéficient alors de ce hook.

Etapes de configuration du mode global :

  1. Depuis n’importe quel répertoire, sélectionner le menu contextuel TortoiseSVN > Settings
  2. Se rendre dans le menu Hook Scripts
  3. Renseigner les champs suivants :
    • Hook type : pre-commit
    • Woking copy path : chemin vers le pom parent de l’application
    • Command line to execute : pre-commit.bat

2014-12-hook-maven-git-svn-sous-windows-svn-hook-global-config

 

 

 

 

Etapes de configuration du mode local :

  1. Sélectionner le répertoire racine du projet SVN
  2. Ouvrir le menu contextuel et sélectionner le menu TortoiseSVN > Properties
  3. Cliquer sur le bouton New > Local Hooks (création d’une property tsvn:precommithook)
  4. Choisir les paramètres suivants :
    1. Hook Type : Start Commit Hook
    2. Command Line to Execute : %REPOROOT+%/myproject-parent/pre-commit.bat
    3. Cocher les options suivantes :
      1. Wait for the script to finish
      2. Always execute the script
      3. Apply property recursively
  5. Commiter ces modifications de manière récursive sur l’ensemble des sous répertoires du projet SVN

2014-12-hook-maven-git-svn-sous-windows-svn-hook-local-properties

 

 

 

 

Remarque : les hooks clients sont une fonctionnalité propre à TortoiseSVN. De ce fait, le client en ligne de commande svn.exe ou bien encore le plugin Subversive d’Eclipse ne reconnaissent pas la propriété tsvn:precommithook.

Hook Git

logo-gitGit appartenant à la catégorie des DVCS, il n’existe pas de hook server. La configuration s’effectue donc au niveau du repository Git local. Les scripts de hook sont à positionner dans le sous-répertoire .git\hooks. Par défaut, ce répertoire contient des exemples post-fixés par l’extension .sample. Le nom des scripts est conventionné et correspond au nom de la phase à laquelle il est exécuté. Ainsi, le script de hook exécuté avant le commit se nomme pre-commit.
Sous Windows, Msysgit est le client Git le plus populaire. Basé sur les utilitaires Msys, le script ne doitpas être écrit en script batch comme c’est le cas avec SVN, mais en bash Linux.

Voici un exemple de sript shell pre-commit :

#!/bin/sh
echo "Executing pre-commit"
# Set Java and Maven:
export JAVA_HOME="C:/dev/jdk/1.7.0_45"
export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=256m"
export MAVEN_HOME="C:/dev/maven/apache-maven-3.2.3"
echo "Running Maven clean install for errors and Sonar for testing if the project fails its quality gate."
# Retrieving current working directory
CWD=`pwd`
MAIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Go to main project dir
cd $MAIN_DIR/../../myapp-parent
# Running Maven clean install and Sonar
$MAVEN_HOME/bin/mvn clean install -U sonar:sonar -Dsonar.analysis.mode=preview -Dsonar.issuesReport.html.enable=true -Dsonar.buildbreaker.skip=false
if [ $? -ne 0 ]; then 
echo "Error while compiling or testing the code"
# Go back to current working dir
cd $CWD
exit 1
fi
# Go back to current working dir
cd $CWD 
exit 0

La commande cd $MAIN_DIR/../../myapp-parent permet de positionner dans le répertoire contenant le POM parent. Ce chemin est à adapter selon la structure du projet.

Conclusion

Que ce soit avec Git ou avec TortoiseSVN, il est possible de systématiser l’appel à commande mvn clean install (ou à tout autre script) avant de commiter. Cette bonne pratique fait en sorte que le code historisé dans le gestionnaire de code source est toujours stable. L’intérêt de maintenir un serveur d’intégration continue peut donc se poser. Dès 2009, David Gageot montrait d’ailleurs qu’il était possible de monter une intégration continue sans serveur. Pour autant, les serveurs d’intégration continue tels que Jenkins ont aujourd’hui davantage de responsabilités que par le passé : exécution des tests d’intégration, des tests Selenium et des tests de montée en charge, packaging, déploiement d’applications sur les différents environnements … Leurs jours ne sont donc pas comptés !

Laisser un commentaire

Votre adresse e-mail 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.