• 10 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 20/04/2023

Compilez et testez votre code en continu

Dans ce chapitre, nous allons utiliser GitLab afin d’implémenter les différentes étapes de l’intégration continue pour garantir que notre code fonctionne à tout moment. Vous allez commencer par implémenter les étapes de compilation et de tests.

Lors de la création d’un repository sur Gitlab, est créée par défaut une branche principale appelée main. Même s’il existe des notions de branche, la création d’une branche doit être évitée le plus possible, privilégiant le développement sur la branche principale ; cela évite de maintenir plusieurs versions en parallèle. Ce genre de pratique est appelé trunk-based development.

Le trunk-based development se compose d'une branche principale et de branches éphémères que l'on merge ensuite sur la branche principale.
Exemple de trunk-based development

Si l’utilisation du trunk-based development n’est pas possible pour votre équipe, une autre approche possible est d’utiliser ce qu’on appelle des feature branches. Le principe d’une feature branch est de créer une branche pour chaque nouvelle fonctionnalité que l’on veut ajouter dans l’application, avant de merger celle-ci dans la branche principale à la fin du développement de la fonctionnalité. Ces feature branches permettent alors à chaque développeur de pouvoir travailler indépendamment les uns des autres, sans que leur développement n’impacte négativement les autres.

Le principe d’une feature branch est de créer une branche pour chaque nouvelle fonctionnalité que l’on veut ajouter dans l’application, avant de merger celle-ci dans la branche principale à la fin du développement de la fonctionnalité.
Exemple de feature branches (GitFlow)

Clonez le projet sur votre poste

Pour pouvoir commencer à travailler sur le projet Gitlab, afin de récupérer le code source, nous allons dans un premier temps cloner le repository Git. Je vous invite à suivre les instructions de la vidéo ci-dessous. 

Avec ces manipulations, nous avons appris comment cloner de manière sécurisée notre repository sur notre poste de travail afin de commencer les développements que l’on a planifiés précédemment.

Activez l’intégration continue sur votre projet avec GitLab

Nous allons maintenant ajouter un pipeline d’intégration continue, afin d’implémenter les différentes étapes que nous avons vues précédemment. Les phases de ce pipeline seront lancées successivement, lors de chaque nouveau push du code sur le repository. Voici à quoi ressemblera le pipeline :

Les étapes à mettre en place sont : build, test, quality, package.
Les étapes que nous allons mettre en place

Pour activer l’intégration continue sur GitLab, le plus simple est de cliquer sur le bouton Set up CI/CD sur la page d’accueil du projet. Cette commande va créer le fichier gitlab-ci.yml dans votre projet. C’est sur ce fichier que vous décrirez tout votre pipeline CI/CD avec la syntaxe YAML.

Puis ajouter les lignes suivantes dans le fichier :

stages:
 - build
 - test

cache:
 paths:
   - .m2/repository
 key: "$CI_JOB_NAME"

build_job:
  stage: build
  image: eclipse-temurin:17-jdk-alpine
  script:
    - ./mvnw compile
      -Dhttps.protocols=TLSv1.2
      -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository
      -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN
      -Dorg.slf4j.simpleLogger.showDateTime=true
      -Djava.awt.headless=true
      --batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true

test_job:
  stage: test
  image: eclipse-temurin:17-jdk-alpine
  script:
    - ./mvnw test
      -Dhttps.protocols=TLSv1.2
      -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository
      -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN
      -Dorg.slf4j.simpleLogger.showDateTime=true
      -Djava.awt.headless=true
      --batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true

Ce fichier est la pierre angulaire de l’implémentation d’un pipeline dans GitLab. Ce fichier s’appelle.gitlab-ci.ymlet c’est ici que nous allons définir notre pipeline. Dans cet exemple, nous avons implémenté deux étapes :

  • l’étape de compilation avec la tâchebuild_job;

  • l’étape des tests avec la tâche test_job.

Découvrons maintenant le fichier bloc par bloc.

Définissez les étapes du pipeline

Dans un premier temps, je définis les étapes de mon pipeline avec le mot cléstages. Ce mot clé permet de définir l’ordre des étapes. Ici, la première étape va être lebuildet ensuite lestests

Ça veut dire que les tâches (ou jobs en anglais) associées à l’étapebuild(icibuild_job) vont s’exécuter en premier, puis les tâches de l’étapetest(icitest_job).

Accélérez les étapes avec le cache

Le deuxième bloc, avec le mot clécache, est utilisé pour accélérer toutes nos étapes. Effectivement, dans le cas d’une compilation Java avec Maven (notre cas), cette compilation récupère beaucoup de dépendances et de librairies externes. Ces librairies sont stockées dans le répertoire.m2.

Grâce à l’utilisation du mot clécacheet de la variable prédéfinie de GitLab$CI_JOB_NAME, ce répertoire est commun à tous les jobs du pipeline.

Définissez les jobs à effectuer

