Aller au contenu
CI/CD & Automatisation medium

Lab 17, Workflows branches et merge requests

60 min de lecture

logo gitlab

Un pipeline bien construit peut rester inefficace si son workflow est mal défini. Vous obtenez alors des pipelines en double, des runs inutiles, et des comportements incohérents entre MR et branches. Dans ce lab, vous corrigez ce pilotage global.

  • Construire un bloc workflow: rules lisible et priorisé
  • Différencier contexte MR, branche simple, branche par défaut et tag
  • Éviter les doublons via $CI_OPEN_MERGE_REQUESTS
  • Ajuster les règles de déploiement selon le contexte d'exécution

Dans les équipes actives, un même commit peut déclencher plusieurs pipelines si le workflow n'est pas clairement défini. Cela consomme des minutes CI et brouille la lecture des statuts dans les merge requests.

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

  • pipelines branch + MR en parallèle pour le même changement ;
  • déploiements déclenchés dans un mauvais contexte ;
  • manque de clarté sur les flux tag/release.

Avant de toucher aux règles, il faut un point de comparaison. Le run baseline de l'étape 3 sert exactement à ça : il montre le comportement actuel, doublons compris, sur lequel vous mesurerez l'effet de vos modifications. Regardez surtout, dans la liste des pipelines du projet, la colonne qui indique la source du déclenchement (push, merge request event) : c'est elle qui révèle les runs redondants.

  1. Basculez sur la branche du lab

    Fenêtre de terminal
    cd pipeline-craft
    git checkout starter/lab-17
  2. Ouvrez .gitlab-ci.yml

    Vérifiez le bloc workflow actuel.

  3. Lancez un run baseline

    Fenêtre de terminal
    git push origin starter/lab-17

Les règles workflow actuelles ne couvrent pas proprement tous les cas. Vous devez prioriser les conditions pour obtenir un flux explicite et non ambigu.

Dans un bloc workflow: rules, GitLab évalue les règles de haut en bas et s'arrête à la première qui correspond. L'ordre n'est donc pas cosmétique, c'est la logique elle-même. La séquence à construire suit un principe simple : le cas le plus spécifique en premier (la merge request), puis la règle de blocage qui neutralise le doublon, puis les cas généraux. Dans un bloc workflow, le mot-clé when n'accepte que deux valeurs, always ou never : une règle qui correspond sans porter de when: never autorise la création du pipeline.

  1. Placez d'abord le cas MR

    Indice : ce cas doit être évalué avant les règles plus génériques sur les branches.

  2. Ajoutez un filtre anti-duplication

    Indice : une règle when: never bien placée évite les doublons branch/MR.

  3. Gardez ensuite les cas branche par défaut, branche simple, et tag

👉 Vérifier votre solution (Étape 1)
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

Ce workflow donne la priorité aux pipelines MR et évite un pipeline branch redondant quand une MR est déjà ouverte.

Deux points de lecture méritent d'être explicités. $CI_OPEN_MERGE_REQUESTS n'est renseignée que si la branche poussée est la source d'au moins une merge request ouverte : sur une branche sans MR, la deuxième règle ne correspond pas et le pipeline branch est bien créé par la quatrième. Ensuite, la règle $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH produit ici le même effet que la règle $CI_COMMIT_BRANCH qui la suit, elle est conservée pour rendre le cas de la branche par défaut explicite et servir de point d'accroche si vous devez plus tard lui donner un traitement particulier.

Le workflow décide si un pipeline existe, les rules d'un job décident si ce job y figure. Les deux niveaux se cumulent : un job dont les règles autorisent le contexte MR ne s'exécutera jamais si le workflow bloque les pipelines de MR. C'est la source de confusion la plus fréquente sur ce sujet, un job « qui ne part pas » alors que ses propres règles sont correctes. Vérifiez donc toujours le workflow global avant de suspecter les règles d'un job.

  1. Vérifiez les rules de deploy-staging et deploy-production
  2. Ajoutez les règles manquantes liées au contexte MR train et release tag
  3. Évitez les règles contradictoires entre workflow global et jobs
👉 Vérifier votre solution (Étape 2)

