5.6. Les étapes de builds

Maintenant, Jenkins sait où et à quelle fréquence obtenir le code source du projet. La prochaine chose que vous devez expliquer à Jenkins est qu’est ce qu’il doit faire avec le code source. Dans un build Freestyle, vous pouvez faire ceci en définissant des étapes de build. Les étapes de build sont des blocs basiques de construction pour le processus de build Freestyle de Jenkins. C’est ce qui permet de dire à Jenkins exactement comment vous voulez que votre projet soit construit.

Une tâche de build peut avoir une étape, ou plusieurs. Il peut éventuellement n’en avoir aucune. Dans un build Freestyle, vous pouvez ajouter autant d’étapes de build que vous le souhaitez dans la section Build de la configuration de votre projet (voir la figure Figure 5.26, “Ajouter une étape de build à une tâche de build Freestyle”). Dans une installation Jenkins basique, vous serez capable d’ajouter des étapes pour invoquer Maven et Ant, aussi bien que lancer des commandes shell spécifique à l’OS ou des batchs Windows. Et en installant des plugins additionnels, vous pouvez aussi intégrer d’autres outils, comme Groovy, Gradle, Grailes, Jython, MSBuild, Phing, Python, Rake, et Ruby, juste pour nommer certains des outils les plus connus.

Dans le reste de cette section, nous allons plonger dans quelques-uns des types d’étapes de build les plus communs.

5.6.1. Les étapes de build Maven

Jenkins a un excellent support de Maven, et les étapes de build Maven sont faciles à configurer et très flexibles. Il suffit de choisir « Invoquer les cibles Maven de haut niveau » depuis la liste des étapes de build, choisir une version de Maven à lancer (si vous avez plusieurs versions installées), et entrer les goals Maven que vous souhaitez lancer. Les tâches de build Freestyle de Jenkins fonctionnent biens avec Maven 2 et Maven 3.

Tout comme en ligne de commande, vous pouvez spécifier autant de goals individuels que vous le souhaitez. Vous pouvez aussi fournir des options en ligne de commande. Quelques options utiles de Maven dans un contexte IC sont :

-B, --batch-mode

Cette option indique à Maven de ne pas demander d’entrée à l’utilisateur, en utilisant les valeurs par défaut si nécessaire. Si Maven demande n’importe quelle entrée durant un build Jenkins, le build sera bloqué indéfiniment.

-U, --update-snapshots

Force Maven à vérifier les mises à jour des dépendances de type release ou snapshot sur le dépôt distant. Cela vous permet d’être sûr que vous êtes en train de construire avec les dernières et les plus grandes dépendances snapshot, et pas uniquement les vieilles copies locales qui ne sont pas forcément synchronisées avec le code source.

-Dsurefire.useFile=false

Cette option force Maven à écrire la sortie JUnit dans la console, au lieu de le faire dans des fichiers textes dans le répertoire target comme c’est fait d’habitude. Avec ceci, n’importe quels détails de test en échec seront visibles directement dans la sortie console de la tâche de build. Les fichiers XML dont Jenkins a besoin pour ses rapports de test seront toujours générés.

Ajouter une étape de build à une tâche de build Freestyle

Figure 5.26. Ajouter une étape de build à une tâche de build Freestyle


Les options avancées sont également utiles (cliquez sur le bouton Avancé).

Le champ optionnel POM permet de surcharger l’emplacement par défaut du fichier pom.xml. C’est l’équivalent de lancer Maven en ligne de commande avec l’option -f ou --file. C’est utile pour certains projets multi modules où le fichier agrégé pom.xml (celui contenant les sections <modules>) est situé dans un sous répertoire et non au niveau supérieur.

Le champ Properties vous permet de spécifier des valeurs de propriété qui seront passées au processus de build Maven, en utilisant le format standard de fichier illustré ici :

# Selenium test configuration
selenium.host=testserver.acme.com
selenium.port=8080
selenium.broswer=firefox

Ces propriétés sont passées à Maven en tant qu’options de ligne de commande, comme montré ici :

$ mvn verify -Dselenium.host=testserver.acme.com ...

Le champ JVM Options vous permet de spécifier des options standards de la machine virtuelle Java pour votre tâche de build. Donc, si votre processus de build est particulièrement consommateur de mémoire, vous pourriez ajouter plus d’espace pour la heap avec l’option -Xmx (par exemple, -Xmx512m peut spécifier la taille maximum de la heap à 512 Mo).

