Cours - CI/CD avec Gitlab
Rappel sur la CI/CD
Section titled “Rappel sur la CI/CD”La CI/CD fait partie du DevOps (la fusion des équipes de développement et d’exploitation) et combine les pratiques de l’intégration continue et de la livraison continue. La CI/CD réduit le travail de développement fastidieux et les processus d’approbation manuels, libérant ainsi les équipes pour plus d’efficacité dans leur développement logiciel.
-
L’automatisation rend les processus prévisibles et reproductibles, réduisant ainsi les possibilités d’erreurs dues à l’intervention humaine.
-
Les équipes obtiennent des retours plus rapides et peuvent intégrer plus fréquemment de petites modifications pour réduire le risque de modifications pouvant perturber le build et le déploiment.
La continuité et l’itération des processus DevOps accélèrent les cycles de développement logiciels, permettant ainsi aux organisations de livrer davantage de fonctionnalités.
L’intégration continue (CI)
Section titled “L’intégration continue (CI)”L’intégration continue est la pratique qui consiste à intégrer tous les changements de code dans la branche principale d’un code source partagé tôt et souvent, en testant automatiquement chaque changement lors de leur validation ou de leur fusion, et en lançant automatiquement un build.
Avec l’intégration continue, les erreurs et les problèmes de sécurité peuvent être identifiés et corrigés plus facilement, et beaucoup plus tôt dans le processus de développement. En “mergeant” fréquemment des changements et en déclenchant des processus de test et de validation automatiques, on minimise la possibilité de conflits de code. Un avantage secondaire est que vous n’avez pas à attendre longtemps pour obtenir des réponses sur la qualité et sécurité de votre code.
Les processus courants de validation du code commencent par une analyse de code statique qui vérifie la qualité du code. Une fois que le code passe les tests statiques, les routines CI automatisées empaquettent et compilent le code pour des tests automatisés supplémentaires. Une CI doit disposer d’un système de gestion de version qui suit les changements afin que vous connaissiez précisément la version du code utilisée.
La livraison continue (continuous delivery) ?
Section titled “La livraison continue (continuous delivery) ?”La livraison continue est une pratique de développement logiciel qui fonctionne en conjonction avec la CI pour automatiser le provisionnement de l’infrastructure et le processus de mise en production de l’application.
Une fois que le code a été testé et buildé dans le cadre du processus CI, la CD prend le relais lors des dernières étapes pour s’assurer qu’il est packagé avec tout ce dont il a besoin pour être déployé dans n’importe quel environnement. Avec la CD, le logiciel est construit de manière à pouvoir être déployé en production à tout moment. Ensuite, vous pouvez déclencher manuellement les déploiements ou passer au déploiement continu, où les déploiements sont également automatisés.
Qu’est-ce que le déploiement continu (continuous deployment) ?
Section titled “Qu’est-ce que le déploiement continu (continuous deployment) ?”Le déploiement continu permet aux organisations de déployer automatiquement leurs applications, éliminant ainsi le besoin d’intervention humaine. Avec cette méthode, les équipes DevOps définissent à l’avance les critères de mise en production du code, et lorsque ces critères sont satisfaits et validés, le code est déployé dans l’environnement de production. Cela permet aux organisations d’être plus agiles et de mettre de nouvelles fonctionnalités entre les mains des utilisateurs plus rapidement.
Pourquoi Docker est central pour la CI ?
Section titled “Pourquoi Docker est central pour la CI ?”- Les pipelines d’automatisation doivent tourner dans un environnement contrôlé qui contient toutes les dépendances nécessaires
- Historiquement avec par exemple Jenkins on utilisait des serveurs dédiés “fixes” provisionnés avec les dépendances nécessaires au boulot des pipelines.
Le problème c’est que cette approche ne permet pas de facilement et économiquement répondre à la charge de calcul nécessaire pour une équipe de dev:
- Typiquement les membres d’une équipe pushent leur code aux même moments de la journée : engorgement de la CI/CD et temps d’attente important.
- Si on prévoit beaucoup de serveurs fixes pour de pipelines pour éviter cela c’est cher et on les utilise seulement une fraction du temps
Autre problème, installer et maintenir les serveurs dédiés peut représenter beaucoup de travail.
-
Docker/les conteneurs permettent de lancer des conteneurs dans un cloud (plus dynamique/scalable) pour effectuer les jobs de CI/CD : cela permet avoir des pipelines à la demande.
-
Cela permet aussi d’avoir plus facilement une reproductibilité des environnements de CI/CD et peut faciliter l’installation : par exemple pour une application maven on prend un conteneur maven officiel du Docker Hub et une grosse partie du travail est fait par d’autres et facile pour les mises à jour.
-
C’est l’approche de Gitlab qui fournit du pipeline as a service par défault basé sur un cloud de conteneur.
-
Jenkins installé avec le plugin Docker ou Kubernetes permet également d’utiliser des conteneurs pour les différentes étapes (stages) d’un pipeline.
Présentation de Gitlab CI/CD
Section titled “Présentation de Gitlab CI/CD”GitLab CI/CD est une plateforme intégrée d’intégration et de déploiement continu qui permet d’automatiser la construction, le test et le déploiement de vos applications directement depuis votre dépôt GitLab.
Concepts clés de GitLab CI/CD
Section titled “Concepts clés de GitLab CI/CD”1. Le fichier .gitlab-ci.yml
C’est le fichier de configuration central qui définit votre pipeline CI/CD. Il doit être placé à la racine de votre dépôt. GitLab détecte automatiquement ce fichier et exécute le pipeline à chaque commit.
2. Les Runners
Les runners sont des agents qui exécutent les jobs définis dans votre pipeline :
- Shared runners : Fournis automatiquement par GitLab.com (gratuits avec des limites)
- Specific runners : Installés sur vos propres serveurs pour plus de contrôle et de ressources
3. Les Pipelines
Un pipeline est une collection de jobs organisés en stages qui s’exécutent automatiquement. GitLab affiche visuellement l’état du pipeline avec chaque commit.
4. Les Stages
Les stages définissent l’ordre d’exécution des jobs :
- Les jobs d’un même stage s’exécutent en parallèle (si des runners sont disponibles)
- Les stages s’exécutent séquentiellement (un stage ne démarre que si le précédent réussit)
- Stages par défaut :
build→test→deploy
5. Les Jobs
Les jobs sont les unités de travail fondamentales qui contiennent :
script: Les commandes à exécuter (attribut obligatoire)stage: Le stage auquel appartient le jobimage: L’image Docker à utiliser pour l’exécutionservices: Services Docker supplémentaires (bases de données, etc.)
6. Les Environnements
Les environnements représentent des cibles de déploiement et permettent de tracker les déploiements :
environment.name: Nom de l’environnement (production, staging, review/*)environment.url: URL pour accéder à l’application déployéeenvironment.on_stop: Job à exécuter pour arrêter l’environnementenvironment.auto_stop_in: Durée avant arrêt automatique (pour review apps)- Tiers automatiques : production, staging, testing, development
Structure de base d’un .gitlab-ci.yml
Section titled “Structure de base d’un .gitlab-ci.yml”# Définition des stages (optionnel, valeurs par défaut : build, test, deploy)stages: - build - test - deploy
# Job de buildbuild-job: stage: build image: node:20-alpine script: - echo "Compilation de l'application..." - npm install - npm run build artifacts: paths: - dist/ expire_in: 1 hour
# Jobs de test (s'exécutent en parallèle)test-job1: stage: test image: node:20-alpine script: - echo "Exécution des tests unitaires" - npm run test:unit
test-job2: stage: test image: node:20-alpine script: - echo "Exécution des tests d'intégration" - npm run test:integration
# Job de déploiementdeploy-prod: stage: deploy image: docker:cli script: - echo "Déploiement en production depuis $CI_COMMIT_BRANCH" - docker build -t mon-app:$CI_COMMIT_SHA . - docker push mon-app:$CI_COMMIT_SHA environment: production only: - mainOptions avancées essentielles
Section titled “Options avancées essentielles”Variables d’environnement
GitLab fournit automatiquement de nombreuses variables prédéfinies :
variables: # Variables globales DATABASE_URL: "postgres://localhost/test"
job-example: script: - echo "Branch: $CI_COMMIT_BRANCH" - echo "Commit SHA: $CI_COMMIT_SHA" - echo "Registry: $CI_REGISTRY"Règles d’exécution conditionnelle
deploy-staging: stage: deploy script: - echo "Déploiement en staging" rules: - if: $CI_COMMIT_BRANCH == "develop" - if: $CI_MERGE_REQUEST_ID # S'exécute aussi sur les MR
deploy-production: stage: deploy script: - echo "Déploiement en production" rules: - if: $CI_COMMIT_TAG # Seulement sur les tags - if: $CI_COMMIT_BRANCH == "main" when: manual # Requiert validation manuelleCache et Artifacts
- Cache : Accélère les builds en réutilisant les dépendances entre pipelines
- Artifacts : Transfère des fichiers entre jobs d’un même pipeline
build-job: stage: build script: - npm install - npm run build cache: key: ${CI_COMMIT_REF_SLUG} paths: - node_modules/ # Cache réutilisé entre pipelines artifacts: paths: - dist/ # Transmis aux jobs suivants expire_in: 1 day
test-job: stage: test script: - npm run test # Utilise dist/ du job précédent dependencies: - build-jobNeeds : Optimisation des pipelines
Par défaut, les jobs attendent que tous les jobs du stage précédent soient terminés. needs permet de définir des dépendances spécifiques :
stages: - build - test - deploy
build-frontend: stage: build script: - npm run build:frontend
build-backend: stage: build script: - npm run build:backend
test-frontend: stage: test needs: [build-frontend] # Démarre dès que build-frontend termine script: - npm run test:frontend
deploy-all: stage: deploy needs: [test-frontend, build-backend] script: - ./deploy.shDocker in Docker (DinD)
Pour construire des images Docker dans GitLab CI :
build-image: stage: build image: docker:cli services: - docker:dind variables: DOCKER_TLS_CERTDIR: "/certs" before_script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHABonnes pratiques GitLab CI/CD
Section titled “Bonnes pratiques GitLab CI/CD”- Commencer simple : Un pipeline basique avec build → test → deploy
- Utiliser des images Docker légères :
alpineouslimpour accélérer - Optimiser le cache : Mettre en cache
node_modules/,vendor/, etc. - Fail fast : Placer les jobs rapides (linting, tests unitaires) en premier
- Paralléliser : Diviser les tests en plusieurs jobs pour gagner du temps
- Protéger les secrets : Utiliser les variables masquées dans Settings > CI/CD
- Environnements : Utiliser
environment:pour tracker les déploiements - Review Apps : Créer des environnements temporaires pour chaque merge request
Exemple complet : Application Node.js
Section titled “Exemple complet : Application Node.js”stages: - check - build - test - deploy
variables: IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
# Stage check : rapide pour feedback immédiatlint: stage: check image: node:20-alpine script: - npm ci - npm run lint cache: key: ${CI_COMMIT_REF_SLUG} paths: - node_modules/
# Stage buildbuild-app: stage: build image: node:20-alpine script: - npm ci - npm run build artifacts: paths: - dist/ expire_in: 1 hour cache: key: ${CI_COMMIT_REF_SLUG} paths: - node_modules/ policy: pull
build-docker: stage: build image: docker:cli services: - docker:dind before_script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - docker build --pull -t $IMAGE_TAG . - docker push $IMAGE_TAG only: - main - develop
# Stage test : jobs en parallèletest-unit: stage: test image: node:20-alpine script: - npm ci - npm run test:unit coverage: '/Lines\s*:\s*(\d+\.\d+)%/' cache: key: ${CI_COMMIT_REF_SLUG} paths: - node_modules/ policy: pull
test-integration: stage: test image: node:20-alpine services: - postgres:15 - redis:7-alpine variables: POSTGRES_DB: testdb POSTGRES_USER: testuser POSTGRES_PASSWORD: testpass DATABASE_URL: "postgresql://testuser:testpass@postgres:5432/testdb" REDIS_URL: "redis://redis:6379" script: - npm ci - npm run test:integration cache: key: ${CI_COMMIT_REF_SLUG} paths: - node_modules/ policy: pull
# Stage deploydeploy-staging: stage: deploy image: docker:cli before_script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - docker pull $IMAGE_TAG - docker tag $IMAGE_TAG $CI_REGISTRY_IMAGE:staging - docker push $CI_REGISTRY_IMAGE:staging environment: name: staging url: https://staging.example.com only: - develop
deploy-production: stage: deploy image: docker:cli before_script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - docker pull $IMAGE_TAG - docker tag $IMAGE_TAG $CI_REGISTRY_IMAGE:latest - docker push $CI_REGISTRY_IMAGE:latest environment: name: production url: https://example.com when: manual only: - mainLes Environnements
Section titled “Les Environnements”Les environnements GitLab permettent de tracker l’historique des déploiements, gérer les rollbacks, et contrôler les accès aux différentes cibles de déploiement.
Configuration des environnements
Section titled “Configuration des environnements”Environnement statique (production, staging) :
deploy-production: stage: deploy script: - ./deploy-prod.sh environment: name: production url: https://app.example.com deployment_tier: production when: manual only: - mainEnvironnement dynamique (review apps) :
deploy-review: stage: deploy script: - ./deploy-review.sh $CI_COMMIT_REF_SLUG environment: name: review/$CI_COMMIT_REF_SLUG url: https://$CI_COMMIT_REF_SLUG.review.example.com on_stop: stop-review auto_stop_in: 1 week only: - merge_requests
stop-review: stage: deploy script: - ./cleanup-review.sh $CI_COMMIT_REF_SLUG environment: name: review/$CI_COMMIT_REF_SLUG action: stop when: manual only: - merge_requestsTiers d’environnements : production, staging, testing, development (assignés automatiquement selon le nom)
Variables scopées : Limitez les secrets à des environnements spécifiques (Settings > CI/CD > Variables > Environment scope)
Visualisation dans GitLab
Section titled “Visualisation dans GitLab”L’interface Deployments > Environments affiche :
- Liste et statut de tous les environnements
- Historique complet des déploiements
- Rollback en un clic vers une version antérieure
- URLs cliquables vers les applications déployées
- Badge dans les Merge Requests montrant où le code est déployé
Ressources officielles
Section titled “Ressources officielles”- 📚 Documentation complète : https://docs.gitlab.com/topics/build_your_application/
- 🚀 Tutoriel Quick Start : https://docs.gitlab.com/ci/quick_start/
- 📖 Référence YAML : https://docs.gitlab.com/ci/yaml/
- 🌍 Environnements : https://docs.gitlab.com/ci/environments/
- 💡 Exemples de pipelines : https://docs.gitlab.com/ci/examples/