1️⃣ Règles de déploiement attendues dans ci/deploy.yml

Section intitulée « 1️⃣ Règles de déploiement attendues dans ci/deploy.yml »

Les deux jobs illustrent deux politiques opposées. deploy-staging part automatiquement dans deux contextes, un pipeline de merge train et la branche par défaut. deploy-production ne part automatiquement que sur un tag, et reste en when: manual sur la branche par défaut, ce qui affiche un bouton à déclencher au lieu de partir tout seul. Notez l'ordre : la règle du tag est placée avant celle de la branche parce que les deux ne peuvent pas correspondre au même pipeline, mais l'écrire dans cet ordre garde la lecture cohérente avec le workflow global.

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_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
rules:
- if: $CI_COMMIT_TAG
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual

glab ci lint valide la syntaxe du fichier et la résolution des include, pas la logique de vos règles : un workflow qui ne déclenche jamais rien passe le lint sans erreur. La validation réelle passe donc par l'observation des pipelines produits après le push, en comparant avec le run baseline de départ.

  1. Validation lint

    Fenêtre de terminal
    glab ci lint .gitlab-ci.yml
  2. Commit et push

    Fenêtre de terminal
    git add .gitlab-ci.yml ci/deploy.yml
    git commit -m "ci: implement advanced workflow rules"
    git push origin starter/lab-17
  3. Vérifiez les déclenchements sur push et MR

👉 Vérifier votre solution (Étape 3)

Ces quatre observations se font dans la vue CI/CD > Pipelines du projet, en regardant la colonne qui indique la source du déclenchement. Le deuxième point est le plus important du lab : sur une branche avec une MR ouverte, vous devez voir un seul pipeline par push, et non deux.

  • une MR déclenche un pipeline MR dédié ;
  • un push sur une branche avec MR ouverte ne déclenche pas de pipeline branch en plus ;
  • un tag peut déclencher le flux de production ;
  • les règles de déploiement restent cohérentes avec le workflow global.

Les deux fichiers ci-dessous montrent le résultat attendu en entier, à utiliser comme référence de comparaison plutôt que comme copier-coller. Un détail du .gitlab-ci.yml mérite l'attention : default: interruptible: true rend chaque job annulable quand un nouveau commit rend son pipeline redondant. Ce marquage ne suffit pas seul, l'annulation dépend du réglage d'auto-annulation du projet ou du bloc workflow:auto_cancel. Une fois les deux en place, c'est le second levier d'économie de minutes CI après le workflow MR-first.

📄 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/deploy.yml complet
deploy-staging:
stage: deploy
image: alpine:3.20@sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc
script:
- echo "Deploying $CI_COMMIT_SHORT_SHA to staging..."
- ./scripts/deploy-demo.sh staging
rules:
- if: $CI_MERGE_REQUEST_EVENT_TYPE == "merge_train"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
deploy-production:
stage: deploy
image: alpine:3.20@sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc
script:
- echo "Deploying $CI_COMMIT_SHORT_SHA to production..."
- ./scripts/deploy-demo.sh production
rules:
- if: $CI_COMMIT_TAG
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual

Le lab est réussi quand ces quatre points sont vrais en même temps. Le troisième demande une manipulation supplémentaire : poussez un tag (git tag v0.1.0 && git push origin v0.1.0) pour vérifier que le flux release existe bien, sinon la dernière règle du workflow reste non testée et vous découvrirez son éventuel défaut le jour d'une vraie release.

  • Le pipeline MR passe par la règle dédiée
  • Un commit sur branche avec MR ouverte ne crée pas de pipeline branch inutile
  • Les tags déclenchent le flux release attendu
  • Les déploiements suivent les contextes prévus

Dans workflow: rules, l'ordre est critique : la première règle qui matche décide. Une règle générale placée trop tôt peut court-circuiter les cas spécifiques.

Autre piège : corriger uniquement les règles de job sans corriger le workflow global.

  • Le workflow est le garde-barrière principal de votre CI
  • Un design MR-first réduit bruit et coûts CI
  • Les règles doivent être explicites et ordonnées
  • Le comportement release doit rester prédictible

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn