
Un pipeline statique peut devenir coûteux quand il traite tous les cas de la même manière. Dans ce lab, vous introduisez une orchestration parent-enfant pour générer un plan d'exécution dynamique, piloté par un script versionné dans le dépôt.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Concevoir une étape d'orchestration dans un pipeline CI
- Générer dynamiquement un YAML enfant depuis un script shell
- Déclencher un child pipeline avec
triggeret artifact - Ajouter une logique contextuelle simple (branche par défaut vs autre branche)
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Ce pattern devient utile quand un pipeline doit s'adapter à des changements fréquents de périmètre. Un monolithe CI finit par lancer trop de jobs pour des modifications mineures.
Vous utiliserez cette approche quand :
- différents services doivent déclencher des sous-pipelines spécialisés ;
- vous voulez isoler la logique de décision dans un script maintenable ;
- vous cherchez à réduire le coût CI sans perdre de contrôle.
Prérequis
Section intitulée « Prérequis »- Lab 15, Matrices multi-versions terminé
- Avoir lu Pipelines parent-enfant et Pipelines dynamiques
Point de départ
Section intitulée « Point de départ »La branche starter/lab-16 contient déjà le découpage en fichiers ci/*.yml et
la matrice du lab précédent. Ne la modifiez pas encore : la baseline poussée
à l'étape 3 sert de point de comparaison, vous devez pouvoir constater à la fin
que le nombre de jobs exécutés a changé. Si votre glab n'est pas configuré sur
le projet, faites-le maintenant, l'étape de validation en dépend.
-
Basculez sur la branche du lab
Fenêtre de terminal cd pipeline-craftgit checkout starter/lab-16 -
Vérifiez la structure existante
Le pipeline est déjà découpé et matriciel, mais pas encore dynamique.
-
Lancez une baseline
Fenêtre de terminal git push origin starter/lab-16
Le problème
Section intitulée « Le problème »Le pipeline actuel exécute toujours la même séquence, même pour des cas simples. Vous allez introduire une orchestration pour produire un sous-plan plus ciblé.
L'exercice
Section intitulée « L'exercice »Étape 1, Ajouter un fichier d'orchestration CI
Section intitulée « Étape 1, Ajouter un fichier d'orchestration CI »L'orchestration vit dans son propre fichier pour rester lisible, mais surtout
parce qu'un job de type trigger ne peut pas coexister avec un script dans la
même définition. Vous écrivez donc deux jobs distincts : l'un génère le
YAML et le publie en artifact, l'autre le consomme. L'expire_in court n'est
pas une coquetterie : un artifact de configuration régénéré à chaque pipeline
n'a aucune raison d'occuper le stockage GitLab pendant des semaines.
-
Créez
ci/orchestration.yml -
Ajoutez un job
generate-child-pipeline -
Publiez
child-pipeline.ymlen artifactIndice : utilisez un
expire_incourt pour cet artifact temporaire.
👉 Vérifier votre solution (Étape 1)
1️⃣ Fichier ci/orchestration.yml
Section intitulée « 1️⃣ Fichier ci/orchestration.yml »generate-child-pipeline: stage: orchestrate image: alpine:3.20@sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc before_script: - apk add --no-cache bash git script: - chmod +x scripts/generate-child-pipeline.sh - ./scripts/generate-child-pipeline.sh artifacts: paths: - child-pipeline.yml expire_in: 1 day
run-child-pipeline: stage: orchestrate needs: - generate-child-pipeline trigger: include: - artifact: child-pipeline.yml job: generate-child-pipeline strategy: depend rules: - if: $CI_PIPELINE_SOURCE == "push" - if: $CI_PIPELINE_SOURCE == "merge_request_event"Étape 2, Générer dynamiquement le YAML enfant
Section intitulée « Étape 2, Générer dynamiquement le YAML enfant »Le script porte toute la logique de décision, et c'est aussi le seul endroit où
vous pouvez vous tromper sans que GitLab vous prévienne : un YAML mal indenté
sera accepté par le job de génération et rejeté seulement au déclenchement du
child pipeline. Écrivez le squelette commun avec un cat en heredoc quoté
(<<'YAML'), qui empêche le shell d'interpréter les $ du contenu, puis
ajoutez les blocs conditionnels par concaténation.
-
Créez le script
scripts/generate-child-pipeline.shIndice : ce fichier n'existe pas dans le starter, vous devez le créer.
-
Ajoutez une logique contextuelle
Exemple : ajouter un job supplémentaire si la branche vaut
main. -
Vérifiez que le script est exécutable
Fenêtre de terminal chmod +x scripts/generate-child-pipeline.sh
👉 Vérifier votre solution (Étape 2)
1️⃣ Script scripts/generate-child-pipeline.sh
Section intitulée « 1️⃣ Script scripts/generate-child-pipeline.sh »#!/usr/bin/env bashset -euo pipefail
# Dynamic child pipeline used in Lab 16.# It adapts jobs according to branch context.
cat > child-pipeline.yml <<'YAML'stages: - verify
child-smoke: stage: verify image: alpine:3.20@sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc script: - echo "Smoke check in child pipeline"YAML
if [[ "${CI_COMMIT_BRANCH:-}" == "${CI_DEFAULT_BRANCH:-}" ]]; then cat >> child-pipeline.yml <<'YAML'
child-default-branch-check: stage: verify image: alpine:3.20@sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc script: - echo "Extra checks on default branch"YAMLfi
cat child-pipeline.ymlÉtape 3, Déclencher le child pipeline
Section intitulée « Étape 3, Déclencher le child pipeline »Le job de déclenchement relie l'artifact au pipeline enfant par deux clés qui
vont ensemble : artifact désigne le fichier, job désigne le job qui l'a
produit. Ces deux clés sont au même niveau d'indentation dans l'élément de
liste, une erreur d'un espace ici et GitLab refuse tout le fichier. Le needs
garantit par ailleurs que la génération est terminée avant la lecture de
l'artifact, y compris si les deux jobs partagent le même stage.
-
Ajoutez un job
run-child-pipeline -
Utilisez
triggeravec include artifactIndice : gardez
strategy: dependpour propager l'état du pipeline enfant. -
Ajoutez
ci/orchestration.ymldans les includes du pipeline racine
👉 Vérifier votre solution (Étape 3)
1️⃣ Orchestrateur racine mis à jour
Section intitulée « 1️⃣ Orchestrateur racine mis à jour »Le pipeline racine ajoute un stage orchestrate et inclut le fichier d'orchestration.
stages: - lint - test - orchestrate - build - deploy
include: - local: ci/lint.yml - local: ci/test.yml - local: ci/build.yml - local: ci/deploy.yml - local: ci/orchestration.ymlÉtape 4, Valider puis pousser
Section intitulée « Étape 4, Valider puis pousser »glab ci lint valide la syntaxe du pipeline racine côté serveur, y compris
les include. En revanche, il ne voit pas le child-pipeline.yml, qui n'existe
pas encore au moment du lint : le fichier enfant n'est validé qu'à l'exécution
réelle. C'est pour cette raison que le lab vous fait pousser puis observer les
deux niveaux de pipeline dans l'interface GitLab plutôt que de vous arrêter au
lint.
-
Validez la syntaxe du pipeline racine
Fenêtre de terminal glab ci lint .gitlab-ci.yml -
Commit
Fenêtre de terminal git add .gitlab-ci.yml ci/orchestration.yml scripts/generate-child-pipeline.shgit commit -m "ci: add dynamic parent-child orchestration"git push origin starter/lab-16 -
Vérifiez les deux niveaux de pipeline dans GitLab
👉 Vérifier votre solution (Étape 4)
1️⃣ Contrôles attendus
Section intitulée « 1️⃣ Contrôles attendus »generate-child-pipelineproduit bienchild-pipeline.ymlen artifact ;run-child-pipelinedéclenche le child pipeline viatrigger.include.artifact;- le parent attend le résultat enfant (
strategy: depend) ; - un job supplémentaire apparaît dans le child pipeline sur la branche par défaut.
Le fichier complet
Section intitulée « Le fichier complet »Les trois blocs repliés ci-dessous donnent l'état final des fichiers touchés par
ce lab. Ouvrez-les seulement pour comparer avec votre version : le .gitlab-ci.yml
racine ne fait qu'ajouter le stage orchestrate et un include, tout le reste
du travail est concentré dans ci/orchestration.yml et le script de génération.
📄 Voir le fichier .gitlab-ci.yml complet
stages: - lint - test - orchestrate - build - deploy
workflow: rules: - if: $CI_PIPELINE_SOURCE == "push" - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_COMMIT_TAG
default: interruptible: true
variables: PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
include: - local: ci/lint.yml - local: ci/test.yml - local: ci/build.yml - local: ci/deploy.yml - local: ci/orchestration.yml📄 Voir le fichier ci/orchestration.yml complet
generate-child-pipeline: stage: orchestrate image: alpine:3.20@sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc before_script: - apk add --no-cache bash git script: - chmod +x scripts/generate-child-pipeline.sh - ./scripts/generate-child-pipeline.sh artifacts: paths: - child-pipeline.yml expire_in: 1 day
run-child-pipeline: stage: orchestrate needs: - generate-child-pipeline trigger: include: - artifact: child-pipeline.yml job: generate-child-pipeline strategy: depend rules: - if: $CI_PIPELINE_SOURCE == "push" - if: $CI_PIPELINE_SOURCE == "merge_request_event"📄 Voir le fichier scripts/generate-child-pipeline.sh complet
#!/usr/bin/env bashset -euo pipefail
# Dynamic child pipeline used in Lab 16.# It adapts jobs according to branch context.
cat > child-pipeline.yml <<'YAML'stages: - verify
child-smoke: stage: verify image: alpine:3.20@sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc script: - echo "Smoke check in child pipeline"YAML
if [[ "${CI_COMMIT_BRANCH:-}" == "${CI_DEFAULT_BRANCH:-}" ]]; then cat >> child-pipeline.yml <<'YAML'
child-default-branch-check: stage: verify image: alpine:3.20@sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc script: - echo "Extra checks on default branch"YAMLfi
cat child-pipeline.ymlVérification
Section intitulée « Vérification »Le lab est réussi quand vous voyez deux pipelines dans l'interface, le
parent avec un job run-child-pipeline marqué comme déclencheur, et l'enfant
avec ses propres jobs. Le dernier point de la liste est le plus discriminant :
poussez une fois sur starter/lab-16 et une fois sur la branche par défaut, et
comparez le nombre de jobs du pipeline enfant. S'il est identique, c'est que la
condition sur CI_COMMIT_BRANCH n'a pas été évaluée comme prévu.
-
ci/orchestration.ymlexiste et est inclus dans le pipeline racine -
child-pipeline.ymlest généré puis consommé via artifact - Le child pipeline se déclenche correctement
- Le comportement varie selon le contexte défini
Pièges fréquents
Section intitulée « Pièges fréquents »Un child pipeline échoue souvent pour une raison simple : YAML généré invalide. Ajoutez un cat child-pipeline.yml dans le job de génération pour faciliter le debug.
Autre point important : sans strategy: depend, le parent peut se terminer sans attendre le résultat réel du child.
À retenir
Section intitulée « À retenir »- Le parent-enfant sépare orchestration et exécution métier
- Un script versionné permet une logique dynamique contrôlée
- Les artifacts servent de transport de configuration entre jobs
- Un pipeline dynamique reste auditable s'il est lisible et traçable
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Multi-projet : Étendre la logique de déclenchement au-delà du dépôt, vers des pipelines d'autres projets.
- Workflows CI/CD : Choisir quel pipeline enfant doit être généré selon la branche, la merge request ou le tag.
- Lab 17, workflows branches et MR : Éviter le pipeline en double sur une merge request quand la génération est dynamique.