
Votre pipeline lance tous les jobs à chaque commit, même quand ce n'est pas nécessaire ? Les rules permettent de contrôler précisément quand un job s'exécute, sur quelle branche, pour quel type de changement, avec quelle approbation.
Ce guide vous montre comment optimiser vos pipelines en exécutant uniquement ce qui est nécessaire, et comment éviter le piège classique des pipelines qui "skip" sans raison apparente.
Ce guide est fait pour vous si...
Section intitulée « Ce guide est fait pour vous si... »Les quatre cartes ci-dessous mènent chacune à une section du guide. Choisissez
celle qui décrit votre situation actuelle : les trois premières traitent
d'écriture de règles, la dernière donne des .gitlab-ci.yml complets à
adapter. Si votre pipeline apparaît skipped sans message d'erreur, prenez
la troisième en priorité, la cause est presque toujours dans workflow:rules
et non dans les règles de vos jobs.
Prérequis
Section intitulée « Prérequis »Avant de continuer, assurez-vous de maîtriser :
- Variables GitLab CI/CD (les rules utilisent des variables)
- Structure de base d'un
.gitlab-ci.yml
Pourquoi les rules sont essentielles
Section intitulée « Pourquoi les rules sont essentielles »Sans rules, tous les jobs s'exécutent à chaque pipeline. C'est un gaspillage de ressources et de temps :
- Tests complets alors que seul le README a changé
- Build Docker alors que le code n'a pas bougé
- Déploiement automatique sans validation humaine
Les rules permettent d'exécuter uniquement ce qui est nécessaire, quand c'est nécessaire.
Les règles de base : if, changes, exists
Section intitulée « Les règles de base : if, changes, exists »if : condition sur une variable
Section intitulée « if : condition sur une variable »La règle la plus utilisée. Teste une expression qui renvoie vrai ou faux.
job: script: echo "Déploiement" rules: - if: '$CI_COMMIT_BRANCH == "main"'Opérateurs disponibles :
| Opérateur | Signification | Exemple |
|---|---|---|
== | Égal à | $VAR == "value" |
!= | Différent de | $VAR != "skip" |
=~ | Match regex | $VAR =~ /^feature-/ |
!~ | Ne match pas regex | $VAR !~ /wip/ |
&& | ET logique | $A == "x" && $B == "y" |
|| | OU logique | $A == "x" || $A == "y" |
Variables les plus utilisées dans les rules :
| Variable | Valeur | Cas d'usage |
|---|---|---|
$CI_COMMIT_BRANCH | Nom de la branche | Limiter à main, develop |
$CI_COMMIT_TAG | Nom du tag (si tag) | Déployer uniquement les releases |
$CI_PIPELINE_SOURCE | Source du pipeline | push, merge_request_event, schedule |
$CI_MERGE_REQUEST_ID | ID de la MR | Jobs spécifiques aux MRs |
# Exemples pratiquesrules: # Sur la branche main uniquement - if: '$CI_COMMIT_BRANCH == "main"'
# Sur un tag de release (v1.0.0, v2.3.4...) - if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
# Uniquement pour les merge requests - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
# Pipeline planifié (cron) - if: '$CI_PIPELINE_SOURCE == "schedule"'changes : condition sur les fichiers modifiés
Section intitulée « changes : condition sur les fichiers modifiés »Exécute le job uniquement si certains fichiers ont été modifiés dans le commit.
build_frontend: script: npm run build rules: - changes: - "frontend/**/*" - "package.json" - "package-lock.json"Patterns supportés :
| Pattern | Signification |
|---|---|
src/*.js | Fichiers .js dans src/ |
src/**/*.js | Fichiers .js dans src/ et sous-dossiers |
*.md | Fichiers .md à la racine |
**/*.md | Tous les fichiers .md du projet |
exists : condition sur l'existence d'un fichier
Section intitulée « exists : condition sur l'existence d'un fichier »Exécute le job si un fichier existe dans le repository.
docker_build: script: docker build -t myapp . rules: - exists: - DockerfileUtile pour les monorepos où tous les projets n'ont pas les mêmes fichiers.
Combiner les conditions
Section intitulée « Combiner les conditions »Vous pouvez combiner if, changes et exists dans une même règle :
deploy_docs: script: ./deploy-docs.sh rules: # Sur main ET si des fichiers docs ont changé - if: '$CI_COMMIT_BRANCH == "main"' changes: - "docs/**/*" - "mkdocs.yml"Attention : dans une règle, les conditions sont en ET. Pour un OU, utilisez plusieurs règles :
job: rules: # Sur main OU sur un tag de release - if: '$CI_COMMIT_BRANCH == "main"' - if: '$CI_COMMIT_TAG =~ /^v\d+/'Contrôler le déclenchement avec when
Section intitulée « Contrôler le déclenchement avec when »when définit comment le job démarre si la règle matche.
Les valeurs de when
Section intitulée « Les valeurs de when »Six valeurs seulement, et la nuance qui compte se situe entre never et les
autres. never exclut le job du pipeline : il n'apparaît même pas dans
l'interface. Les cinq autres l'incluent et se contentent de décider quand
il démarre. Retenez aussi que on_success est la valeur par défaut : un job
sans when explicite démarre dès que les étapes précédentes ont réussi. Dans
workflow:rules, seules always et never sont acceptées.
| Valeur | Comportement |
|---|---|
on_success | Démarre automatiquement si les jobs précédents ont réussi (défaut) |
on_failure | Démarre uniquement si un job précédent a échoué |
always | Démarre toujours, quel que soit le résultat des jobs précédents |
manual | Attend un clic dans l'interface pour démarrer |
delayed | Démarre automatiquement après un délai |
never | Ne démarre jamais (exclut le job) |
Quatre usages courants de when
Section intitulée « Quatre usages courants de when »Les quatre extraits qui suivent couvrent l'essentiel de ce que vous écrirez au
quotidien. Observez surtout le dernier : il montre le couple d'exclusion,
une première règle when: never qui écarte les branches concernées, puis une
règle finale sans condition qui rattrape tout le reste. Sans cette seconde
règle, le job ne s'exécuterait nulle part, car un job dont aucune règle ne
matche est simplement retiré du pipeline.
Déploiement manuel en production :
deploy_prod: script: ./deploy.sh production rules: - if: '$CI_COMMIT_BRANCH == "main"' when: manualNotification en cas d'échec :
notify_failure: script: ./send-slack-alert.sh rules: # Condition explicite + when: on_failure - if: '$CI_PIPELINE_SOURCE' when: on_failureDéploiement différé (canary) :
deploy_canary: script: ./deploy.sh canary rules: - if: '$CI_COMMIT_BRANCH == "main"' when: delayed start_in: 30 minutesExclure explicitement :
heavy_tests: script: ./run-all-tests.sh rules: # Pas sur les branches WIP - if: '$CI_COMMIT_BRANCH =~ /^wip-/' when: never # Sinon, exécuter normalement - when: on_successworkflow:rules : contrôler le pipeline entier
Section intitulée « workflow:rules : contrôler le pipeline entier »workflow:rules détermine si le pipeline lui-même doit être créé. C'est différent des rules au niveau des jobs qui contrôlent chaque job individuellement.
Pourquoi c'est important
Section intitulée « Pourquoi c'est important »Sans workflow:rules, GitLab crée un pipeline pour chaque push, même si aucun job ne doit s'exécuter. Cela crée du bruit dans l'interface.
Avec workflow:rules, vous pouvez empêcher la création du pipeline dans certains cas.
Exemple : éviter les pipelines en double
Section intitulée « Exemple : éviter les pipelines en double »workflow: rules: # Pas de pipeline si c'est un tag (on déploie via autre workflow) - if: '$CI_COMMIT_TAG' when: never # Pas de pipeline si la branche a une MR ouverte # (le pipeline MR suffit) - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS' when: never # Pour les merge requests - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' # Pour les pushs sur les branches - if: '$CI_COMMIT_BRANCH'Le piège classique : pipeline qui "skip"
Section intitulée « Le piège classique : pipeline qui "skip" »C'est le symptôme le plus déroutant de GitLab CI, parce qu'il ne produit
aucun message d'erreur : le fichier est valide, le lint passe, et pourtant
rien ne se lance. La cause tient à une règle implicite qu'on oublie vite : un
workflow:rules dont aucune entrée ne matche empêche la création du
pipeline. Il n'existe pas de comportement par défaut de repli.
Symptôme : vous poussez du code, le pipeline apparaît comme "skipped" ou ne démarre pas du tout.
Cause probable : workflow:rules empêche la création du pipeline.
Diagnostic :
- Vérifiez votre section
workflow:rules - Identifiez quelle règle matche avec vos conditions actuelles
- Si aucune règle ne matche, le pipeline est skipped
# ❌ Problème : ce workflow ne matche jamais pour les pushs simplesworkflow: rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
# ✅ Solution : ajouter les autres casworkflow: rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - if: '$CI_COMMIT_BRANCH'Exemples pratiques
Section intitulée « Exemples pratiques »Les deux fichiers suivants sont complets et copiables tels quels dans un
.gitlab-ci.yml. Ils répondent à la demande la plus fréquente : ne pas relancer
un build et une suite de tests quand seule la documentation a bougé.
Pipeline optimisé par type de changement
Section intitulée « Pipeline optimisé par type de changement »Ce fichier combine les trois mécanismes vus plus haut. Le job lint n'a
volontairement aucune règle : il tourne partout, parce qu'il coûte quelques
secondes. Les jobs build et test sont conditionnés par changes sur
src/**/*, doublé d'un if sur $CI_PIPELINE_SOURCE pour neutraliser le cas
où changes est toujours vrai. Le déploiement en production est le
seul à porter when: manual : le pipeline s'arrête là et attend un clic.
workflow: rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - if: '$CI_COMMIT_BRANCH == "main"' - if: '$CI_COMMIT_TAG'
stages: - lint - build - test - deploy
# Lint : toujours (rapide, peu coûteux)lint: stage: lint script: npm run lint
# Build : seulement si le code a changébuild: stage: build script: npm run build rules: - if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"' changes: - "src/**/*" - "package*.json"
# Tests : seulement si le code a changétest: stage: test script: npm test rules: - if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"' changes: - "src/**/*" - "tests/**/*" - "package*.json"
# Deploy staging : auto sur maindeploy_staging: stage: deploy script: ./deploy.sh staging environment: name: staging rules: - if: '$CI_COMMIT_BRANCH == "main"'
# Deploy prod : manuel sur tagsdeploy_prod: stage: deploy script: ./deploy.sh production environment: name: production rules: - if: '$CI_COMMIT_TAG =~ /^v\d+/' when: manualÉviter les exécutions redondantes
Section intitulée « Éviter les exécutions redondantes »Quand une merge request est ouverte sur une branche, chaque push y crée
deux pipelines : celui de la branche et celui de la MR. Ce workflow supprime
le doublon grâce à $CI_OPEN_MERGE_REQUESTS, une variable qui n'est renseignée
que si la branche courante est la source d'au moins une MR ouverte. L'ordre est
déterminant : la règle when: never doit précéder la règle générale
$CI_COMMIT_BRANCH, sinon cette dernière matche d'abord et le doublon revient.
workflow: rules: # Un tag déclenche son propre pipeline, pas besoin du push - if: '$CI_COMMIT_TAG' # Pour les MRs, utiliser le pipeline MR - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' # Pour les pushs sur branches sans MR ouverte - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS' when: never - if: '$CI_COMMIT_BRANCH'Erreurs fréquentes
Section intitulée « Erreurs fréquentes »Ce tableau se lit par le symptôme, celui que vous constatez dans
l'interface GitLab. Le réflexe utile est de distinguer d'abord ce qui est
skipped au niveau du pipeline de ce qui est absent au niveau du job :
dans le premier cas rien n'apparaît du tout, dans le second le pipeline existe
mais un job manque à l'appel. Cette distinction oriente vers workflow:rules
ou vers les rules du job, et évite de modifier le mauvais fichier.
| Symptôme | Cause probable | Solution |
|---|---|---|
| Pipeline entier "skipped" | workflow:rules ne matche pas | Ajouter une règle pour votre cas |
| Job jamais exécuté | Ordre des règles (never en dernier) | Mettre les exclusions en premier |
| Job toujours exécuté | Pas de règle, comportement par défaut | Ajouter rules: explicites |
changes toujours vrai | Pipeline schedule ou web | changes ne fonctionne qu'avec push/MR |
| Variables non définies dans rules | Variable inexistante | Tester avec $VAR (vide = faux) |
Migrer depuis only/except
Section intitulée « Migrer depuis only/except »only et except figurent dans la liste des mots-clés dépréciés de GitLab et ne sont plus activement développés. Migrez vos pipelines vers rules, qui exprime les mêmes conditions avec des expressions de variables plutôt qu'avec des listes de branches.
Faites la bascule job par job jusqu'au bout. GitLab déconseille de mélanger des jobs only/except et des jobs rules dans un même pipeline : les comportements par défaut diffèrent, notamment sur les pipelines de merge request, et le résultat devient difficile à prévoir. Un job qui porterait les deux syntaxes en même temps provoque en outre une erreur de configuration.
# ❌ Ancien style (deprecated)deploy: script: ./deploy.sh only: - main except: - schedules
# ✅ Nouveau styledeploy: script: ./deploy.sh rules: - if: '$CI_PIPELINE_SOURCE == "schedule"' when: never - if: '$CI_COMMIT_BRANCH == "main"'À retenir
Section intitulée « À retenir »rulescontrôle quand un job s'exécute,workflow:rulescontrôle quand le pipeline est créé.- Première règle qui matche gagne, ordonnez vos règles du plus spécifique au plus général.
ifteste des variables,changesteste les fichiers modifiés,existsteste l'existence.when: neveren premier pour exclure,when: on_successen dernier par défaut.changesne filtre rien sur les pipelinesscheduleetwebni sur une nouvelle branche : faute de base de comparaison, GitLab considère tous les fichiers comme modifiés et la condition vaut vrai.- Pipeline "skipped" = vérifier
workflow:rulesen premier.
On passe à la pratique
Section intitulée « On passe à la pratique »Mettez ces règles en pratique dans le Lab 06, Contrôler l'exécution.
Testez vos connaissances
Section intitulée « Testez vos connaissances »Dix questions tirées de la banque GitLab CI/CD, centrées sur l'ordre
d'évaluation des règles et sur la frontière entre rules et workflow:rules.
Comptez cinq minutes et visez 70 % pour considérer le sujet acquis. Un
échec sur les questions changes est le signal qu'il faut relire l'encadré sur
les pièges avant d'attaquer le lab.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications