Aller au contenu principal
outilsL'intégration continue

L'intégration continue

Ce que ce chapitre apporte

  • Expliquer pourquoi une machine neutre attrape ce qu'une machine de développement laisse passer.
  • Lire la description d'une chaîne : déclencheur, travaux, étapes, dépendances.
  • Calculer la durée d'une chaîne et identifier son chemin critique.
  • Employer cache et artefacts à bon escient.
  • Manipuler des secrets sans les exposer.
  • Distinguer intégration, livraison et déploiement continus.
  • Réagir correctement à une chaîne en échec.
Où on va
Tout ce que les chapitres précédents ont mis en place, les tests, le linteur, la construction de l'image, ne vaut que si cela s'exécute vraiment, à chaque fois, chez tout le monde. Une vérification qu'on lance quand on y pense finit par ne plus être lancée. L'intégration continue confie ces vérifications à une machine neutre qui les exécute à chaque poussée, et refuse la fusion tant qu'elles échouent. Le principe est traité dans le bloc génie logiciel ; ici on écrit la chaîne, et on regarde ce qui décide de sa durée.

Une machine neutre

Définition

Une chaîne d'intégration est une suite de vérifications exécutées automatiquement sur un serveur, à partir d'une copie neuve du dépôt, à chaque événement choisi : poussée, demande de fusion, étiquette.

Le mot important est neuve. La machine ne contient rien de ce qui traîne sur votre poste : ni la bibliothèque installée à la main un soir de novembre, ni la variable d'environnement définie dans votre .bashrc, ni le fichier de données que vous seul possédez.

C'est ce qui fait de la chaîne un juge utile. Elle répond à la seule question qui compte pour l'équipe : ce dépôt, tel qu'il est, suffit-il à installer, construire et vérifier le projet ? Un projet qui ne passe pas ce test ne se transmet pas, quelle que soit la qualité du code.

L'anatomie d'une chaîne

Le vocabulaire varie d'un outil à l'autre, la structure non.

NotionCe que c'est
Déclencheurl'événement qui lance la chaîne
Travailun ensemble d'étapes exécuté sur une machine
Étapeune commande, ou une action réutilisable
Dépendanceun travail qui attend la fin d'un autre
Artefactun fichier produit, conservé et transmis
Cacheun dossier restauré d'une exécution à l'autre
Matricele même travail répété sur plusieurs versions ou systèmes
# .github/workflows/verification.yml
name: Vérification

on:
  push:
    branches: [main]
  pull_request:

jobs:
  qualite:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
          cache: pip
      - run: pip install -r requirements.txt
      - run: ruff check .
      - run: mypy src/
      - run: pytest --cov=src

Trois choses à remarquer. Le déclencheur couvre la demande de fusion, pas seulement la poussée sur la branche principale : c'est là que la vérification sert, avant l'intégration. La version de Python est figée, sinon la chaîne changerait de comportement sans que personne n'ait rien modifié. Et le cache des dépendances est déclaré, faute de quoi chaque exécution réinstallerait tout.

Ce qui décide de la durée

Une chaîne est un graphe de travaux, certains parallèles, d'autres en attente. Sa durée n'est pas la somme des durées : c'est la longueur du plus long chemin de dépendances.

main.py
Sortie
>_ Prêt à exécuter…

Le chemin critique dit où investir. Accélérer la vérification des types ne changera rien à la durée totale, puisqu'elle attend de toute façon les tests d'intégration. Découper les tests unitaires en deux moitiés parallèles, en revanche, raccourcit toute la chaîne.

Dix minutes
Au-delà d'une dizaine de minutes, une chaîne cesse d'être un retour d'information et devient une attente : on part faire autre chose, on perd le contexte, et on prend l'habitude de fusionner avant la fin.
Les leviers, dans l'ordre : mettre en cache les dépendances, paralléliser les tests, ne construire l'image que lorsque c'est utile, et repousser les tests les plus longs à une exécution nocturne.

Cache et artefacts

Deux mécanismes voisins, deux usages distincts.

Le cache accélère. Il restaure un dossier d'une exécution à l'autre, typiquement les dépendances téléchargées. Sa disparition ne casse rien : la chaîne est simplement plus lente. La clé du cache doit dépendre du fichier de verrouillage, sinon on restaure des dépendances qui ne correspondent plus.

L'artefact transmet. Il conserve un fichier produit par un travail pour le donner à un autre, ou à un humain : image construite, rapport de couverture, binaire, journal d'échec. Un artefact bien choisi évite de reproduire localement une panne survenue sur le serveur.

Les secrets

Une chaîne a besoin de jetons : registre d'images, serveur de déploiement, service tiers. Ils se rangent dans le magasin de secrets de la plateforme, jamais dans le dépôt, et sont exposés au travail sous forme de variables d'environnement.

Trois façons de faire fuir un secret
L'afficher dans les journaux, par un echo de diagnostic ou une commande lancée en mode verbeux. Les plateformes masquent les valeurs connues, mais pas leur version encodée ni les fragments.
Le faire passer dans une image, où la couche le conserve définitivement.
L'exposer à une chaîne déclenchée par une contribution extérieure : le code proposé s'exécuterait avec vos jetons. Les chaînes déclenchées par un dépôt tiers ne doivent pas y avoir accès.

Intégration, livraison, déploiement

Trois termes voisins, souvent confondus, et la différence porte sur ce qui est automatique.

L'intégration continue vérifie chaque modification, automatiquement.

La livraison continue ajoute la production d'un artefact prêt à installer, à chaque modification retenue. La mise en production reste une décision humaine.

Le déploiement continu enchaîne aussi cette dernière étape : ce qui passe les vérifications part en production sans intervention.

Le déploiement continu ne se décrète pas. Il suppose une couverture de tests sérieuse, des déploiements réversibles, et une surveillance capable de détecter une anomalie plus vite qu'un utilisateur. Sans ces trois conditions, il automatise surtout la propagation des défauts.

La règle sociale

Une chaîne rouge sur la branche principale bloque tout le monde : plus personne ne sait si son propre échec vient de son travail ou de celui d'avant. C'est donc la priorité de l'équipe, avant toute nouvelle fonctionnalité.

Deux réactions à proscrire. Relancer la chaîne en espérant qu'elle passe, ce qui ne se justifie que si l'on sait déjà que l'échec est instable, et qui dans ce cas signale un test à réparer. Et désactiver le test qui échoue pour débloquer la fusion, ce qui revient à supprimer le détecteur de fumée parce qu'il sonne.

Exercices type

Pourquoi exécuter les tests sur un serveur alors qu'ils passent déjà sur le poste du développeur ?

Parce que le poste contient des choses que le dépôt ne contient pas : bibliothèque installée à la main, variable d'environnement locale, fichier de données absent ailleurs, version d'outil différente.

Le serveur part d'une copie neuve. Il vérifie donc, en plus du code, que le dépôt suffit à installer et à vérifier le projet.

Il garantit aussi que les tests sont réellement exécutés, y compris par ceux qui les oublient, et sur la version fusionnée plutôt que sur la version locale.

Une chaîne dure 12 minutes. Quel travail faut-il accélérer ?

Celui qui se trouve sur le chemin critique, c'est-à-dire la plus longue suite de travaux liés par des dépendances.

Accélérer un travail hors de ce chemin ne change rien à la durée totale : il attend de toute façon.

En pratique, on commence par regarder ce que les travaux attendent réellement, puis on met en cache les dépendances, on parallélise le travail le plus long, et on repousse à une exécution nocturne ce qui n'a pas besoin d'être vérifié à chaque poussée.

Quelle différence entre un cache et un artefact ?

Le cache accélère : il restaure un dossier d'une exécution à l'autre, en général des dépendances téléchargées. S'il est vide, la chaîne fonctionne quand même, plus lentement. Il ne doit jamais contenir un résultat dont la justesse compte.

L'artefact transmet : il conserve un fichier produit, pour un autre travail ou pour un humain. Image construite, rapport, journal d'échec.

Confondre les deux mène à l'erreur classique : mettre en cache un produit de construction, et publier une version obsolète parce que la clé du cache n'a pas changé.

Pourquoi ne pas donner accès aux secrets à une chaîne déclenchée par une contribution extérieure ?

Parce que la chaîne exécute le code proposé. Une contribution malveillante peut ajouter une étape qui lit les variables d'environnement et les envoie ailleurs.

Le secret serait alors utilisé avec vos droits : publication d'image, déploiement, accès à un service payant.

La pratique courante est de séparer les déclencheurs : vérification sans secrets pour les contributions extérieures, et étapes sensibles réservées aux exécutions déclenchées depuis le dépôt lui-même, après relecture humaine.

Quelle différence entre livraison continue et déploiement continu ?

La livraison continue produit automatiquement un artefact prêt à installer pour chaque modification retenue. La mise en production reste déclenchée par un humain.

Le déploiement continu automatise aussi cette dernière étape.

Le second suppose trois conditions : des tests dans lesquels on a réellement confiance, un retour arrière rapide et éprouvé, et une surveillance qui détecte une anomalie avant les utilisateurs. Sans elles, il automatise la propagation des défauts.

La chaîne est rouge sur la branche principale. Que fait l'équipe ?

Elle traite l'échec en priorité, avant toute nouvelle fonctionnalité. Une chaîne rouge rend tous les résultats suivants ininterprétables : personne ne sait plus si son propre échec vient de lui.

Si la correction demande du temps, on revient à l'état précédent avec un revert, ce qui remet la branche au vert, et on reprend la correction tranquillement sur une branche.

Ce qu'on ne fait pas : relancer en espérant, ou désactiver le test qui échoue pour débloquer la fusion.

La méthode

  1. Déclenche la chaîne sur les demandes de fusion, pas seulement sur la branche principale.
  2. Fige les versions d'outils et de systèmes utilisés par la chaîne.
  3. Mets en cache les dépendances, avec une clé liée au fichier de verrouillage.
  4. Vise dix minutes, et travaille sur le chemin critique pour y arriver.
  5. Publie un artefact pour tout échec difficile à reproduire localement.
  6. Range les secrets dans le magasin de la plateforme, jamais dans le dépôt.
  7. Répare une chaîne rouge avant tout le reste.

En résumé

  • La chaîne part d'une copie neuve : elle vérifie que le dépôt suffit.
  • Une chaîne est un graphe de travaux ; sa durée est celle de son chemin critique.
  • Le cache accélère et peut disparaître ; l'artefact transmet un résultat.
  • Une clé de cache se lie au fichier de verrouillage.
  • Les secrets ne sont jamais dans le dépôt, et jamais exposés à une contribution extérieure.
  • Intégration, livraison et déploiement continus se distinguent par ce qui reste manuel.
  • Le déploiement continu suppose tests fiables, retour arrière rapide et surveillance.
  • Une chaîne rouge est la priorité de l'équipe ; on ne désactive pas le test qui échoue.

Et ensuite ? Vous disposez maintenant d'un atelier complet : un terminal, un éditeur, un historique, un environnement reproductible, des vérifications automatiques. Le reste s'apprend en construisant quelque chose, et les autres parcours du site sont faits pour cela.

L'intégration continue | Plateforme ETS