
À chaque run, votre pipeline réinstalle 15 paquets pip depuis zéro. Deux fois par job. Et quand les tests échouent, il faut aller chercher les logs dans l’interface GitLab pour comprendre ce qui s’est passé — rien n’est conservé. Dans ce lab, vous allez mettre les dépendances pip en cache (pour ne plus les télécharger à chaque fois) et publier les rapports de tests comme artifacts accessibles directement depuis GitLab.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre la différence entre un artifact et un cache dans GitLab CI/CD
- Configurer un cache pip avec une clé basée sur le hash du fichier
requirements-dev.txt - Publier un rapport JUnit en tant qu’artifact et le visualiser dans GitLab
- Versionner les images Docker avec les variables prédéfinies de GitLab
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Un pipeline qui réinstalle toutes ses dépendances à chaque run est clairement sous-optimal. Sur un projet professionnel avec 50 dépendances et 20 runs par jour, ça représente des heures de temps machine perdues chaque semaine. Le cache est souvent la première optimisation qu’on ajoute après un pipeline fonctionnel.
Les artifacts, eux, servent à transmettre des fichiers entre jobs ou à conserver des données après le pipeline. Les rapports JUnit sont particulièrement utiles : GitLab les lit automatiquement et affiche un résumé des tests dans les Merge Requests, sans avoir à chercher dans les logs.
Situations réelles où ce lab vous aide :
- Un collègue demande « est-ce que les tests passent sur ma MR ? » — les rapports JUnit répondent directement dans l’interface
- Le pipeline prend 5 minutes pour lancer 30 secondes de tests à cause des
pip install - Vous voulez retrouver les logs d’un run passé — les artifacts conservent les fichiers 7 jours par défaut
- Le
docker pushécrase toujourslatestsans versionnement — impossible de savoir quelle image correspond à quel commit
Prérequis
Section intitulée « Prérequis »- Lab 03 complété — ou partir directement de la branche
starter/lab-04 - Avoir lu Artifacts et cache GitLab CI/CD (conseillé)
Point de départ
Section intitulée « Point de départ »-
Passez sur la branche de départ
Fenêtre de terminal cd pipeline-craftgit checkout starter/lab-04 -
Poussez pour déclencher le pipeline
Fenêtre de terminal git push origin starter/lab-04 -
Observez le pipeline dans Build > Pipelines
Le pipeline passe au vert — il hérite des corrections du Lab 03. Mais chaque job réinstalle ses dépendances depuis zéro, et le rapport de tests disparaît après le run.
L’exercice
Section intitulée « L’exercice »Comprendre : artifact vs cache
Section intitulée « Comprendre : artifact vs cache »Avant de coder, il faut clarifier deux concepts souvent confondus.
Un cache est conçu pour accélérer les builds. Il conserve des fichiers entre deux runs du même pipeline sur le même runner — typiquement un dossier de dépendances comme .pip-cache/. Si le cache n’existe pas encore, le job fonctionne quand même (il réinstalle juste tout). Le cache n’est pas garanti : si le runner change, si le cache expire, il sera vide.
Un artifact est un fichier que vous voulez conserver et partager. Il est téléversé sur GitLab après le job et reste accessible pendant la durée d’expiration configurée. Il peut être transmis d’un job à un autre dans le même pipeline (on l’utilise pour passer des binaires compilés d’un stage build à un stage deploy), ou conservé pour être consulté plus tard (rapports de tests, logs).
| Cache | Artifact | |
|---|---|---|
| Objectif | Accélérer le build | Conserver / transmettre des fichiers |
| Partagé entre jobs | Non (même runner) | Oui (pipeline entier) |
| Garanti ? | Non | Oui (jusqu’à expiration) |
| Visible dans GitLab UI | Non | Oui |
Étape 1 — Configurer le cache pip global
Section intitulée « Étape 1 — Configurer le cache pip global »-
Ajoutez une variable globale pour le répertoire de cache pip
En haut du
.gitlab-ci.yml, avant les définitions de jobs, ajoutez :variables:PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"$CI_PROJECT_DIRest une variable prédéfinie de GitLab qui pointe vers le répertoire du projet sur le runner — c’est là que votre code est cloné. On va y créer un dossier.pip-cachepour stocker les paquets pip téléchargés.En configurant
PIP_CACHE_DIR, on dit à pip : « au lieu de mettre les paquets dans le cache système par défaut, mets-les dans ce dossier du projet ». Ça permet à GitLab de mettre ce dossier en cache entre les runs. -
Ajoutez la configuration de cache au job
pytest(c’est lui qui installe le plus de dépendances)pytest:stage: testimage: python:3.12-slimcache:key:files:- requirements-dev.txtpaths:- .pip-cache/before_script:- pip install -r requirements-dev.txtscript:- pytest -vDécortiquons la clé de cache :
key.files: - requirements-dev.txt: la clé du cache est calculée à partir du hash du fichierrequirements-dev.txt. Si vous ajoutez ou supprimez une dépendance (ce qui modifierequirements-dev.txt), la clé change → GitLab crée un nouveau cache. Sirequirements-dev.txtn’a pas changé, la même clé est réutilisée → les dépendances sont déjà là.paths: - .pip-cache/: ce dossier sera sauvegardé et restauré automatiquement autour du job.
-
Ajoutez le cache en lecture seule au job
ruff-lintLe job
ruff-lintn’installe qu’un seul paquet (ruff), mais si vous y mettez aussi le cache, il bénéficiera de ce qui a été mis en cache parpytestlors du run précédent. Ajoutez la clépolicy: pullpour indiquer que ce job ne fait que lire le cache (il ne le met pas à jour) :ruff-lint:stage: lintimage: python:3.12-slimcache:key:files:- requirements-dev.txtpaths:- .pip-cache/policy: pullbefore_script:- pip install ruffscript:- ruff check app/ tests/La politique
pullévite que deux jobs essaient d’écrire dans le cache en même temps.
Étape 2 — Publier le rapport JUnit
Section intitulée « Étape 2 — Publier le rapport JUnit »-
Modifiez le script pytest pour générer un fichier de rapport XML
pytest:...script:- pytest -v --junitxml=report.xmlL’option
--junitxml=report.xmldemande à pytest d’écrire les résultats dans un fichier XML au format JUnit. Ce format est un standard reconnu par GitLab, Jenkins, et de nombreux autres outils CI. -
Déclarez l’artifact juste après le
scriptpytest:stage: testimage: python:3.12-slimcache:key:files:- requirements-dev.txtpaths:- .pip-cache/before_script:- pip install -r requirements-dev.txtscript:- pytest -v --junitxml=report.xmlartifacts:when: alwayspaths:- report.xmlreports:junit: report.xmlexpire_in: 7 daysQuelques précisions :
when: always: conserve l’artifact même si le job échoue. C’est essentiel pour les rapports de tests — c’est précisément quand les tests échouent qu’on veut le rapport.paths: - report.xml: le fichier sera téléchargeable depuis la page du job dans GitLab.reports.junit: report.xml: indique à GitLab que ce fichier est un rapport JUnit. GitLab le parse et affiche un résumé des tests dans les Merge Requests.expire_in: 7 days: après 7 jours, GitLab supprime automatiquement l’artifact pour économiser de l’espace.
Étape 3 — Versionner l’image Docker
Section intitulée « Étape 3 — Versionner l’image Docker »-
Modifiez le script du job
docker-buildpour utiliser le SHA du commit comme tagdocker-build:stage: buildimage: docker:27services:- docker:27-dindvariables: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:latestCes lignes utilisent des variables prédéfinies de GitLab injectées automatiquement dans chaque job :
$CI_REGISTRY_IMAGE: l’adresse du Container Registry de votre projet (ex :registry.gitlab.com/votre-pseudo/pipeline-craft)$CI_COMMIT_SHORT_SHA: les 8 premiers caractères du hash du commit (ex :a1b2c3d4). Chaque push produit un tag unique.$CI_REGISTRY_USERet$CI_REGISTRY_PASSWORD: identifiants pour se connecter au registry — GitLab les injecte automatiquement, vous n’avez rien à configurer.
Le fichier complet
Section intitulée « Le fichier complet »stages: - lint - test - build
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 cache: key: files: - requirements-dev.txt paths: - .pip-cache/ before_script: - pip install -r requirements-dev.txt script: - pytest -v --junitxml=report.xml 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:latestPousser et vérifier
Section intitulée « Pousser et vérifier »-
Committez et poussez
Fenêtre de terminal git add .gitlab-ci.ymlgit commit -m "ci: add pip cache, junit artifact and docker versioning"git push origin starter/lab-04 -
Observez le premier run
Le premier run ne bénéficie pas encore du cache (il n’existe pas encore). C’est normal. Regardez le job
pytest— à la fin, GitLab afficheUploading artifacts...puisreport.xml. -
Déclenchez un deuxième run (faites un commit vide par exemple)
Fenêtre de terminal git commit --allow-empty -m "ci: test cache hit"git push origin starter/lab-04Cette fois, les jobs doivent afficher
Checking cache for ...suivi deSuccessfully extracted cache. Lepip installva beaucoup plus vite. -
Vérifiez le rapport de tests
Après le run, cliquez sur le job
pytestdans GitLab. En bas de la page, vous verrez une section Artifacts avec un lien pour téléchargerreport.xml. Si vous créez une Merge Request sur ce projet, l’onglet Tests affichera automatiquement les résultats.
Vérification
Section intitulée « Vérification »- Le pipeline passe au vert
- Le deuxième run est plus rapide que le premier (cache hit)
- Le fichier
report.xmlest visible comme artifact dans le jobpytest - Le job
docker-buildutilise$CI_COMMIT_SHORT_SHApour taguer l’image
Pièges fréquents
Section intitulée « Pièges fréquents »| Symptôme | Cause | Solution |
|---|---|---|
| Cache jamais utilisé | Clé de cache différente entre les runs | Vérifier que les clés (key:) sont identiques entre le job qui écrit et les jobs qui lisent |
report.xml absent des artifacts | --junitxml=report.xml absent du script pytest | Ajouter l’option à la commande pytest |
| Tests absents dans les MR | reports.junit: manquant dans artifacts: | Le chemin dans reports.junit: doit correspondre exactement au fichier généré |
| Push registry échoue | Container Registry désactivé dans le projet | Activer dans Settings > General > Visibility |
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Les variables prédéfinies de GitLab : GitLab injecte des dizaines de variables dans chaque job (
$CI_COMMIT_REF_NAME,$CI_PROJECT_PATH,$CI_PIPELINE_ID…). Ajoutezenv | grep CI_dans unscript:pour les voir toutes. Voir Artifacts et cache. - Comparez avec
solution/lab-04:git diff starter/lab-04..solution/lab-04montre les corrections complètes.
À retenir
Section intitulée « À retenir »- Un cache accélère les builds en réutilisant des fichiers entre les runs (pas garanti), un artifact conserve des fichiers après un job (garanti jusqu’à expiration)
- La clé de cache basée sur
key.filesinvalide automatiquement le cache quand les dépendances changent — c’est la bonne pratique when: alwayssur les artifacts de tests est essentiel : c’est quand les tests échouent qu’on a le plus besoin du rapport- Les variables prédéfinies (
$CI_REGISTRY_IMAGE,$CI_COMMIT_SHORT_SHA…) évitent de coder en dur des valeurs dans le pipeline