Niveau 2 : Intégration continue avec Gitlab CI
Auteurs
Assemblé et rédigé par Martin Souchal

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
Introduction
L'intégration continue est une méthode de développement de logiciel DevOps avec laquelle les développeurs intègrent régulièrement leurs modifications de code à un référentiel centralisé, suite à quoi des opérations de création et de test sont automatiquement menées. L'intégration continue désigne souvent l'étape de création ou d'intégration du processus de publication de logiciel, et implique un aspect automatisé (un service d'IC ou de création) et un aspect culturel (apprendre à intégrer fréquemment). Les principaux objectifs de l'intégration continue sont de trouver et de corriger plus rapidement les bogues, d'améliorer la qualité des logiciels et de réduire le temps nécessaire pour valider et publier de nouvelles mises à jour de logiciels. AWS
Le but de ce TP est de mettre en place un mécanisme d'intégration continue sous Gitlab dans le but d'automatiser la création d'un conteneur pour une application Django, de générer de la documentation et d'effectuer des tests de qualité sur le code.
Création d'une application Django
Commencez par créer un répertoire vide.
On va ensuite créer un environnement virtuel python dans ce répertoire :
Maintenant activez cet environnement virtuel :
Votre prompt doit maintenant commencer par (django-venv).
Pour vérifier que votre environnement est bien actif, la commande which python doit renvoyer un chemin dans le dossier actuel.
Si tout est bon, on peut maintenant installer Django :
On va maintenant initialiser un projet Django, ici on va l'appeller tp :
Si tout s'est bien passé, vous devez maintenant avoir un répertoire tp qui contient un fichier manage.py. Tapez la commande python tp/manage.py runserver pour lancer Django. Vous pouvez maintenant ouvrir un navigateur sur l'adresse http://127.0.0.1:8000/ et admirer la fusée Django.
On va ensuite personnaliser un peu le code pour afficher le message "Hello, World!". Commencez par créer une application, que l'on va appeller hello dans le projet Django :
Django à automatiquement crée un répertoire nommé hello qui va contenir le code de notre application. On va ajouter les fichiers suivants :
django-tp/tp/hello/urls.py
django-tp/tp/hello/views.py
et enfin
django-tp/tp/tp/urls.py
Maintenant, si tout va bien, vous pouvez lancer le serveur Django qui doit afficher un magnifique "Hello, World!" sur la page http://127.0.0.1:8000/ :
Nous avons maintenant un code en python, utilisant le framework django en local. La prochaine étape, c'est de versionner ce code via git, et ensuite de l'envoyer sur le serveur GitLab.
Gitlab
Commencez par vous connecter sur Gitlab puis créez un nouveau dépot. Ajoutez ensuite votre code dans ce dépôt.
Ajout du code Django dans git
Pour ajouter un répertoire existant dans gitlab, il faut d'abord transformer le répertoire en dépôt git, puis l'envoyer sur gitlab :
Mise en place de l'intégration continue

Dans Gitlab, la configuration de l'intégration continue se fait dans un fichier texte qui doit impérativement être nommé .gitlab-ci.yml et doit être situé à la racine du code. Ce fichier contient la liste des actions à mener à chaque push sur le dépot git et doit être rédigé dans le langage YAML (attention, ce langage est particulièrement sensible à l'indentation du code). Ces actions seront executées sur un "gitlab-runner", c'est à dire un serveur connecté à Gitlab et qui offre au moins le service docker. L'ensemble des actions définies dans ce fichier constitue un pipeline. En général un pipeline se décompose en trois étapes :
- build
- test
- deploy
Il n'est cependant pas obligatoire d'utiliser ces trois étapes. Dans l'interface Gitlab il est possible de voir l'état des différentes étapes d'un pipeline, ainsi que les logs d'execution. Si il n'y a aucune erreur dans un pipeline, il apparait en vert. Dans le cas contraire, il sera en rouge avec une croix. En cas d'erreur, il est utile de consulter les logs dans Gitlab.
Commencons par créer un fichier .gitlab-ci.yml avec le contenu suivant :
Ajoutez ensuite le fichier dans Git :
Puis on commit et on push les modifs dans gitlab :
Rendez vous ensuite dans Gitlab, il doit y avoir un pipeline qui s'est lancé automatiquement suite au push. Pour vérifier, allez dans "CI/CD" dans le menu de gauche, puis dans "Pipelines". Il doit y avoir un pipeline correspondant à votre commit. Cliquez sur le statu du pipeline pour accèder aux logs d'execution. Le log devrait ressembler à cela :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
Si vous faites un nouveau commit et un nouveau push, sans modifier le fichier .gitlab-ci.yml vous aurez le même résultat : en effet nous nous contentons d'afficher un message, sans lien avec notre code gitlab.
Automatiser la création d'un conteneur
Un des interêts majeurs de l'intégration continue est de permettre d'automatiser la création de conteneurs Docker. En effet, une fois l'image Docker configurée, seul le code de l'application change : l'idée est donc de régenerer l'image Docker dans un dépot a chanque nouvelle modification de code. Ca tombe bien : Gitlab embarque son propre dépot Docker.
Nous allons dans un premier temps écrire un Dockerfile qui servira à créer un conteneur Docker qui sera en mesure de faire tourner notre application. Là encore Gitlab peut nous aider : allez dans le dossier tp dans l'interface web Gitalb et cliquez sur ajouter un nouveau fichier (c'est le petit plus a coté de la branche en cours dans le panneau de droite), ensuite choisissez le template "Dockerfile", puis "Python". Vous aurez alors un fichier avec ce contenu :
Le Dockerfile généré contient le minimum necessaire pour faire tourner une application Django : nous avons juste besoin d'un fichier requirements.txt pour pouvoir installer les dépendances python. Pour générer ce fichier, lancez la commande suivante depuis votre environnement virtuel python, toujours dans le repertoire tp (qui contient le fichier manage.py :
Ensuite on peut passer à la création de l'image Docker :
Si le build s'est bien passé, il devrait y avoir le message suivant :
1 2 | |
Pour tester le conteneur, il faut lancer l'image que l'on vient de créer :
Véifiez que le message "Hello World" s'affiche bien dans un navigateur à l'adresse http://127.0.0.1:8000/
Votre application est conteneurisée !
Maintenant, nous allons faire la même chose, mais de manière automatique pour que lors de chaque modification du code, Gitlab construise lui-même le conteneur. Pour cela nous avons besoin de modifier à nouveau le fichier .gitlab-ci.yml :
Avec cet exemple nous avons défini une étape appellée docker-build dans laquelle nous allons utiliser docker dans un conteneur docker (dind pour docker in docker afin de pouvoir construire notre image (docker build) et l'envoyer sur le registre Gitlab de notre projet (docker push). Comme ce projet est privé, nous avons besoin de nous authentifier au préalable (docker login).
Les variables en majuscules sont des variables d'environnement Gitlab prédéfinies, comme le nom d'utilisateur ou le mot de passe gitlab. Pour avoir la liste de ces variables, consultez la documentation.
Si le pipeline se termine sans erreur, votre conteneur docker est maintenant disponible dans le registre du projet : allez vérifier dans "Packages & Registries" -> "Container Registry".
Vous pouvez maintenant lancer votre conteneur sur n'importe quelle machine avec la commande pull :
Avec cette commande, docker va rapatrier l'image depuis gitlab et la lancer sur votre machine. Vérifiez que votre application est bien accessible à l'adresse http://127.0.0.1:8000/
Testons notre pipeline en modfiant le code : par exemple, changez le texte dans tp/hello/views.py, faites un commit et push. Une fois le pipeline terminé, relancez la commande docker run, en faisant un pull d'abord pour mettre a jour le conteneur.
Générer et publier la documentation
Ici nous allons générer une documentation au format HTML et la publier sur gitlab pages pour pouvoir y accéder via un navigateur web. Pour générer la documentation, nous allons utiliser le logiciel doxygen qui va analyser le code source python et automatiquement générer de la documentation.
Pour commencer, il faut créer un fichier de configuration pour Doxygen. Ce fichier pré-rempli est disponible dans le dépôt git : files/niveau2/Doxyfile : copiez le dans un dossier doxygen à la racine de votre projet django.
On va ensuite ajouter une étape dans le pipeline CI/CD de gitlab en modifiant le fichier .gitlab-ci.yml. Comme le but est de générer des fichiers html, on va utiliser le mot clé pages pour spécifier qu'on utilise le plugin "gitlab pages" qui permet de publier des pages html statiques sur un serveur web intégré dans Gitlab.
Comme dans la première partie, l'idée est de spécifier une image docker et d'installer le logiciel Doxygen dans cette image afin de générer les fichiers html. Appellons cette étape deploy :
Le fichier .gitab-ci.yml doit maintenant ressembler à cela :
Nous avons maintenant un pipeline en deux étapes qui construit automatiquement une image docker et ensuite génère une dcoumentation en ligne. Pour visualiser cette documentation, une fois que le pipeline s'est exécuté avec succès, il faut aller dans l'interface web Gitlab et dans le menu de gauche -> Settings -> Pages. Cliquez sur le lien pour voir votre documentation.
Il est également possible de télécharger les fichiers html générés via l'artifact défini dans .gitab-ci.yml. Pour cela il faut aller dans l'interface Gitlab puis dans jobs.
Effectuer des test
La dernière partie de notre pipeline va effectuer des tests sur l'application ; c'est à dire que l'on va vérifier automatiquement si notre application réponds bien à son cahier des charges : ici notre application doit afficher un texte en html à la racine du serveur. C'est un cas simple à tester avec django.
Configuration des tests : éditez le fichier hello/tests.py comme ceci.
Ce code va vérifier que le code réponse http soit bien 200 lorsque'on fait une requête sur la racine (/) du serveur web. Pour lancer ce test, la commande django est la suivante :
Vous pouvez vérifier que le test tourne en local sur votre machine.
Nous allons modifier notre fichier .gitab-ci.yml pour ajouter cette dernière étape :
Le fichier .gitab-ci.yml doit maintenant ressembler à cela :
Pour afficher le résultat des tests il faut se rendre dans l'interface web gitlab, et ensuite dans l'étape de test du pipeline. Il est également possible d'afficher le résultat des tests ou le coverage dans des badges gitlab.
Si les tests sont vérifiés, cela veut dire que l'application répond bien à son cahier des charges, elle peut être déployée automatiquement. Cela permet de pousser les modifications en production dès qu'elles sont implémentées et ainsi de gagner du temps pour proposer directement aux utilisateurs les nouvelles fonctionnalités. Il est important de tester tout le code, ainsi que la sécurité du code lorsque que l'on travaille ainsi.
Au travers de ce TP nous avons vu des cas simple de pipelines. Pour aller plus loin et connaitre toutes les possibilités qui sont proposées il vous est conseillé de visiter la documentation officielle de Gitlab.
Pour aller plus loin
Sur des pipelines très long, il devient nécessaire d'utiliser des conditions pour ne pas lancer tout ou partie des jobs à chaque commit. Par exemple, pour ne lancer les tests que lors d'un commit sur la branche master on utilise le mot clé only :
Un autre moyen de limiter les jobs est de lancer les jobs manuellement. Ainsi, a chaque commit l'utilisateur aura le choix de lancer, ou non, un ou plusieurs jobs. Testons avec le job de test :
Il faut ensuite aller dans l'interface Gitlab, puis dans Pipelines pour lancer le job.
Sinon il est également possible de mettre les mots clés [ci skip] ou [skip ci] dans un message de commit pour ne pas lancer la CI du tout.