
Vos pipelines attendent la fin d’un stage complet alors qu’un seul job est nécessaire ? Avec needs: (DAG), un job démarre dès que ses vraies dépendances sont terminées, sans attendre tout le stage. Résultat : des pipelines souvent sensiblement plus rapides (et surtout plus parallèles).
Ce guide est fait pour vous si…
Section intitulée « Ce guide est fait pour vous si… »Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »À la fin de ce module, vous saurez :
- Comprendre le problème : pourquoi les stages ralentissent vos pipelines
- Utiliser
needs: définir les vraies dépendances entre jobs - Gérer les artefacts :
artifacts: true/falseavec needs - Visualiser le DAG : lire le graphe de dépendances dans GitLab
- Utiliser
needs: []: démarrer un job immédiatement - Éviter les pièges : dépendances circulaires, jobs manqués
Prérequis
Section intitulée « Prérequis »Avant de continuer, assurez-vous de maîtriser :
Le problème sans DAG
Section intitulée « Le problème sans DAG »L’analogie du restaurant
Section intitulée « L’analogie du restaurant »Imaginez un restaurant où le serveur attend que tous les plats de l’entrée soient prêts avant de les servir, même si votre salade est prête depuis 10 minutes. Puis il attend que tous les plats principaux soient prêts… Votre steak refroidit pendant que le risotto de votre voisin cuit encore.
C’est exactement ce que font les pipelines GitLab par défaut : ils attendent la fin de tout un stage avant de passer au suivant.
Le comportement par défaut : stage par stage
Section intitulée « Le comportement par défaut : stage par stage »Par défaut, GitLab exécute les pipelines stage par stage :
stages: - build - test - deploy
build: stage: build script: npm run build
lint: stage: test script: npm run lint
unit_tests: stage: test script: npm test
integration_tests: stage: test script: npm run test:integration
deploy: stage: deploy script: ./deploy.shDécortiquons ce qui se passe :
- Stage build :
builds’exécute seul (2 minutes) - Stage test :
lint(30s),unit_tests(3 min),integration_tests(5 min) démarrent en parallèle - Attente forcée : même si
lintfinit en 30 secondes, le stage “test” dure 5 minutes (le plus long) - Stage deploy :
deploydémarre enfin
Problème : deploy attend que lint, unit_tests ET integration_tests soient tous terminés, même si deploy n’a besoin que de build. Si lint échoue et que vous devez le corriger, vous avez attendu 5 minutes pour rien.
Configuration avec needs
Section intitulée « Configuration avec needs »Le mot-clé needs: change la donne : au lieu de dire “attends tout le stage précédent”, vous dites “attends uniquement ces jobs spécifiques”.
Syntaxe de base
Section intitulée « Syntaxe de base »needs: prend une liste de noms de jobs. Le job actuel démarrera dès que tous les jobs listés sont terminés, peu importe leur stage.
stages: - build - test - deploy
build: stage: build script: npm run build artifacts: paths: - dist/
lint: stage: test script: npm run lint needs: [] # Pas de dépendance, démarre immédiatement
unit_tests: stage: test script: npm test needs: ["build"] # Attend seulement build
integration_tests: stage: test script: npm run test:integration needs: ["build"]
deploy: stage: deploy script: ./deploy.sh needs: ["unit_tests"] # N'attend pas lint ni integration_testsAnalysons les changements :
| Job | needs | Ce qui change |
|---|---|---|
lint | [] (vide) | Démarre immédiatement, en parallèle avec build |
unit_tests | ["build"] | Attend seulement build, pas tout le stage |
integration_tests | ["build"] | Pareil, attend juste build |
deploy | ["unit_tests"] | Démarre dès que unit_tests finit, sans attendre lint ni integration_tests |
Résultat :
Le pipeline est plus rapide car :
lintdémarre immédiatement (pas besoin d’attendrebuild)deployn’attend paslintniintegration_tests- Si
integration_testsprend 10 minutes maisunit_testsseulement 2,deploydémarre après 2 minutes
Options de needs
Section intitulée « Options de needs »needs offre plusieurs syntaxes selon vos besoins. Commençons par la plus simple.
Liste simple
Section intitulée « Liste simple »La syntaxe la plus courante : une liste de noms de jobs entre crochets.
deploy: needs: ["build", "test"] # Attend que build ET test soient terminésLe job deploy démarrera quand les deux jobs seront au vert. Si l’un échoue, deploy ne démarrera pas (comportement par défaut).
Avec contrôle des contrôle des artefacts
Section intitulée « Avec contrôle des contrôle des artefacts »Quand vous utilisez needs, GitLab télécharge automatiquement les artefacts des jobs référencés (les fichiers produits par ces jobs). Mais parfois, vous voulez attendre un job sans récupérer ses fichiers.
Exemple concret : deploy attend lint (pour être sûr que le code est propre), mais n’a pas besoin des fichiers produits par lint.
deploy: needs: - job: build artifacts: true # ✅ Télécharge le dossier dist/ produit par build - job: lint artifacts: false # ⏳ Attend lint, mais ne télécharge rienPourquoi c’est utile ? Télécharger des artefacts prend du temps et de la bande passante. Si vous n’en avez pas besoin, artifacts: false accélère le démarrage du job.
needs: [] — aucune dépendance
Section intitulée « needs: [] — aucune dépendance »C’est la syntaxe la plus puissante pour accélérer vos pipelines. Un job avec needs: [] (liste vide) démarre immédiatement, sans attendre aucun autre job.
lint: stage: test # Même s'il est dans le stage "test"... needs: [] # ...il démarre immédiatement, en parallèle avec "build" ! script: npm run lintPourquoi ça marche ? Le linting analyse le code source, pas le code compilé. Il n’a pas besoin d’attendre que build produise le dossier dist/. Donc pourquoi le faire attendre ?
needs avec optional
Section intitulée « needs avec optional »Parfois, un job dans votre needs peut ne pas exister dans certains pipelines. Par exemple, security_scan ne s’exécute que sur la branche main (via rules). Sur une branche de feature, ce job n’existe pas.
Sans optional : GitLab refuse de créer le pipeline (“job not found”).
Avec optional: true : GitLab ignore silencieusement le job manquant.
security_scan: stage: test rules: - if: $CI_COMMIT_BRANCH == "main" # N'existe que sur main script: ./scan.sh
deploy: needs: - job: build # Obligatoire, doit exister - job: security_scan optional: true # Optionnel : OK si le job n'existe pasComportement :
- Sur
main:deployattendbuildETsecurity_scan - Sur
feature-x:deployattend seulementbuild(carsecurity_scann’existe pas)
Limites et cas particuliers
Section intitulée « Limites et cas particuliers »Limite de 50 jobs
Section intitulée « Limite de 50 jobs »Par défaut, needs accepte maximum 50 jobs. Au-delà, GitLab refuse de créer le pipeline. Cette limite existe pour éviter les pipelines trop complexes qui deviennent difficiles à débugger.
Si vous atteignez cette limite, c’est souvent un signe que votre pipeline devrait être découpé en pipelines parent-enfant.
Interaction avec parallel:
Section intitulée « Interaction avec parallel: »Si vous référencez un job qui utilise parallel: (ou parallel:matrix), votre job attend toutes les instances générées, pas une seule.
test: parallel: 3 # Génère test 1/3, test 2/3, test 3/3 script: npm test
deploy: needs: ["test"] # Attend les 3 jobs testPour cibler une instance spécifique, consultez le guide sur les matrices.
Dépendances dans le même stage
Section intitulée « Dépendances dans le même stage »needs peut référencer des jobs du même stage. C’est utile quand deux jobs sont dans le même stage mais l’un dépend de l’autre.
build_lib: stage: build script: npm run build:lib
build_app: stage: build needs: ["build_lib"] # Même stage, mais attend build_lib script: npm run build:appNe pas mélanger needs et dependencies
Section intitulée « Ne pas mélanger needs et dependencies »dependencies est l’ancien mot-clé pour contrôler les artefacts. Ne l’utilisez pas dans un job qui a déjà needs — les comportements peuvent entrer en conflit.
Visualiser le DAG
Section intitulée « Visualiser le DAG »GitLab affiche le graphe de dépendances dans l’interface :
-
Allez dans Build > Pipelines
-
Cliquez sur un pipeline
-
Sélectionnez l’onglet Needs (ou regardez le graphe qui montre les flèches)

