
Un pipeline peut être propre, modulaire et malgré tout fragile. Il suffit d’une défaillance runner temporaire, d’un timeout non maîtrisé ou de deux déploiements concurrents pour casser la chaîne. Ce lab vous fait traiter cette couche de résilience.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Diagnostiquer une erreur de stage volontairement injectée
- Ajouter
retryavec un ciblage des causes transitoires - Poser des
timeoutexplicites sur les jobs critiques - Utiliser
resource_grouppour sérialiser les déploiements
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Cette étape correspond au passage d’un pipeline “fonctionnel” à un pipeline “opérationnel”. Dans la vraie vie, les échecs transitoires sont inévitables : runners indisponibles, congestion réseau, jobs longs qui s’accumulent, déploiements concurrents.
Ce lab est utile quand :
- les pipelines échouent de manière intermittente ;
- plusieurs déploiements se chevauchent ;
- l’équipe veut réduire les faux négatifs CI.
Prérequis
Section intitulée « Prérequis »- Lab 17 — Workflows branches et MR terminé
- Avoir lu Fiabilité des pipelines
Point de départ
Section intitulée « Point de départ »-
Basculez sur la branche de départ
Fenêtre de terminal cd pipeline-craftgit checkout starter/lab-18 -
Lancez un lint branch-aware
Fenêtre de terminal glab ci lint --dry-run --ref starter/lab-18 -
Observez l’erreur attendue
Le starter est volontairement invalide avec un stage
orchestrateabsent.
Le problème
Section intitulée « Le problème »Vous devez d’abord rétablir un pipeline valide, puis renforcer sa robustesse sur les jobs sensibles.
L’exercice
Section intitulée « L’exercice »Étape 1 — Corriger la base cassée
Section intitulée « Étape 1 — Corriger la base cassée »-
Ouvrez
.gitlab-ci.yml -
Ajoutez le stage manquant
orchestratedansstages: -
Revalidez
Fenêtre de terminal glab ci lint .gitlab-ci.yml
👉 Vérifier votre solution (Étape 1)
1️⃣ Stage manquant dans .gitlab-ci.yml
Section intitulée « 1️⃣ Stage manquant dans .gitlab-ci.yml »Le starter du lab 18 référence déjà des jobs d’orchestration, mais oublie le stage correspondant.
stages: - lint - test - orchestrate - build - deployÉtape 2 — Durcir le job de build
Section intitulée « Étape 2 — Durcir le job de build »-
Ajoutez un retry ciblé
Indice : ciblez les causes transitoires infra, pas les erreurs applicatives.
-
Ajoutez un timeout explicite
Indice : le timeout doit rester réaliste pour un build Docker normal.
-
Gardez
interruptible: truesur les jobs non critiques de long run
👉 Vérifier votre solution (Étape 2)
1️⃣ Renforcement de docker-build dans ci/build.yml
Section intitulée « 1️⃣ Renforcement de docker-build dans ci/build.yml »docker-build: stage: build needs: - pytest-matrix - run-child-pipeline image: docker:27 services: - docker:27-dind variables: <<: *docker_vars retry: max: 2 when: - runner_system_failure - stuck_or_timeout_failure timeout: 20m interruptible: trueÉtape 3 — Fiabiliser les déploiements
Section intitulée « Étape 3 — Fiabiliser les déploiements »-
Ajoutez
resource_grouppour éviter les déploiements concurrentsIndice : utilisez un verrou distinct par environnement.
-
Ajoutez
timeoutetretryraisonnables sur staging et production -
Conservez
interruptible: falsepour éviter une interruption de déploiement en cours
👉 Vérifier votre solution (Étape 3)
1️⃣ Durcissement de ci/deploy.yml
Section intitulée « 1️⃣ Durcissement de ci/deploy.yml »deploy-staging: stage: deploy image: alpine:3.20 script: - echo "Deploying $CI_COMMIT_SHORT_SHA to staging..." - ./scripts/deploy-demo.sh staging resource_group: staging retry: max: 1 when: - runner_system_failure timeout: 10m interruptible: false rules: - if: $CI_MERGE_REQUEST_EVENT_TYPE == "merge_train" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
deploy-production: stage: deploy image: alpine:3.20 script: - echo "Deploying $CI_COMMIT_SHORT_SHA to production..." - ./scripts/deploy-demo.sh production resource_group: production retry: max: 1 when: - runner_system_failure timeout: 15m interruptible: false rules: - if: $CI_COMMIT_TAG - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: manualÉtape 4 — Valider puis pousser
Section intitulée « Étape 4 — Valider puis pousser »-
Validation CI
Fenêtre de terminal glab ci lint .gitlab-ci.yml -
Commit et push
Fenêtre de terminal git add .gitlab-ci.yml ci/build.yml ci/deploy.ymlgit commit -m "ci: improve reliability with retry timeout and resource locks"git push origin starter/lab-18 -
Vérifiez un run complet
👉 Vérifier votre solution (Étape 4)
1️⃣ Contrôles attendus
Section intitulée « 1️⃣ Contrôles attendus »- le lint ne remonte plus l’erreur de stage manquant ;
docker-buildsupporte mieux les pannes transitoires runner/réseau ;- les déploiements sont sérialisés (
resource_group) et non interruptibles ; - les timeouts explicites empêchent les jobs bloqués trop longtemps.
Le fichier complet
Section intitulée « Le fichier complet »📄 Voir le fichier .gitlab-ci.yml complet
stages: - lint - test - orchestrate - build - deploy
workflow: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS when: never - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_COMMIT_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/orchestration.yml - local: ci/build.yml - local: ci/deploy.yml📄 Voir le fichier ci/build.yml complet
.docker-vars: &docker_vars DOCKER_TLS_CERTDIR: "/certs"
docker-build: stage: build needs: - pytest-matrix - run-child-pipeline image: docker:27 services: - docker:27-dind variables: <<: *docker_vars retry: max: 2 when: - runner_system_failure - stuck_or_timeout_failure timeout: 20m interruptible: true script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA . - docker build -t $CI_REGISTRY_IMAGE:latest . - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA - docker push $CI_REGISTRY_IMAGE:latest📄 Voir le fichier ci/deploy.yml complet
deploy-staging: stage: deploy image: alpine:3.20 script: - echo "Deploying $CI_COMMIT_SHORT_SHA to staging..." - ./scripts/deploy-demo.sh staging resource_group: staging retry: max: 1 when: - runner_system_failure timeout: 10m interruptible: false rules: - if: $CI_MERGE_REQUEST_EVENT_TYPE == "merge_train" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
deploy-production: stage: deploy image: alpine:3.20 script: - echo "Deploying $CI_COMMIT_SHORT_SHA to production..." - ./scripts/deploy-demo.sh production resource_group: production retry: max: 1 when: - runner_system_failure timeout: 15m interruptible: false rules: - if: $CI_COMMIT_TAG - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: manualVérification
Section intitulée « Vérification »- Le lint ne renvoie plus l’erreur de stage
-
retryest ciblé sur des causes transitoires pertinentes - Les jobs critiques ont un
timeoutexplicite - Les déploiements sont sérialisés via
resource_group
Pièges fréquents
Section intitulée « Pièges fréquents »Un retry trop large masque les vraies erreurs applicatives. Ciblez seulement les cas transitoires liés à l’infrastructure CI.
Ne mettez pas interruptible: true sur un job de production critique, sinon un nouveau pipeline peut interrompre un déploiement en cours.
À retenir
Section intitulée « À retenir »- Fiabiliser un pipeline, ce n’est pas seulement le faire passer une fois
retry,timeoutetresource_grouptraitent des risques différents- Le starter cassé est un exercice de diagnostic, pas un accident
- La résilience CI doit rester explicite et mesurable