Aller au contenu
CI/CD & Automatisation medium

Lab 12 — Accélérer le pipeline

10 min de lecture

logo gitlab

Un pipeline lent finit par coûter cher : attente développeur, review ralentie, files runners saturées. Dans ce lab, vous optimisez les points qui apportent le plus de gains sans complexifier inutilement le YAML : cache bien clés, images allégées et parallélisme contrôlé.

  • Choisir une clé de cache stable et pertinente
  • Éviter les caches inutilisables ($CI_COMMIT_SHA)
  • Utiliser needs pour lancer des jobs en parallèle
  • Mesurer l'impact réel des optimisations

Ce lab s'appuie sur les acquis du Lab 11. Si vous maîtrisez déjà le diagnostic de pipeline, vous pouvez démarrer ici avec starter/lab-12.

Les pipelines lents sont un problème de productivité avant d'être un problème technique. Si chaque push met 8 minutes, les développeurs poussent moins souvent et accumulent des changements plus gros, ce qui augmente le risque de conflit et d'erreur.

Ce lab répond à des cas fréquents :

  • cache jamais réutilisé à cause d'une clé trop spécifique
  • jobs indépendants bloqués par la logique de stage séquentielle
  • images trop lourdes téléchargées à chaque run
  1. Basculez sur la branche du lab

    Fenêtre de terminal
    cd pipeline-craft
    git checkout starter/lab-12
  2. Lancez un run de référence

    Fenêtre de terminal
    git push origin starter/lab-12
  3. Notez la durée du pipeline

    Cette valeur sert de baseline avant optimisation.

La lenteur vient souvent de trois causes combinées :

  • cache inexploitable
  • exécution trop séquentielle
  • images ou builds non optimisés

Vous allez corriger ces trois zones sans rendre le pipeline illisible.

Étape 1 — À vous de corriger la stratégie de cache

Section intitulée « Étape 1 — À vous de corriger la stratégie de cache »
  1. Remplacez une clé de cache instable par une clé basée sur les fichiers de dépendances.

  2. Vérifiez sur deux runs successifs : le second doit restaurer le cache.

    Indice : une clé par commit empêche la réutilisation du cache.

👉 Vérifier votre solution (Étape 1)

Avant (clé instable, jamais réutilisée) :

cache:
key: "$CI_COMMIT_SHA" # ❌ Change à chaque commit
paths:
- .pip-cache/

Après (clé stable, réutilisée quand les dépendances ne changent pas) :

cache:
key:
files:
- requirements-dev.txt
paths:
- .pip-cache/

La clé change uniquement quand requirements-dev.txt est modifié.

Vérification dans les logs du job :

  • 1er run : Uploading cache.zip to https://... (création)
  • 2e run : Downloading cache.zip from https://... (restauration ✅)
  1. Identifiez les jobs indépendants.

  2. Ajoutez des needs explicites si nécessaire pour activer le DAG.

    Cette approche réduit l'attente artificielle liée aux stages.

👉 Vérifier votre solution (Étape 2)

Sans needs, les stages s'exécutent en séquence stricte. Avec needs, chaque job démarre dès que ses dépendances sont satisfaites :

pytest:
stage: test
needs: [] # ✅ Démarre dès que possible, sans attendre lint

Graphe d'exécution :

  • Avant : ruff-lint fini → pytest démarre → docker-build démarre
  • Après : ruff-lint et pytest démarrent en parallèle grâce à needs: [] sur pytest

Étape 3 — À vous de vérifier les images utilisées

Section intitulée « Étape 3 — À vous de vérifier les images utilisées »
  1. Confirmez l'usage de variantes allégées (python:3.12-slim)

  2. Gardez docker:27 uniquement pour les jobs qui en ont besoin

    Chaque job doit utiliser l'image minimale adaptée à son besoin.

👉 Vérifier votre solution (Étape 3)
Type de jobImage recommandéeÀ éviter
Lint Pythonpython:3.12-slimpython:3.12 (+200 MB inutiles)
Tests Pythonpython:3.12-slimubuntu:22.04 (outils inutiles)
Build Dockerdocker:27 + docker:27-dindImage Docker + OS complet
Deploy simplealpine:3.20Image Debian ou Ubuntu

La variante slim d'une image Python coûte généralement 3 à 4 fois moins en temps de pull que la variante standard. alpine:3.20 pèse moins de 10 MB.

  1. Poussez votre optimisation

    Fenêtre de terminal
    git add .gitlab-ci.yml
    git commit -m "ci: speed up pipeline with cache and dag"
    git push origin starter/lab-12
  2. Comparez la durée avec la baseline

    Vous devez observer une réduction tangible dès le second run optimisé.

👉 Vérifier votre solution (Étape 4)

Méthode : notez la colonne duration dans la liste des pipelines avant et après optimisation.

Gains typiques :

OptimisationGain attendu
Cache restauré-30 à 60 sec
needs sur jobs indépendants-durée du stage le plus court
Image slim vs standard-10 à 30 sec de pull

Mesurez sur 2 à 3 runs consécutifs : le premier run alimente le cache, les suivants le réutilisent. C'est à partir du deuxième run que le gain est visible.

📄 Voir le fichier .gitlab-ci.yml complet
stages:
- lint
- test
- 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
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
ruff-lint:
stage: lint
image: python:3.12-slim
cache:
key:
files:
- requirements-dev.txt
paths:
- .pip-cache/
policy: pull
before_script:
- pip install ruff
script:
- ruff check app/ tests/
pytest:
stage: test
image: python:3.12-slim
needs: []
cache:
key:
files:
- requirements-dev.txt
paths:
- .pip-cache/
before_script:
- pip install -r requirements-dev.txt
script:
- pytest -v --junitxml=report.xml --cov=app --cov-report=term-missing
coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
artifacts:
when: always
paths:
- report.xml
reports:
junit: report.xml
expire_in: 7 days
docker-build:
stage: build
image: docker:27
services:
- docker:27-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
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
deploy-staging:
stage: deploy
image: alpine:3.20
script:
- echo "Deploying $CI_COMMIT_SHORT_SHA to staging..."
- ./scripts/deploy-demo.sh staging
rules:
- 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
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual
  • Le cache est restauré sur un run suivant
  • Les jobs indépendants ne s'attendent plus inutilement
  • Le pipeline total est sensiblement plus court
  • Le YAML reste lisible et maintenable

Un pipeline très optimisé mais illisible devient vite un problème de maintenance. Cherchez un équilibre entre performance et clarté.

Autre piège : annoncer un gain après un seul run. Le premier run sert souvent à alimenter le cache. Mesurez au minimum sur deux à trois exécutions comparables.

  • Une bonne clé de cache change quand les dépendances changent, pas à chaque commit
  • Le DAG (needs) réduit l'attente artificielle des stages
  • Les images allégées accélèrent le pull et donc le pipeline
  • Mesurer avant/après est indispensable pour valider une optimisation

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn