Première étape d'un pipeline CI/CD : Récupération du code et configuration de l'environnement

Vous poussez un commit. Votre outil CI/CD détecte le changement et lance un nouveau pipeline. Mais avant toute compilation, test ou déploiement, le pipeline doit répondre à trois questions fondamentales : Quel code dois-je traiter ? Quels outils sont à ma disposition ? Mon espace de travail est-il propre ?

Cette première étape est souvent négligée, mais c'est là que de nombreux échecs de pipeline commencent. Un espace de travail sale, une version d'outil incompatible ou une dépendance manquante peuvent faire dérailler tout un pipeline avant même qu'il n'ait commencé un travail significatif. Passons en revue ce qui se passe lors du checkout et de la préparation initiale, et pourquoi bien faire cette étape est crucial pour la suite.

L'étape de checkout : récupérer le bon code

Lorsqu'un pipeline se déclenche, il transporte les informations de l'événement déclencheur : un hash de commit, un nom de branche ou un tag. L'étape de checkout utilise ces informations pour extraire la version exacte du code depuis le dépôt vers l'espace de travail du pipeline.

L'espace de travail est un dossier temporaire sur la machine qui exécute le pipeline. Cette machine est généralement appelée runner ou agent, selon l'outil CI/CD utilisé. Le pipeline télécharge le code dans ce dossier, et tout le reste — compilations, tests, déploiements — se déroule dans cet espace.

Imaginez que vous arrivez à un nouveau bureau. Vous devez savoir sur quel projet vous travaillez, quelle version du projet utiliser, et quels outils sont disponibles à votre poste. Sans cela, vous ne pouvez pas commencer.

Le diagramme suivant montre la séquence des actions qui se déroulent dans la première étape d'un pipeline CI/CD :