Le graphe montre les vraies dépendances entre jobs, pas l’organisation par stages.
Exemples pratiques
Section intitulée « Exemples pratiques »Pipeline Node.js optimisé
Section intitulée « Pipeline Node.js optimisé »stages: - prepare - quality - build - test - deploy
install: stage: prepare script: npm ci cache: key: files: - package-lock.json paths: - node_modules/ artifacts: paths: - node_modules/ expire_in: 1 hour
# Jobs de qualité : pas de dépendance, démarrent immédiatementlint: stage: quality needs: [] script: npm run lint
format_check: stage: quality needs: [] script: npm run format:check
# Build : attend seulement installbuild: stage: build needs: ["install"] script: npm run build artifacts: paths: - dist/
# Tests : en parallèle, chacun attend seulement ce dont il a besoinunit_tests: stage: test needs: ["install"] script: npm test
e2e_tests: stage: test needs: ["build"] # A besoin du build script: npm run test:e2e
# Deploy : attend les tests critiques, pas le lintdeploy_staging: stage: deploy needs: ["unit_tests", "build"] script: ./deploy.sh stagingMonorepo avec services indépendants
Section intitulée « Monorepo avec services indépendants »stages: - build - test - deploy
# Frontend et Backend buildent en parallèlebuild_frontend: stage: build script: npm run build:frontend artifacts: paths: - frontend/dist/
build_backend: stage: build script: npm run build:backend artifacts: paths: - backend/target/
# Tests indépendantstest_frontend: stage: test needs: ["build_frontend"] script: npm run test:frontend
test_backend: stage: test needs: ["build_backend"] script: npm run test:backend
# Déploiements indépendantsdeploy_frontend: stage: deploy needs: ["test_frontend"] script: ./deploy-frontend.sh
deploy_backend: stage: deploy needs: ["test_backend"] script: ./deploy-backend.shLe frontend et le backend sont complètement indépendants. Si le backend est lent, le frontend se déploie quand même.
Bonnes pratiques
Section intitulée « Bonnes pratiques »1. Posez-vous la question : “De quoi ce job a-t-il VRAIMENT besoin ?”
Section intitulée « 1. Posez-vous la question : “De quoi ce job a-t-il VRAIMENT besoin ?” »Avant d’ajouter un job dans needs, demandez-vous : “Si ce job n’existait pas, le mien pourrait-il quand même s’exécuter ?” Si oui, ne l’ajoutez pas.
Exemple : deploy a-t-il besoin d’attendre lint ? Probablement pas — le lint vérifie la qualité du code, mais ne produit rien dont deploy a besoin.
2. Utilisez needs: [] agressivement
Section intitulée « 2. Utilisez needs: [] agressivement »Chaque job qui peut démarrer immédiatement devrait avoir needs: []. C’est le levier le plus puissant pour accélérer vos pipelines.
Règle simple : si le job n’a besoin d’aucun fichier produit par un autre job, mettez needs: [].
3. Désactivez les artefacts inutiles
Section intitulée « 3. Désactivez les artefacts inutiles »Quand vous attendez un job pour son statut (pas ses fichiers), utilisez artifacts: false :
deploy: needs: - job: lint artifacts: false # On veut juste que lint soit passé, pas ses fichiers - job: build artifacts: true # On a besoin du dossier dist/4. Visualisez le graphe régulièrement
Section intitulée « 4. Visualisez le graphe régulièrement »Après avoir modifié vos needs, regardez le graphe dans GitLab (onglet “Needs” du pipeline). Il montre les vraies dépendances et vous aide à repérer les erreurs.
5. Gardez les stages pour l’organisation
Section intitulée « 5. Gardez les stages pour l’organisation »Même avec DAG, les stages restent utiles pour l’organisation visuelle. Regroupez les jobs par “catégorie” (build, test, deploy) même si leur exécution ne suit plus strictement cet ordre.
Erreurs fréquentes
Section intitulée « Erreurs fréquentes »Voici les problèmes les plus courants et comment les résoudre.
1. Dépendance circulaire (circular dependency)
Section intitulée « 1. Dépendance circulaire (circular dependency) »Symptôme : Le pipeline refuse de se créer avec “circular dependency detected”.
Cause : Deux jobs se référencent mutuellement, créant une boucle impossible.
# ❌ INTERDIT : A attend B, mais B attend Ajob_a: needs: ["job_b"]
job_b: needs: ["job_a"]Solution : Revoyez l’architecture. Posez-vous la question : “Qui a vraiment besoin de qui ?” Souvent, un des deux needs est inutile.
2. Trop de dépendances (too many dependencies)
Section intitulée « 2. Trop de dépendances (too many dependencies) »Symptôme : “needs cannot have more than 50 entries”.
Cause : Vous avez listé plus de 50 jobs dans un seul needs.
Solution :
- Simplifiez : ce job a-t-il vraiment besoin de 50 dépendances ?
- Regroupez : créez un job intermédiaire qui attend plusieurs jobs, puis dépendez de lui
- Self-managed : la limite est configurable dans les paramètres administrateur
3. Artefacts “disparus”
Section intitulée « 3. Artefacts “disparus” »Symptôme : “file not found” alors que le job précédent les a bien créés.
Cause : Vous avez ajouté needs sans inclure le job qui produit les artefacts.
Rappel : Avec needs, vous ne recevez que les artefacts des jobs listés. Le comportement “magique” des stages précédents est désactivé.
# ❌ Problème : deploy attend lint, mais n'a pas les artefacts de builddeploy: needs: ["lint"] script: ls dist/ # ERREUR : dist/ n'existe pas !
# ✅ Solution : ajouter build dans needsdeploy: needs: ["lint", "build"] script: ls dist/ # OK : dist/ est téléchargé depuis build4. needs: [] mais le job échoue
Section intitulée « 4. needs: [] mais le job échoue »Symptôme : Vous avez mis needs: [] pour accélérer, mais le job échoue car il manque des fichiers.
Cause : Le job a en fait besoin d’artefacts d’un autre job.
Solution : Identifiez les fichiers manquants et ajoutez le job qui les produit dans needs.
# ❌ Le job a besoin de node_modules/, mais n'attend personnetest: needs: [] script: npm test # ERREUR : node_modules/ n'existe pas !
# ✅ Attendez le job qui installe les dépendancestest: needs: ["install"] script: npm test # OK : node_modules/ est disponibleÀ retenir
Section intitulée « À retenir »needsdéfinit les vraies dépendances, pas les stagesneeds: []= aucune dépendance, démarre immédiatement- Artefacts : avec
needs, seuls ceux des jobs listés sont téléchargés - Limite : max 50 jobs dans
needspar défaut - Pas de boucles — les dépendances doivent être acycliques
- Ne pas mélanger
needsetdependenciesdans un même job - Visualisez le graphe dans GitLab pour valider