Ensuite, je déclare deux jobs, correspondant chacun à une des étapes de notre pipeline d’intégration continue. Dans ces deux jobs, nous voyons que nous avons trois lignes différentes. Découvrons à quoi ces lignes correspondent :

  • stage: c’est le nom de l’étape qui va apparaître dans notre pipeline d’intégration continue. Cela correspond aussi austageauquel sera exécuté le job ;

  • script: ce sont les lignes de script à lancer afin d’exécuter l’étape. Ici, nous lançons le script Maven suivant son lifecycle. Dans la partiebuild, nous lançons la compilation et dans la partietest, nous lançons les tests de l’application. D’autres options sont définies afin d’accélérer le temps de traitement de ces lignes. Lescriptva alors télécharger Maven, l’outil de compilation, toutes les dépendances de l’application, et lancer la compilation du projet ;

  • image: c’est l’image Docker qui va être lancée par GitLab afin d’exécuter les lignes de script que nous avons définies. Ici, l’imageeclipse-temurin:17-jdk-alpine, qui contient déjà Java 17, va être lancée afin de pouvoir compiler le projet. Une fois le fichier sauvegardé, le pipeline de build se lance et vous devriez voir les différentes étapes se lancer (ici, l’étape de build et l’étape de test).

Lors de l’étape detest, le pipeline va exécuter les tests unitaires déjà présents au sein du projet. L’objectif de cette étape est de s’assurer de lancer les tests écrits par les développeurs. Si un seul de ces tests échoue, le pipeline s’arrête.

Ces tests doivent s’exécuter de la manière la plus rapide possible, afin d’avoir un feedback le plus rapide lui aussi. Pour arriver à ce niveau, il est nécessaire que les tests unitaires n’aient aucune dépendance vis-à-vis de systèmes externes, comme une base de données ou même le système de fichiers de la machine.

Les tests unitaires apportent trois atouts à la production :

  • trouver les erreurs plus facilement. Les tests sont exécutés durant tout le développement, permettant de visualiser si le code fraîchement écrit correspond au besoin ;

  • sécuriser la maintenance. Lors d’une modification d’un programme, les tests unitaires signalent les éventuelles régressions. En effet, certains tests peuvent échouer à la suite d’une modification, il faut donc soit réécrire le test pour le faire correspondre aux nouvelles attentes, soit corriger l’erreur se situant dans le code ;

  • documenter le code. Les tests unitaires peuvent servir de complément à la documentation ; il est très utile de lire les tests pour comprendre comment s’utilise une méthode. De plus, il est possible que la documentation ne soit plus à jour, mais les tests, eux, correspondent à la réalité de l’application.

L’ensemble des tests unitaires doit être relancé après une modification du code, afin de vérifier qu’il n’y ait pas de régressions (l’apparition de nouveaux dysfonctionnements).

Si les tests échouent, le rôle du développeur est alors de :

  • soit corriger le test qu’il a écrit, car la fonctionnalité a évolué et le test ne correspond plus ;

  • soit faire évoluer le code, car le test a détecté un bug.

Il existe d’autres types de tests à lancer, qui dépendent des environnements où l’application est déployée, comme les tests de performance ou d’acceptation utilisateur en préproduction ; ou encore les smoke tests en production afin de garantir le fonctionnement normal de l’application en production.

Il y a de nombreux tests à effectuer à chaque étape de la CI/CD.
Les différents tests à lancer à chaque étape de la CI/CD

Lancez votre pipeline CI/CD

Pour voir le pipeline complet, il suffit de cliquer sur le sous-menu Pipelines dans le menu CI/CD.

La liste des exécutions du pipeline.
La page Pipeline avec toutes les exécutions du pipeline

En cliquant sur le statut running du pipeline, nous avons plus de détails sur ce pipeline, les jobs associés ainsi que leurs statuts.

Le détail d'exécution du pipeline donne les détails du pipeline, avec les jobs associés et leurs statuts.
Détail d’exécution du pipeline

Corrigez les bugs de votre application

Afin de démontrer la valeur d’un workflow typique de CI/CD, nous allons introduire un bug dans l’application. Ainsi, nous verrons comment le pipeline de CI/CD le détecte et le corrige. Suivez les étapes dans la vidéo ci-dessous. 

Dans ce screencast, vous avez modifié un fichier sur votre poste en local. Une fois ce fichier modifié, vous avez poussé vos changements et constaté le lancement du pipeline. Le fichier poussé contenait intentionnellement un bug afin de voir comment créer un bug associé à un statut de pipeline non réussi. Vous avez enfin modifié de nouveau le fichier afin de corriger le bug et poussé les changements sur une nouvelle branche afin de pouvoir faire une Merge Request et voir le bug corrigé automatiquement lors du succès du pipeline.

En résumé

  • Le pipeline d’intégration continue permet d’implémenter les étapes de la CI dans GitLab.

  • Pour implémenter le pipeline, il faut définir ses étapes, les accélérer avec le cache et définir les jobs à effectuer. 

  • Lors de l’étape de test, le pipeline exécute les tests unitaires existants au sein du projet.

  • Le pipeline de CI/CD détecte les bugs et les corrige. 

Maintenant que vous avez intégré et testé votre code, vous allez pouvoir mettre en place les deux dernières étapes de l’intégration continue dans le chapitre suivant.

Exemple de certificat de réussite
Exemple de certificat de réussite