Hook SVN et Git pour Maven sous Windows


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 d e 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

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 :
- 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.
- 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 :
- Depuis n’importe quel répertoire, sélectionner le menu contextuel T ortoiseSVN > Settings
- Se rendre dans le menu Hook Scripts
- 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

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

svn.exe ou bien encore le plugin Subversive d’Eclipse ne reconnaissent pas la propriété tsvn:precommithook.
Hook Git

.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 !
