
Dans un projet réel, un pipeline ne doit pas dépendre uniquement d'un git push. Vous avez souvent besoin de lancer des tests chaque nuit, de déclencher un rebuild depuis un outil externe, ou de relancer un pipeline à la demande après une alerte monitoring. Ce lab vous montre comment faire avec les déclencheurs GitLab natifs.
Ce lab se fait sur un projet GitLab réel, pas en simulation : la création d'un schedule et la génération d'un trigger token passent par l'interface du projet, et le pipeline déclenché consomme des minutes de runner.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Déclencher un pipeline via un schedule GitLab
- Déclencher un pipeline via API et trigger token
- Comprendre les valeurs de
$CI_PIPELINE_SOURCE - Écrire des
rulesspécifiques au type de déclenchement
Quel lab commencer ?
Section intitulée « Quel lab commencer ? »Ce lab vient après Lab 07. Si vous êtes déjà à l'aise avec la validation de pipeline, vous pouvez commencer directement depuis starter/lab-08.
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Les équipes DevOps utilisent plusieurs sources de déclenchement selon le besoin :
- push et merge request pour la validation continue
- schedule pour les tests de régression nocturnes
- API/trigger pour orchestrer des pipelines depuis d'autres systèmes
Sans cette maîtrise, vous limitez l'automatisation et vous ratez des scénarios importants.
Prérequis
Section intitulée « Prérequis »- Lab 07, Valider un pipeline terminé
- Avoir lu Déclencheurs de pipelines
Point de départ
Section intitulée « Point de départ »La branche starter/lab-08 contient un .gitlab-ci.yml déjà fonctionnel sur push et merge request. Vous ne partez donc pas d'une page blanche : le travail consiste à ouvrir les sources de déclenchement manquantes, pas à réécrire le pipeline. Gardez cette branche telle quelle et travaillez dessus, la branche solution/lab-08 sert uniquement de point de comparaison.
-
Basculez sur la branche du lab
Fenêtre de terminal cd pipeline-craftgit checkout starter/lab-08 -
Ouvrez le
.gitlab-ci.ymlVous allez ajouter des règles basées sur la source du pipeline.
Le problème
Section intitulée « Le problème »Le pipeline gère déjà les runs MR, main et tags, mais il ne traite pas correctement les déclenchements schedule, trigger et api. Le but de ce lab est de rendre ces sources explicites dans workflow et dans les rules des jobs.
Vous allez faire évoluer le pipeline pour distinguer clairement :
pushscheduletriggerapi
L'exercice
Section intitulée « L'exercice »Étape 1, À vous d'ajouter des règles basées sur la source
Section intitulée « Étape 1, À vous d'ajouter des règles basées sur la source »Cette première étape se joue entièrement dans le fichier .gitlab-ci.yml, sans toucher à l'interface GitLab. Le point clé : le bloc workflow:rules décide si un pipeline existe, les rules d'un job décident s'il s'exécute dans ce pipeline. Une source absente de workflow ne créera jamais de pipeline, même si tous les jobs l'autorisent. Commencez donc par workflow, puis descendez vers les jobs.
-
Ajoutez un job dédié aux runs planifiés (
schedule). -
Remplacez les règles MR basées sur
$CI_MERGE_REQUEST_IIDpar des règles basées sur la source du pipeline. -
Ajoutez des règles explicites sur les jobs de validation pour distinguer :
merge_request_eventtriggerapi
-
Vérifiez que la logique dépend bien de
CI_PIPELINE_SOURCE.
Vérifier votre solution (Étape 1)
workflow basé sur CI_PIPELINE_SOURCE
Section intitulée « workflow basé sur CI_PIPELINE_SOURCE »Remplacez la règle MR historique par une règle source explicite et ajoutez les sources externes :
workflow: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_COMMIT_TAG - if: $CI_PIPELINE_SOURCE == "schedule" - if: $CI_PIPELINE_SOURCE == "trigger" - if: $CI_PIPELINE_SOURCE == "api"Job dédié aux runs planifiés
Section intitulée « Job dédié aux runs planifiés »La règle unique if: $CI_PIPELINE_SOURCE == "schedule" isole ce job : il n'apparaît dans aucun pipeline de push ni de merge request. C'est ce qui permet d'y mettre une suite pytest complète, plus lente, sans pénaliser la boucle de développement. Notez l'absence de --junitxml ici, contrairement au job pytest : la régression nocturne sert d'alerte, pas de rapport de merge request.
nightly-regression: stage: test image: python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de cache: key: files: - requirements-dev.txt paths: - .pip-cache/ before_script: - pip install -r requirements-dev.txt script: - echo "Nightly run on source=$CI_PIPELINE_SOURCE" - pytest -v rules: - if: $CI_PIPELINE_SOURCE == "schedule"Règles basées sur $CI_PIPELINE_SOURCE
Section intitulée « Règles basées sur $CI_PIPELINE_SOURCE »Les six valeurs ci-dessous sont celles que vous rencontrerez dans ce lab. La distinction la plus piégeuse est celle entre trigger et api : les deux passent par l'API REST, mais trigger désigne un appel authentifié par un trigger token sur l'endpoint /trigger/pipeline, alors que api désigne un appel à /pipeline authentifié par un jeton d'accès. Une règle qui n'autorise que api ne verra donc jamais passer un trigger token.
| Valeur | Déclencheur |
|---|---|
push | git push |
merge_request_event | Ouverture / mise à jour MR |
schedule | Tâche planifiée GitLab |
trigger | Trigger token |
api | API REST GitLab |
web | Bouton « Run pipeline » dans l'UI |
Exemple sur un job existant (ruff-lint/pytest) :
ruff-lint: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_PIPELINE_SOURCE == "api" - if: $CI_PIPELINE_SOURCE == "trigger"Étape 2, À vous de créer un schedule dans GitLab
Section intitulée « Étape 2, À vous de créer un schedule dans GitLab »On quitte le fichier YAML pour l'interface : un schedule est un objet du projet, pas une directive du pipeline. Conséquence pratique, il survit aux modifications du .gitlab-ci.yml et s'exécute avec les droits de l'utilisateur qui l'a créé, ce qui compte si ce compte perd son accès au projet. Le schedule ne produira un pipeline que si la source schedule est acceptée par le bloc workflow de l'étape 1.
-
Allez dans Build > Pipeline schedules
-
Créez un schedule quotidien
-
Choisissez la branche cible, l'horaire et le fuseau
Le champ Cron timezone vaut UTC par défaut. Si vous raisonnez en heure locale, changez ce champ ou compensez le décalage dans l'expression cron.
Vérifier votre solution (Étape 2)
Créer un schedule dans GitLab
Section intitulée « Créer un schedule dans GitLab »Le formulaire tient en quatre champs. Le seul qui demande réflexion est Interval Pattern : GitLab accepte une expression cron standard à cinq champs, et propose aussi des raccourcis (Every day, Every week). Prenez l'expression explicite pour ce lab, elle rend le fuseau et la minute d'exécution visibles.
- Allez dans Build > Pipeline schedules
- Cliquez New schedule
- Remplissez les champs :
| Champ | Valeur exemple |
|---|---|
| Description | Régression nocturne |
| Interval Pattern | 0 2 * * * (chaque nuit à 02:00 UTC) |
| Target branch | main |
| Active | ✅ |
- Cliquez Save pipeline schedule
Pour déclencher immédiatement en test, utilisez le bouton de lancement à droite du schedule dans la liste. Le pipeline créé porte bien CI_PIPELINE_SOURCE == "schedule", vous n'avez pas à attendre l'heure programmée pour valider vos règles.
Le formulaire propose un champ Cron timezone, positionné sur UTC par défaut. Laissé tel quel, 0 2 * * * correspond à 02:00 UTC, soit 04:00 à Paris en heure d'été (CEST, UTC+2) et 03:00 en heure d'hiver (CET, UTC+1). L'horaire réel se décale donc d'une heure deux fois par an. Pour figer l'heure locale, sélectionnez explicitement Paris dans ce champ plutôt que de compenser à la main dans l'expression cron.
Étape 3, À vous de déclencher via API avec trigger token
Section intitulée « Étape 3, À vous de déclencher via API avec trigger token »Le trigger token est un secret de projet à portée volontairement étroite : il ne sert qu'à créer un pipeline, il ne donne accès ni au code, ni aux variables, ni au reste de l'API. C'est ce qui le rend acceptable dans un système tiers (outil de supervision, ordonnanceur maison) auquel vous ne confieriez jamais un jeton d'accès personnel. Traitez-le malgré tout comme un mot de passe : quiconque le détient peut consommer vos minutes de runner et exécuter votre pipeline sur la branche de son choix.
-
Générez un token dans Settings > CI/CD > Pipeline trigger tokens.
-
Déclenchez un pipeline via l'API GitLab avec ce token.
-
Vérifiez dans GitLab que la source du pipeline est
trigger.
Vérifier votre solution (Étape 3)
Générer un trigger token
Section intitulée « Générer un trigger token »Un détail de visibilité mérite d'être connu : vous pouvez relire en clair les tokens que vous avez créés, mais des tokens créés par un autre membre du projet ne vous montrent que leurs quatre premiers caractères. Un token perdu par son créateur se révoque et se recrée, il ne se récupère pas auprès d'un collègue. La description sert au moment de la révocation, donnez-lui le nom du système qui va l'utiliser plutôt qu'un libellé générique.
- Allez dans Settings > CI/CD > Pipeline trigger tokens
- Saisissez une description :
test external trigger - Cliquez Add trigger token et copiez le token généré
Appeler l'API pour déclencher un pipeline
Section intitulée « Appeler l'API pour déclencher un pipeline »Le token transite en paramètre de formulaire, pas en en-tête. Passez-le par une variable d'environnement plutôt qu'en clair sur la ligne de commande : un argument curl finit dans l'historique du shell et reste visible dans la liste des processus le temps de l'appel. Le --fail fait renvoyer un code non nul à curl sur une réponse HTTP d'erreur, sans quoi un token invalide passerait pour un succès.
read -rs -p "Trigger token : " TRIGGER_TOKENexport TRIGGER_TOKEN
curl -X POST \ --fail \ -F "token=${TRIGGER_TOKEN}" \ -F ref=main \ "https://gitlab.com/api/v4/projects/<PROJECT_ID>/trigger/pipeline"Récupérez <PROJECT_ID> dans Settings > General > Project ID.
La réponse JSON confirme le déclenchement :
{ "id": 12345, "status": "created", "source": "trigger"}Étape 4, À vous de vérifier la source dans les logs
Section intitulée « Étape 4, À vous de vérifier la source dans les logs »Vos règles peuvent être syntaxiquement correctes et malgré tout ne jamais matcher : GitLab n'affiche aucun avertissement quand une condition rules:if est fausse, le job disparaît simplement du pipeline. La seule preuve fiable est la valeur réellement injectée dans le job. Un echo dans le script la rend visible dans les logs et transforme un doute en constat.
-
Ajoutez temporairement une ligne de debug qui affiche la valeur de
CI_PIPELINE_SOURCE. -
Lancez un pipeline de chaque type et comparez les valeurs observées.
Cette étape vous aide à valider vos règles sans ambiguïté.
Vérifier votre solution (Étape 4)
Vérification dans les logs pytest
Section intitulée « Vérification dans les logs pytest »La ligne d'echo se place en tête du script, avant toute commande susceptible d'échouer : si pytest plante, vous voulez quand même avoir lu la source du pipeline. Le job pytest est un bon porteur pour cette trace parce que ses rules couvrent quatre sources sur six, il s'exécutera donc dans presque tous vos essais.
pytest: script: - 'echo "Pipeline source: $CI_PIPELINE_SOURCE"' - pytest -v --junitxml=report.xmlLes logs affichent la valeur exacte selon le déclencheur :
- MR →
Pipeline source: merge_request_event - schedule →
Pipeline source: schedule - trigger API →
Pipeline source: trigger - API REST →
Pipeline source: api
Vous pouvez garder cette ligne echo le temps du lab pour observer le routage des règles, puis la retirer ensuite.
Le fichier complet
Section intitulée « Le fichier complet »Voici le .gitlab-ci.yml obtenu à l'issue des quatre étapes. Comparez-le au vôtre en regardant d'abord les blocs rules : c'est là que se concentre tout le travail du lab, le reste (stages, cache, images) est identique à la branche de départ. Les jobs docker-build, deploy-staging et deploy-production conservent volontairement une règle sur la seule branche par défaut : on ne veut ni construire ni déployer depuis un déclenchement externe.
Voir le fichier .gitlab-ci.yml complet
stages: - lint - test - build - deploy
workflow: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_COMMIT_TAG - if: $CI_PIPELINE_SOURCE == "schedule" - if: $CI_PIPELINE_SOURCE == "trigger" - if: $CI_PIPELINE_SOURCE == "api"
variables: PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
ruff-lint: stage: lint image: python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de cache: key: files: - requirements-dev.txt paths: - .pip-cache/ policy: pull before_script: - pip install ruff script: - ruff check app/ tests/ rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_PIPELINE_SOURCE == "api" - if: $CI_PIPELINE_SOURCE == "trigger"
pytest: stage: test image: python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de cache: key: files: - requirements-dev.txt paths: - .pip-cache/ before_script: - pip install -r requirements-dev.txt script: - 'echo "Pipeline source: $CI_PIPELINE_SOURCE"' - pytest -v --junitxml=report.xml artifacts: when: always paths: - report.xml reports: junit: report.xml expire_in: 7 days rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_PIPELINE_SOURCE == "api" - if: $CI_PIPELINE_SOURCE == "trigger"
nightly-regression: stage: test image: python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de cache: key: files: - requirements-dev.txt paths: - .pip-cache/ before_script: - pip install -r requirements-dev.txt script: - echo "Nightly run on source=$CI_PIPELINE_SOURCE" - pytest -v rules: - if: $CI_PIPELINE_SOURCE == "schedule"
docker-build: stage: build image: docker:27@sha256:aa3df78ecf320f5fafdce71c659f1629e96e9de0968305fe1de670e0ca9176ce 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 rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
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_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_BRANCH == $CI_DEFAULT_BRANCH when: manualVérification
Section intitulée « Vérification »Le lab est réussi quand vous obtenez quatre pipelines de sources différentes sur le même dépôt et que la composition des jobs change d'un pipeline à l'autre. Un pipeline qui contient exactement les mêmes jobs quelle que soit la source signale des rules qui ne discriminent rien.
- Un schedule déclenche bien un pipeline
- Un trigger API déclenche bien un pipeline
- Les jobs s'exécutent selon la valeur de
CI_PIPELINE_SOURCE - Vous savez expliquer la différence entre trigger token et personal access token
Pièges fréquents
Section intitulée « Pièges fréquents »Le trigger token sert à déclencher un pipeline, pas à accéder à toute l'API GitLab. Le personal access token a un autre usage. Mélanger les deux est une erreur classique.
Autre point : un cron mal calé en UTC donne l'impression que le schedule ne fonctionne pas. Vérifiez toujours le fuseau horaire avant de conclure.
À retenir
Section intitulée « À retenir »- Un pipeline GitLab peut être déclenché sans push
$CI_PIPELINE_SOURCEpermet d'adapter les jobs au contexte- Schedule et API couvrent des besoins complémentaires
- Tester vos règles par source évite les surprises en production