Exercice 07 : Projet Capstone - Pipeline GitLab CI Optimisé avec Rules, Cache et DAG
🎯 Objectifs
À la fin de cet exercice, vous serez capable de :
- ✅ Contrôler l'exécution conditionnelle avec
rules:(remplaçantonly/except) - ✅ Accélérer le pipeline avec un cache efficace
- ✅ Lancer un service PostgreSQL aux côtés d'un job de test
- ✅ Créer un pipeline DAG (graphe dirigé acyclique) avec
needs:pour éviter les attentes inutiles - ✅ Réutiliser des configurations avec
extends:et les ancres YAML (&anchor)
Durée estimée : 45 minutes
Difficulté : ⭐⭐⭐⭐☆ (Avancé)
Prérequis :
- Exercice 06 GitLab CI complété
- Module GitLab CI Intermédiaire complété
📖 Contexte
Le pipeline de base fonctionne mais prend trop de temps. Votre objectif : optimiser avec needs: pour supprimer les attentes entre stages, utiliser un service PostgreSQL pour les tests d'intégration, et utiliser rules: pour un contrôle fin de l'exécution.
📋 Énoncé
Refactorisez le pipeline GitLab CI avec DAG, rules, cache optimisé, services PostgreSQL et configurations réutilisables.
🧭 Déroulement de l'exercice
Tâche 1 : Remplacer only/except par rules
Remplacez les only: [main] du pipeline précédent par des rules: équivalentes. Ajoutez une règle qui empêche l'exécution du job build-docker sur des branches dont le nom commence par wip/.
Indice :
`yamlrules:
- if: '$CI_COMMIT_BRANCH =~ /^wip\//'
when: never
- if: '$CI_COMMIT_BRANCH == "main"'
when: on_success
- when: never
`
rules:est évalué de haut en bas - la première règle qui correspond est appliquée.when: neverexclut le job.
Vérification : Sur une branche wip/test-feature, le job build-docker n'apparaît pas dans le pipeline.
Tâche 2 : Implémenter un pipeline DAG avec needs
Retirez les stages du pipeline et utilisez needs: pour définir les dépendances directes entre jobs. Le but : run-lint et build-docker ne doivent plus attendre que run-tests se termine.
Indice : Avec
needs:, un job démarre dès que ses dépendances directes sont terminées, sans attendre que tout un stage soit complet.run-lintpeut démarrer dès queinstall-dependenciesest terminé, en même temps querun-tests.
Vérification : Dans la vue pipeline GitLab, le graphe montre des flèches directes entre jobs plutôt qu'une progression par stage. La durée totale du pipeline est réduite.
Tâche 3 : Lancer un service PostgreSQL
Créez un job test-integration qui lance un service PostgreSQL et exécute des requêtes SQL basiques pour valider la connectivité. Configurez les variables d'environnement PostgreSQL pour le service.
Indice :
`yamltest-integration:
services:
- name: postgres:16-alpine
alias: postgres
variables:
POSTGRES_USER: testuser
POSTGRES_PASSWORD: testpass
POSTGRES_DB: testdb
PGPASSWORD: testpass
script:
- apk add --no-cache postgresql-client
- psql -h postgres -U testuser -d testdb -c "SELECT version();"
`Le service
postgresest accessible via son alias comme hostname.
Vérification : Le job test-integration se connecte à PostgreSQL et affiche la version du serveur.
Tâche 4 : Créer des ancres YAML et extends
Définissez une ancre YAML &node-job avec la configuration commune (image, cache) et utilisez <<: *node-job dans les jobs appropriés. Définissez également un job caché .deploy-base utilisé avec extends:.
Indice : Les ancres YAML permettent la réutilisation au niveau YAML :
`yaml.node-defaults: &node-defaults
image: node:20-alpine
cache:
key:
files: [package-lock.json]
paths: [node_modules/]
>
run-tests:
<<: *node-defaults
script: npm test
`Les jobs commençant par
.sont des jobs cachés (non exécutés) utilisables comme templates avecextends:.
Vérification : gitlab-ci-lint valide le fichier. Plusieurs jobs partagent la même configuration grâce aux ancres sans duplication.
Tâche 5 : Planifier un pipeline schedulé
Configurez un pipeline planifié (CI/CD → Schedules dans GitLab) pour exécuter uniquement le job de tests d'intégration tous les jours à 2h00. Utilisez la variable $CI_PIPELINE_SOURCE == "schedule" dans les rules: du job.
Indice : Dans GitLab CI/CD → Schedules, définissez une cron expression
0 2 * * *. Dans le job :
`yamlrules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: always
- when: never
`Cela restreint le job aux pipelines planifiés uniquement.
Vérification : Le job test-integration n'apparaît pas sur un push normal. Un pipeline schedulé le déclenche.
Tâche 6 : Ajouter un job de notification de fin de pipeline
Créez un job notify-completion qui s'exécute à la fin du pipeline dans tous les cas (when: always). Ce job affiche un résumé : durée du pipeline, statut global, branche, et commit. Utilisez needs: pour qu'il attende tous les autres jobs.
Indice :
CI_PIPELINE_CREATED_ATetCI_JOB_STARTED_ATpermettent de calculer la durée.$CI_PIPELINE_STATUSn'existe pas, mais$CI_JOB_STATUSest disponible pour le job courant.
Vérification : notify-completion apparaît dans le graphe comme nœud final, avec flèches entrantes depuis tous les autres jobs.
🗂️ Mini-Projet : Pipeline DAG optimisé
Graphe DAG :
[install-deps] ──┬──→ [run-tests]
├──→ [run-lint]
└──→ [test-integration] (scheduled only)
↓
[build-docker] (main) ↓
↓ ↓
└────────┬──────────┘
↓
[notify-completion]Checkpoints de validation :
rules:remplace tous lesonly/except- Le graphe pipeline montre des dépendances directes (DAG)
test-integrationse connecte à PostgreSQL avec succès- Les ancres YAML évitent la duplication de la config
image+cache test-integrationn'apparaît que dans les pipelines schedulésnotify-completions'exécute en dernier avecwhen: always