Je me suis mis récemment à utiliser GitLab CI pour mes sides projects. Dans le but de build mes images docker, les tester et les déployer. Le tout de manière automatisée.
Utilisant déjà GitLab comme repository, je me suis dit pourquoi pas exploiter cet outil à fond, notamment avec la partie CI/CD.
Vous l’aurez compris, dans cet article, je vous emmène à la découverte de GitLab CI. 😃
Qu’est-ce qu’un pipeline CI/CD ?
Avant de rentrer dans le vif du sujet, je pense qu’il est pertinent de mettre une définition sur ce qu’est un pipeline CI/CD.
Globalement, cela va nous aider à automatiser le processus de livraison de nos applications, en passant par plusieurs étapes bien orchestrées. On retrouve généralement le schéma suivant :
L’intégration continue (Continuous Integration ou encore CI) représente toutes les étapes nécessaires pour automatiser le build et le packaging d’une application. Le déploiement continu (Continuous Delivery/Deployment ou encore CD) a pour but de déployer les applications en toute sécurité (même jusqu’en production 😜).
Je ne rentre pas plus dans le détail. Je ferais sûrement un article plus complet sur le sujet.
Si toutefois, vous souhaitez en savoir plus, je vous invite à consulter cet article.
Le fonctionnement et les composants de GitLab CI
Il y a 3 composants principaux :
- Le pipeline
- Les stages
- Les jobs
Ces différents éléments se complètent et s’imbriquent parfaitement. Tout d’abord, nous avons notre pipeline, composé d’un ou plusieurs stages qui eux même contiennent les jobs.
Ils sont regroupés au sein d’un fichier .gitlab-ci.yaml généralement placé à la racine de votre repository.
Nous pouvons faire l’analogie avec une recette de cuisine. Imaginons que nous souhaitions réaliser un gâteau au chocolat 🍫.
Notre recette sera notre pipeline. Les différentes étapes de celle-ci (comme : préparer la pâte, préchauffer le four etc) : nos stages. Pour chaque étape nous allons avoir des instructions à suivre pour réussir notre dessert : les jobs. Le gâteau, sera notre résultat final.
Dans les prochaines sections, je détaillerai le rôle de chacun de ces composants.
Les jobs
Aussi appelé “build step”, sont des actions qui vont être exécutées. La clause script est obligatoire, c’est elle qui contient les commandes à lancer. Par exemple, cela peut être des commandes pour build des images docker, compiler un programme, lancer des tests… Bref, tout ce que l’on pourrait lancer à la main.
Ci-dessous un exemple de job en reprenant l’analogie du dessert au chocolat :
préparation de pâte:
script:
- Dans une casserole, faire fondre le chocolat et le beurre à feu doux
- Dans un saladier, ajoutez le sucre, les oeufs, la farine
- Mélanger les ingrédients
- Ajoutez le mélange chocolat/beurre dans le saladier
- Mélange
Les stages
Au sens GitLab, ils représentent une étape au sein d’un pipeline. C’est lui qui contient le ou les jobs qui vont s’exécuter.
À noter également que les stages s’exécutent en série, uniquement si le précédent a réussi.
Voici un exemple de 3 stages (nécessaire pour la réalisation de notre délicieux gâteau au chocolat) :
stages:
- Préchauffer le four
- Préparer de la pâte
- Cuire le gâteau
- Servir le gâteau
En prenant l’exemple précédant, lorsque tous les jobs contenus dans le stage Préchauffer le four ont réussis, GitLab va exécuter les jobs présents dans le stage Préparation de la pâte et ainsi de suite.
Le pipeline
Au plus haut niveau, nous avons notre pipeline. Il est chargé d’orchestrer les stages et les jobs. Ils sont déclenchés automatiquement lorsqu’un nouveau commit est poussé sur le repository qui contient le fichier .gitlab-ci.yaml. Il va ensuite exécuter tous les jobs qui sont renseignés dans les stages.
Voici notre pipeline complet pour réaliser le meilleur gâteau au chocolat du monde 😇:
stages:
- Préchauffer le four
- Préparer de la pâte
- Cuire le gâteau
- Servir le gâteau
Préparer le four:
stage: Préchauffer le four
script:
- Préchauffer le four à 180°C (thermostat 6)
Confection de la pâte à gâteau:
stage: Préparer de la pâte
script:
- Dans une casserole, faire fondre le chocolat et le beurre à feu doux
- Dans un saladier, ajoutez le sucre, les œufs, la farine
- Mélanger les ingrédients
- Ajoutez le mélange chocolat/beurre dans le saladier
- Mélanger
Mettre le gâteau à cuire:
stage: Cuire le gâteau
script:
- Cuire au four environ 20 minutes
Servir une part de gâteau à Paul:
stage: Servir le gâteau
script:
- Couper une part
- Prendre une assiette
- Déposer la part de gâteau dans l'assiette
- Donner l'assiette à Paul
Servir une part de gâteau à Pierre:
stage: Servir le gâteau
script:
- Couper une part
- Prendre une assiette
- Déposer la part de gâteau dans l'assiette
- Donner l'assiette à Pierre
Pour terminer sur le fonctionnement de GitLab CI, il est important de savoir qu’il y a une partie GitLab Server qui héberge le code et l’interface graphique. Les Runners GitLab eux, exécutent les jobs.
Quelques tips and tricks
Jobs templates et extends
Si vous avez l’œil, dans le pipeline précédant, nous avons deux étapes qui se répètent. Mise à part la personne à qui nous donnons le morceau de gâteau, les instructions sont identiques. Il est possible de factoriser cela en utilisant des modèles (templates).
Les jobs qui commencent par un . (par exemple .Servir_une_part_de_gâteau) sont considérés comme des templates. Ils n’apparaîtront pas dans le pipeline, mais ils seront appelés via extends.
.Servir_une_part_de_gâteau:
script:
- couper une part
- prendre une assiette
- déposer la part de gâteau dans l'assiette
- donner l'assiette à $NAME
Servir une part de gâteau à Paul:
stage: Servir le gâteau
variables:
NAME: Paul
extends: .Servir_une_part_de_gâteau
Servir une part de gâteau à Pierre:
stage: Servir le gâteau
variables:
NAME: Pierre
extends: .Servir_une_part_de_gâteau
Avec extends nous avons réussi à factoriser la distribution des parts de gâteau. Il nous suffit à présent de déclarer le nom de la personne à qui il faut les donner. Toutes les autres instructions seront exécutées par défaut (en fonction du template renseigné via extends).
Variables
Dans l’exemple précédent, j’ai introduit l’utilisation de variables. Elles me permettent de rendre plus dynamique et flexible notre pipeline. Je l’ai initialisé directement dans le stage. Pour des variables plus sensibles, typiquement des mots de passe, des tokens ou des clés privées, il n’est pas recommandé de les déclarer directement dans le fichier .gitlab-ci.yaml. Celles-ci se retrouveraient en clair, à la vue de tous.
GitLab à une section qui nous permet d’ajouter des variables, est de les masquer afin qu’elles ne soient jamais affichées.
Before_script
Cette directive permet de déclarer des instructions qui seront exécutées avant celles présentes dans script.
Pour imager, reprenons notre gâteau au chocolat. Avant de préparer la pâte, il serait judicieux de s’assurer d’avoir tous les ingrédients, les quantités et les ustensiles non ? 😁
Voici comment procéder :
Confection de la pâte à gâteau:
stage: Préparation de la pâte
before_script:
- 200g de chocolat pâtissier
- 100g de beurre
- 50g de farine
- 100g de sucre
- 3 oeufs
- 1 moule à gâteau
- 1 casserole
script:
- Dans une casserole, faire fondre le chocolat et le beurre à feu doux
- Dans un saladier, ajoutez le sucre, les oeufs, la farine
- Mélanger les ingrédients
- Ajoutez le mélange chocolat/beurre dans le saladier
- Mélanger
Artefacts
D’après la documentation de GitLab, les artefacts sont des fichiers que l’on veut garder d’un stage à l’autre. Par défaut, les jobs des stages ultérieurs téléchargeront automatiquement les artefacts créés dans les jobs précédents.
Reprenons notre gâteau. Une fois qu’il est cuit, pour distribuer les parts, il faut que les jobs contenus dans les stages Servir le gâteau aient accès à celui-ci.
Mettre le gâteau à cuire:
stage: Cuire le gâteau
script:
- Cuire au four environ 20 minutes
artefacts:
paths:
- gâteau
.Servir_une_part_de_gâteau:
script:
- couper une part de gâteau
- prendre une assiette
- déposer la part de gâteau dans l'assiette
- donner l'assiette à $NAME
Servir une part de gâteau à Paul:
stage: Servir le gâteau
variables:
NAME: Paul
extends: .Servir_une_part_de_gâteau
Servir une part de gâteau à Pierre:
stage: Servir le gâteau
variables:
NAME: Pierre
extends: .Servir_une_part_de_gâteau
Images
Les Runners GitLab exécutent les jobs dans des images Docker. Il est souvent utile d’en déclarer. Vous pouvez renseigner une image par défaut, dans ce cas, tous les jobs seront exécutés à partir de celle-ci. Soit, en fonction des différents stages, vous n’avez pas les mêmes besoins donc vous souhaiterez appeler plusieurs images Docker d’un stage à l’autre.
Dans notre exemple de gâteau, il serait pratique de commencer la recette avec tous les ingrédients sans se poser de questions ni d’avoir besoin de les renseigner (comme nous l’avons fait avec before_script). Imaginons une image Docker embarquant tous nos ingrédients avec les bonnes quantités. Par exemple :
Confection de la pâte à gâteau:
stage: Préparation de la pâte
image: ingredientsGâteau:6personnes
script:
- Dans une casserole, faire fondre le chocolat et le beurre à feu doux
- Dans un saladier, ajoutez le sucre, les oeufs, la farine
- Mélanger les ingrédients
- Ajoutez le mélange chocolat/beurre dans le saladier
- Mélanger
Pipeline complet
stages:
- Préchauffer le four
- Préparer de la pâte
- Cuire le gâteau
- Servir le gâteau
Préparer le four:
stage: Préchauffer le four
script:
- Préchauffer le four à 180°C (thermostat 6)
Confection de la pâte à gâteau:
stage: Préparer de la pâte
image: ingredientsGâteau:6personnes
script:
- Dans une casserole, faire fondre le chocolat et le beurre à feu doux
- Dans un saladier, ajoutez le sucre, les oeufs, la farine
- Mélanger les ingrédients
- Ajoutez le mélange chocolat/beurre dans le saladier
- Mélanger
Mettre le gâteau à cuire:
stage: Cuire le gâteau
script:
- Cuire au four environ 20 minutes
artefacts:
paths:
- gâteau
.Servir_une_part_de_gâteau:
script:
- couper une part de gâteau
- prendre une assiette
- déposer la part de gâteau dans l'assiette
- donner l'assiette à $NAME
Servir une part de gâteau à Paul:
stage: Servir le gâteau
variables:
NAME: Paul
extends: .Servir_une_part_de_gâteau
Servir une part de gâteau à Pierre:
stage: Servir le gâteau
variables:
NAME: Pierre
extends: .Servir_une_part_de_gâteau
Si vous souhaitez voir des pipelines qui font autre chose que des gâteaux aux chocolats, je vous invite à aller sur mon profil GitLab. J’ai 2 projets assez intéressants :
- Mon projet Freecodecamp-gitlab-ci
- Mon projet Eazytraining
GitLab propose des templates de fichiers .gitlab-ci.yaml
Conclusion
Étant habitué à Jenkins, GitLab CI est assez facile à prendre en main. Si vous avez l’habitude de travailler avec des fichiers yaml, vous ne serez pas perdu.
Le fichier .gitlab-ci.yaml directement à la racine du repository permet de versionner avec git l’ensemble du projet (Dockerfile, gitlab-ci, compose, tests, infra as code etc.) et de garder la partie CI/CD et le code au même endroit. Contrairement à Jenkins qui est uniquement un outil de CI/CD.
Cet outil à l’avantage d’avoir une excellente documentation, complète et compréhensible.
Il y a une forte communauté autour de GitLab CI. Internet regorge de tutos ou de forums, pour vous aider à mettre en place votre pipeline.
Pour conclure, je trouve cet outil très intéressant et je comprends pourquoi beaucoup d’entreprises l’utilisent. GitLab s’efforce de devenir une plateforme DevOps complète et d’être en mesure de construire nos Workflow de A à Z.
En espérant vous avoir donné envie d’utiliser GitLab et que vous avez compris le fonctionnement d’un pipeline ! 😁
Comments are closed.