La dernière option que vous pouvez configurer est un dépôt privé Maven pour cette tâche de build. Normalement, Maven utilisera le dépôt Maven par défaut (usuellement le dossier .m2/repository dans le répertoire personnel de l’utilisateur). Parfois, cela peut mener à des interférences entre tâches de build, ou utiliser des versions snapshot inconsistantes d’un build à un autre. Pour être sûr que votre build est lancé dans des conditions de laboratoire, vous pouvez activer cette option. Votre tâche de build aura son propre dépôt privé, réservé pour son utilisation exclusive. Sur le plan négatif, la première fois que la tâche de build lancera un build, cela prendra du temps pour télécharger tous les artefacts Maven, et les dépôts privés peuvent prendre beaucoup de place. Cependant, c’est la meilleure façon de garantir que votre build est lancé dans un environnement vraiment isolé.

5.6.2. Les étapes de build Ant

Les tâches de build Freestyle fonctionnent également biens avec Ant. Apache Ant est un outil de scripting de build Java largement utilisé et bien connu. En effet, un nombre important de projets Java sont liés à des scripts de build Ant.

Ant n’est pas seulement utilisé comme un outil de build principal — même si votre projet utilise Maven, vous pouvez recourir à l’appel de scripts Ant pour faire des tâches spécifiques. Il y a des librairies Ant disponibles pour beaucoup d’outils de développement et des tâches bas niveau, comme utiliser SSH, ou travailler avec des serveurs d’application propriétaires.

Dans da forme la plus basique, configurer une étape de build Ant est très simple, en effet, il vous suffit de fournir la version de Ant que vous souhaitez utiliser et le nom de la target que vous voulez invoquer. Dans la Figure 5.27, “Configurer une étape de build Ant”, par exemple, nous invoquons un script Ant pour démarrer un script de test JMeter.

Configurer une étape de build Ant

Figure 5.27. Configurer une étape de build Ant


Comme dans une étape de build Maven, le bouton « Avancé… » vous fournit plus d’options détaillées, comme spécifier un script de build different, ou un script de build dans un répertoire différent (celui par défaut sera build.xml dans le répertoire racine). Vous pouvez aussi spécifier des propriétés et des options de la JVM, comme vous pouvez le faire pour Maven.

5.6.3. Exécuter une commande Batch Shell ou Windows

Occasionnellement, vous pouvez avoir besoin d’exécuter une commande directement au niveau du système d’exploitation. Certains processus de build anciens sont liés à des scripts spécifiques à l’OS, par exemple. Dans d’autres cas, vous pourriez avoir besoin d’effectuer un opérateur bas niveau qui serait plus facilement faite avec une commande au niveau OS.

Vous pouvez faire ceci avec Jenkins avec une commande Exécuter un script shell (pour Unix) ou Exécuter une ligne de commande batch Windows (pour Windows). Par exemple, dans la Figure 5.28, “Configurer une étape Exécuter un script Shell”, nous avons ajouté une étape pour exécuter la commande Unix ls.

Configurer une étape Exécuter un script Shell

Figure 5.28. Configurer une étape Exécuter un script Shell


La sortie de l’étape de build est montrée ici :

[workspace] $ /bin/sh -xe /var/folders/.../jenkins2542160238803334344.s
+ ls -al
total 64
drwxr-xr-x  14 johnsmart  staff   476 30 Oct 15:21 .
drwxr-xr-x   9 johnsmart  staff   306 30 Oct 15:21 ..
-rw-r--r--@  1 johnsmart  staff   294 22 Sep 01:40 .checkstyle
-rw-r--r--@  1 johnsmart  staff   651 22 Sep 01:40 .classpath
-rw-r--r--@  1 johnsmart  staff   947 22 Sep 01:40 .project
drwxr-xr-x   5 johnsmart  staff   170 22 Sep 01:40 .settings
-rw-r--r--@  1 johnsmart  staff   437 22 Sep 01:40 .springBeans
drwxr-xr-x   9 johnsmart  staff   306 30 Oct 15:21 .svn
-rw-r--r--@  1 johnsmart  staff  1228 22 Sep 01:40 build.xml
-rw-r--r--@  1 johnsmart  staff    50 22 Sep 01:40 infinitest.filters
-rw-r--r--   1 johnsmart  staff  6112 30 Oct 15:21 pom.xml
drwxr-xr-x   5 johnsmart  staff   170 22 Sep 01:40 src
drwxr-xr-x   3 johnsmart  staff   102 22 Sep 01:40 target
drwxr-xr-x   5 johnsmart  staff   170 22 Sep 01:40 tools

Vous pouvez soit exécuter une commande spécifique à l’OS (ex : ls), soit stocker un script plus compliqué comme un fichier dans votre gestionnaire de contrôle de version, et exécuter ce script. Si vous exécutez un script, vous n’avez juste qu’à faire référence au nom de votre script relativement par rapport au répertoire de travail.