Voici un exemple concret avec GitHub Actions :

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js 18
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'
flowchart TD A[Événement déclencheur : commit, branche ou tag] --> B[Récupération du code : extraction du hash exact] B --> C[Nettoyage du workspace : suppression des fichiers résiduels] C --> D[Identification de la build : étiquetage de l'artefact par branche/tag] D --> E[Configuration de l'environnement : installation des outils et dépendances] E --> F[Cache disponible ?] F -- Oui --> G[Restauration des dépendances mises en cache] F -- Non --> H[Téléchargement de dépendances fraîches] G --> I[Prêt pour l'étape de build] H --> I

Pourquoi un espace de travail propre est important

Chaque exécution de pipeline doit démarrer avec un espace de travail propre. Si des fichiers d'une exécution précédente subsistent, ils peuvent contaminer la build en cours. Un fichier de configuration oublié, un binaire compilé obsolète ou une ancienne dépendance peuvent amener le pipeline à produire un artefact qui ne correspond pas au code actuel. Déboguer ce genre de problème est pénible car le problème ne vient pas de votre code, mais des résidus d'une exécution antérieure.

La plupart des outils CI/CD proposent une option de nettoyage du workspace. Certains l'activent par défaut, d'autres nécessitent une configuration manuelle. Si vous mettez en place un pipeline, assurez-vous que cette option est activée. C'est un petit réglage qui évite une grande classe de bugs difficiles à trouver.

Identifier ce que vous construisez

Après le checkout, le pipeline doit savoir quelle branche ou quel tag il traite. Cette information détermine comment l'artefact résultant sera étiqueté et où il ira ensuite.

Par exemple, un commit sur la branche main peut produire un artefact étiqueté latest ou stable. Un commit sur une branche de fonctionnalité peut produire un artefact avec le nom de la branche et un numéro de build. Un tag comme v1.2.3 doit produire un artefact étiqueté avec cette version exacte.

Cet étiquetage est important car il permet aux équipes de retracer les artefacts jusqu'à leur source. Quand quelqu'un demande « quelle version du code a produit cet artefact ? », l'étiquette doit donner une réponse claire. Sans étiquetage cohérent, la gestion des artefacts devient un jeu de devinettes.

Configuration de l'environnement

Une fois le code en place, le pipeline doit préparer son environnement. Par environnement, on entend ici plus que le simple dossier où réside le code. Cela inclut tous les outils et dépendances nécessaires pour compiler, tester et déployer l'application.

Une application Java a besoin d'une version spécifique du JDK. Une application Node.js nécessite le bon runtime Node.js et npm. Une migration de base de données a besoin d'un outil comme Flyway ou Liquibase. Chacun de ces outils doit être disponible dans l'environnement du pipeline, à la bonne version.

Le problème du « ça marche sur ma machine »

L'une des frustrations les plus courantes en CI/CD est le décalage entre l'environnement local d'un développeur et l'environnement du pipeline. Un développeur exécute la build sur son ordinateur portable, tout passe, et il pousse le code. Le pipeline le récupère, exécute la même build, et elle échoue.

La cause est presque toujours une différence d'environnement. Le développeur a JDK 17 installé localement, mais le pipeline utilise JDK 11. Le développeur a un package npm global que le pipeline n'a pas. L'ordinateur du développeur a un système d'exploitation ou une architecture différente.

C'est le classique problème du « ça marche sur ma machine », et c'est le signe que l'environnement du pipeline n'est pas défini de manière suffisamment explicite.

Rendre les environnements reproductibles

La solution est de définir l'environnement du pipeline de manière explicite, afin qu'il puisse être reproduit partout. Il existe plusieurs approches courantes :

  • Images Docker : Empaquetez tous les outils nécessaires dans une image Docker. Le pipeline s'exécute dans un conteneur basé sur cette image, garantissant le même environnement à chaque fois.
  • Fichiers de version d'outils : Utilisez des fichiers comme .tool-versions (pour asdf), .nvmrc (pour Node.js) ou .ruby-version pour déclarer les versions exactes des outils. Le pipeline lit ces fichiers et installe les versions spécifiées.
  • Gestionnaires d'environnement : Des outils comme Conda pour Python ou SDKMAN pour Java peuvent gérer les versions d'outils de manière déclarative.

L'objectif est le même : l'environnement du pipeline doit être reproductible partout où le pipeline s'exécute. Si vous pouvez exécuter le pipeline sur votre ordinateur portable, sur un serveur CI et sur la machine d'un collègue, et obtenir le même résultat, vous avez résolu le problème de cohérence de l'environnement.

Mise en cache : vitesse vs fraîcheur

Certains pipelines ajoutent une mise en cache à cette étape pour accélérer les exécutions suivantes. Les dépendances téléchargées lors d'une exécution précédente peuvent être stockées et réutilisées. Cela a du sens pour de grands ensembles de dépendances, comme node_modules pour Node.js ou venv pour Python.

Mais la mise en cache introduit un compromis. Un cache obsolète peut amener le pipeline à utiliser d'anciennes dépendances qui auraient dû être remplacées. Si une dépendance a été mise à jour dans le dépôt, mais que le cache contient encore l'ancienne version, le pipeline pourrait compiler contre un code obsolète.

Si vous utilisez la mise en cache, assurez-vous que la clé de cache inclut suffisamment d'informations pour l'invalider lorsque les dépendances changent. Une approche courante consiste à hacher le fichier de dépendances (comme package-lock.json ou requirements.txt) et à utiliser ce hash comme partie de la clé de cache. Lorsque le fichier de dépendances change, la clé de cache change, et un téléchargement frais a lieu.

Ce que le pipeline a après cette étape

Une fois le checkout et la configuration de l'environnement terminés, le pipeline dispose :

  • Du code exact provenant du commit, de la branche ou du tag déclencheur
  • D'un espace de travail propre, sans fichiers résiduels
  • D'une étiquette connue pour l'artefact qu'il va produire
  • De tous les outils et dépendances nécessaires pour les étapes suivantes

C'est la fondation. Sans elle, chaque étape ultérieure — compilation, test, déploiement — repose sur l'incertitude. Avec elle, le pipeline peut avancer en toute confiance.

Une checklist rapide pour la première étape de votre pipeline

  • Le nettoyage du workspace est activé ou configuré
  • Le checkout utilise le hash exact du commit déclencheur
  • L'étiquetage de l'artefact correspond aux conventions de branche ou de tag
  • Les versions des outils sont déclarées explicitement (Docker, fichiers de version d'outils ou gestionnaire d'environnement)
  • Les clés de cache incluent les hash des fichiers de dépendances si la mise en cache est utilisée

Ce qu'il faut retenir

Les premières secondes d'une exécution de pipeline déterminent si le reste du pipeline s'exécute sur des bases solides. Un espace de travail propre, le bon code et un environnement reproductible ne sont pas des détails optionnels. Ils sont la fondation qui rend chaque étape ultérieure prévisible et débogable. Investissez du temps pour bien faire cette étape, et vous économiserez bien plus de temps à résoudre des échecs qui s'avèrent être des problèmes d'environnement plutôt que des problèmes de code.