Les scripts Shell sont exécutés en utilisant l’option -ex — les commandes sont affichées dans la console, comme si c’était la sortie. Si n’importe laquelle des commandes exécutées retourne une valeur différente de zéro, le build échouera.

Lorsque Jenkins exécute un script, il spécifie un nombre en tant que variable d’environnement que vous pouvez utiliser à l’intérieur de votre script. Nous discutons de ces variables plus en détail dans le prochaine section.

En réalité, il y a beaucoup de bonnes raisons pour lesquelles vous devriez éviter d’utiliser des scripts de niveau OS dans vos tâches de build si vous pouvez les éviter. En particulier, il rend votre tâche de build au meilleur des cas, spécifique à l’OS, et dans le pire dépendant de la configuration précise de la machine. Une alternative plus portable pour exécuter des scripts spécifiques à l’OS est d’écrire un script équivalent dans un langage de script plus portable, comme Groovy ou Gant.

5.6.4. Utiliser les variables d’environnement Jenkins dans vos builds

Une astuce utile qui peut être utilisée dans pratiquement n’importe quelle étape de build est d’obtenir des informations de la part de Jenkins sur la tâche de build courante. En réalité, lorsque Jenkins démarre une étape de build, il met à disposition les variables d’environnement suivantes dans le script de build :

BUILD_NUMBER

Le numéro du build courant, comme “153”.

BUILD_ID

Un horodatage pour identifier le build courant, sous le format YYYY-MM-DD_hh-mm-ss.

JOB_NAME

Le nom du job, comme game-of-life.

BUILD_TAG

Un moyen commode d’identifier la tâche de build courante, sous la forme jenkins-${JOB_NAME}-${BUILD_NUMBER} (ex : jenkins-game-of-life-2010-10-30_23-59-59).

EXECUTOR_NUMBER

Un nombre identifiant l’exécuteur ayant démarré cette construction parmi les exécuteurs sur la même machine. C’est le nombre que vous voyez dans « Etat du lanceur de construction », à l’exception que ce nombre commence de 0, pas 1.

NODE_NAME

Le nom de l’esclave si ce build est en train d’être lancé sur un esclave, ou "" si le build est en train d’être lancé sur le maître.

NODE_LABELS

La liste des libellés associés au nœud sur lequel le build est démarré.

JAVA_HOME

Si votre tâche est configurée pour utiliser une version spécifique de JDK, cette variable contient la valeur du JAVA_HOME correspondant au JDK spécifié. Lorsque cette variable est fixée, la variable PATH est aussi mise à jour pour avoir $JAVA_HOME/bin.

WORKSPACE

Le chemin absolu du répertoire de travail.

HUDSON_URL

L’URL complète du serveur Jenkins, par exemple http://ci.acme.com:8080/jenkins/.

JOB_URL

L’URL complète pour cette tâche de build, par exemple http://ci.acme.com:8080/jenkins/game-of-life.

BUILD_URL

L’URL complète de ce build, par exemple http://ci.acme.com:8080/jenkins/game-of-life/20.

SVN_REVISION

Pour les projets basés sur Subversion, cette variable contient le numéro de la révision courante.

CVS_BRANCH

Pour les projets basés sur CVS, cette variable contient la branche du module. Si CVS est configuré pour consulter le trunk, cette variable d’environnement ne sera pas spécifiée.

Ces variables sont faciles à utiliser. Dans un script Ant, vous pouvez y accéder avec le tag <property> comme montré ici :

<target name="printinfo">
  <property environment="env" />
  <echo message="${env.BUILD_TAG}"/>
</target>

Dans Maven, vous pouvez accéder au variables soit de la même manière (en utilisant le prefix « env. »), soit directement en utilisant la variable d’environnement Jenkins. Par exemple, dans le fichier pom.xml, l’URL du projet pointera sur la tâche de build Jenkins qui a lancé le build mvn site :

<project...>
  ...
  <groupId>com.wakaleo.gameoflife</groupId>
  <artifactId>gameoflife-core</artifactId>
  <version>0.0.55-SNAPSHOT</version>
  <name>gameoflife-core</name>
  <url>${JOB_URL}</url>

Alternativement, si vous construises une application web, vous pouvez aussi utiliser maven-war-plugin pour insérer le numéro de la tâche de build dans le manifest de l’application web, ex :

<project>
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <configuration>
          <manifest>
            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
          </manifest>
          <archive>
            <manifestEntries>
              <Specification-Title>Continuous Integration with Hudson (French Content)</Specification-Title>
              <Specification-Version>0.0.4-SNAPSHOT</Specification-Version>
              <Implementation-Version>${BUILD_TAG}</Implementation-Version>
            </manifestEntries>
          </archive>
        </configuration>
      </plugin>
      ...
    </plugins>
  </build>
  ...
</project>

Cela produire un fichier MANIFEST.MF avec les lignes suivantes :

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: johnsmart
Build-Jdk: 1.6.0_22
Jenkins-Build-Number: 63
Jenkins-Project: game-of-life
Jenkins-Version: 1.382
Implementation-Version: jenkins-game-of-life-63
Specification-Title: gameoflife-web
Specification-Version: 0.0.55-SNAPSHOT

Dans un script Groovy, elles peuvent être accéder via la méthode System.getenv() :

def env = System.getenv()
env.each {
    println it
}

ou :

def env = System.getenv()
println env['BUILD_NUMBER']

5.6.5. Exécuter des scripts Groovy

Groovy n’est pas seulement un langage dynamique populaire de la JVM, c’est aussi un langage qui convient pour le scripting de bas niveau. Le plugin Groovy de Jenkins vous permet d’exécuter des commandes Groovy arbitraires, ou invoquer des scripts Groovy, dans le cadre de votre processus de build.

Une fois que vous avez installé le plugin Groovy avec la manière habituelle, vous aurez besoin d’ajouter une référence de votre installation Groovy dans la page de configuration du système (voir la figure Figure 5.29, “Ajouter une installation Groovy à Jenkins”).

Ajouter une installation Groovy à Jenkins

Figure 5.29. Ajouter une installation Groovy à Jenkins


Maintenant, vous pouvez ajouter du script Groovy dans votre tâche de build. Lorsque vous cliquez sur ‘Ajouter une étape de build’, vous verrez deux nouvelles entrées dans le menu déroulant : « Exécuter un script Groovy » et « Exécuter un script Groovy Système ». La première option est généralement celle que vous souhaitez — cela exécutera simplement un script Groovy dans une JVM séparée, comme si vous l’invoquiez depuis la ligne de commande. La deuxième option lance des commandes Groovy depuis la JVM de Jenkins, avec un accès interne complet à Jenkins, et est principalement utilisé pour manipuler les tâches de build de Jenkins ou le processus de build lui-même. C’est un sujet plus avancé dont nous discuterons plus loin dans ce livre.

Une étape de build Groovy peut prendre une forme sur deux. Pour les cas simples, vous pouvez juste ajouter un petit bout de Groovy, comme montré dans la Figure 5.30, “Lancer des commandes Groovy dans le cadre d’une tâche de build”. Pour les cas plus complexes ou compliqués, vous pouvez probablement écrire un script Groovy et le placer sous un système de contrôle de version. Une fois que votre script est en sûreté dans votre SCM, vous pouvez le démarrer en sélectionnant l’option « Fichier de script Groovy » et fournir le chemin de votre script (relatif au répertoire de travail de la tâche de build).

Lancer des commandes Groovy dans le cadre d’une tâche de build

Figure 5.30. Lancer des commandes Groovy dans le cadre d’une tâche de build


Dans la Figure 5.31, “Lancer des scripts Groovy dans le cadre d’une tâche de build”, vous pouvez voir un exemple légèrement plus compliqué. Ici nous lançons un script Groovy appelé run-fitness-tests.groovy, qui peut être trouvé dans le répertoire scripts. Ce script prend des suites de test pour être exécutés comme ses paramètres — nous pouvons les mettre dans le champ Paramètres Groovy. Sinon vous pouvez aussi fournir des propriétés en ligne de commande dans le champ Propriétés — c’est simplement un moyen plus pratique d’utiliser l’option -D en ligne de commande pour passer des valeurs de propriétés au script Groovy.

Lancer des scripts Groovy dans le cadre d’une tâche de build

Figure 5.31. Lancer des scripts Groovy dans le cadre d’une tâche de build


5.6.6. Construire des projets dans d’autres langages

Jenkins est un outil flexible, il peut être utilisé avec beaucoup plus de de langage que Java et Groovy. Par exemple, Jenkins fonctionne aussi très bien avec Grails, .Net, Ruby, Python et PHP, juste pour en nommer quelques uns. En utilisant d’autres langages, vous aurez généralement besoin d’installer un plugin supportant votre langage favori, qui ajoutera un nouveau type d’étape de build pour ce langage.Nous regarderons d’autres exemples dans la section Section 5.10, “Utiliser Jenkins avec d’autres langages”.