Malik Benali déployait l'outil de réservation d'une salle associative à Brest en recopiant un dossier par SSH, ce qui a marché pendant huit mois. Un vendredi soir il a recopié une version qui ne savait plus lire le fichier des créneaux de la semaine, et il a découvert que la version précédente n'existait plus nulle part. Il l'avait écrasée. Le samedi et le dimanche, deux bénévoles ont répondu au téléphone avec un cahier.
Rien dans cette histoire ne concerne l'écriture du code, et tout y est ce sujet. La mise en production est l'ensemble des pratiques qui rendent un changement réversible, reproductible et inspectable par quelqu'un qui n'est pas vous. C'est ce que le développement web suppose réglé dès qu'il prononce le mot serveur, et que personne ne présente comme un sujet.
Réversible d'abord
La propriété qui aurait sauvé le week-end de Malik n'est ni les tests ni les conteneurs. C'est qu'un retour arrière est un déploiement de la version précédente, et qu'il doit être aussi facile qu'un déploiement ordinaire. Si revenir en arrière est une procédure différente d'avancer, elle sera improvisée au pire moment par la personne la plus effrayée disponible. Un déploiement fait correctement est un basculement entre deux versions qui existent toutes les deux, et l'ancienne est gardée précisément pour que la réponse à un mauvais vendredi soit une commande et non une soirée.
La même idée, un étage plus bas, explique pourquoi l'on garde une histoire. Deux commandes défont des choses et elles ne sont pas interchangeables : git revert crée un nouveau commit, git reset déplace la branche. Revert est celle qui est sûre sur tout ce que d'autres ont déjà, parce qu'elle ajoute un changement qui en annule un autre et laisse la trace des deux. Reset réécrit ce que la branche désigne, ce qui est le bon outil sur un travail que personne n'a vu et une façon de détruire l'après-midi d'un collègue sur un travail qu'il a. C'est la moitié pratique du contrôle de version.
La sauvegarde qui a brûlé avec la production
En France, la démonstration de ce que vaut une copie ne s'est pas faite en séminaire. Dans la nuit du 10 mars 2021, un incendie a détruit le centre de données SBG2 d'OVHcloud à Strasbourg : environ 30 000 serveurs perdus, quelque 3,6 millions de sites arrêtés, et des milliers d'entreprises découvrant que leur sauvegarde avait brûlé en même temps que leur production, parce qu'elle se trouvait dans le même bâtiment. Le tribunal de commerce de Lille Métropole a condamné l'hébergeur à verser 100 000 euros à l'un de ces clients.
Ce que cela enseigne tient en une phrase et il est moins cher de l'apprendre ici : une copie dans le même bâtiment n'est pas une sauvegarde. La règle qui tient est de savoir, pour chaque projet, où est la copie, à quelle distance, et à quand remonte la dernière fois où quelqu'un l'a restaurée pour de bon. Une sauvegarde jamais restaurée est une hypothèse, et c'est le seul point de cette page qui se vérifie en une heure et se paie en semaines.
La machine qui n'a rien
Le déploiement de Malik marchait parce que son portable avait accumulé huit mois de petits ajustements : une bibliothèque installée une fois, une variable d'environnement posée dans un profil de shell, un dossier qui se trouvait exister. Rien n'était écrit nulle part, et rien n'était sur le serveur de la salle avant qu'il l'y mette à la main.
La chaîne d'intégration tourne sur une machine qui n'a rien, et c'est ce qui la rend honnête. Un serveur de construction repart d'une boîte vide à chaque fois, donc tout ce dont le projet a besoin doit être déclaré quelque part qu'un fichier peut enregistrer. C'est la vraie valeur de la CI et la CD, et elle vaut mieux que l'automatisation : c'est un audit continu et sans indulgence de la question de savoir si le projet peut être construit par quelqu'un qui n'en est pas l'auteur.
Le même réflexe, poussé d'un cran, produit le conteneur. Une image de conteneur, ce sont les dépendances, le moteur d'exécution et le code dans un seul fichier, construit une fois et exécuté à l'identique partout où il atterrit. Elle supprime toute la classe de pannes où le serveur et le portable ne s'accordent pas sur une version, ce à quoi servent les conteneurs. Ce qu'elle ne supprime pas, c'est l'obligation de savoir ce qui est entré dedans : une image construite sur une base non épinglée est la même dépendance non déclarée qu'avant, scellée dans une boîte et livrée avec plus d'assurance.
git revert <commit>ajoute un commit qui annule, et se pousse sans dangergit reset --hard <commit>déplace la branche et jette ce qui suivaitdocker build -t reservation:2026-09-08 .nomme l'image par sa date, donc la précédente existe encoreFROM python:3.12.7-slimplutôt queFROM python:3, sinon la base change sans prévenir
Quatre couches
Ce que chaque couche arrête, et ce qu'elle laisse passer tout droit
Quatre couches entre un changement et deux bénévoles qui prennent les réservations sur un cahier, et chacune est transparente à la faute que la suivante attrape.
- La suite de tests+Un comportement qui marchait et ne marche plus→Tout ce que personne n'a pensé à décrire, et chaque différence d'environnement
- La construction à partir de rien+La bibliothèque non déclarée et la variable posée dans un profil de shell→Du code faux d'une façon qui se construit parfaitement
- Le conteneur+Le serveur et le portable en désaccord sur une version→Un mauvais changement, fidèlement et identiquement, partout
- La version précédente, gardée+Tout ce que les trois autres laissent passer, le temps que quelqu'un s'en aperçoive→Rien, et c'est la couche qu'on supprime pour gagner du disque
Elle ne dit pas où la copie est rangée, et c'est la question que l'incendie de Strasbourg a posée à tout le pays : une quatrième couche dans le même bâtiment que la production n'est pas une couche.
La preuve, et ce à quoi elle sert vraiment
L'argument pour les tests qui convainc n'est pas qu'ils attrapent des bogues, parce qu'un débutant observe raisonnablement qu'ils attrapent surtout ceux auxquels l'auteur pensait déjà. L'argument qui tient est qu'ils rendent un changement sûr à faire. Malik peut réécrire l'analyseur de créneaux un mardi avec une confiance proportionnelle à la part de son comportement qui est écrite quelque part sous une forme qu'une machine vérifie.
C'est pourquoi les tests se formulent autour de la survie plutôt que de la justesse. Une suite de tests est une description de ce que le programme est censé faire, tenue sous une forme qui proteste quand la description cesse d'être vraie, et sa valeur arrive des mois après son écriture, le jour où quelqu'un modifie un fichier qu'il ne comprend pas entièrement.
Le premier test utile n'est pas un test unitaire. C'est celui qui fait tourner l'ensemble sur le fichier de créneaux de la semaine dernière et vérifie le total, parce que c'est exactement la panne que Malik a eue, et parce qu'un test écrit contre une vraie entrée passée ne demande aucune théorie sur ce qu'est une unité. La structure élaborée peut venir plus tard, et pour la plupart des petits projets elle ne vient jamais.
L'ordre, et où l'on cale
L'ordre qui marche est le contrôle de version, puis une façon de faire tourner la chose à partir de rien, puis les tests, puis l'automatisation de la livraison. Presque tout le monde fait le quatrième en premier, parce que c'est celui dont l'outillage est intéressant, et se retrouve avec une chaîne qui automatise un déploiement que personne ne sait annuler.
Le blocage arrive juste après le premier programme qui marche. La syntaxe avait un sens, le terminal n'en a pas, git est quatre concepts qui se font passer pour un, la cible de déploiement a son propre vocabulaire, et quelqu'un en conclut qu'il est mauvais en programmation. Il ne l'est pas. Il vient d'entrer dans un second métier sans annonce, et la preuve en est qu'aucune de ces difficultés ne porte sur le langage qu'il vient d'apprendre, ni sur rien de ce que les bases de la programmation lui ont donné.
Ce qu'on ouvre en 2026
Git n'est pas optionnel et ne l'est plus depuis qu'il a pris la place de Subversion au cours des années 2010. Il est gratuit, et l'heure la plus rentable de ce sujet est celle passée à comprendre qu'un commit est un instantané et qu'une branche est un pointeur vers un instantané, après quoi la plus grande part de la confusion se dissout d'elle-même.
GitHub Actions est la chaîne par défaut pour les projets déjà sur GitHub, elle est gratuite pour les dépôts publics, et elle a remplacé Jenkins pour la plupart des petites équipes, ce que supposent encore les tutoriels antérieurs à 2019 environ. Docker reste la façon de construire des conteneurs et il est gratuit pour un usage individuel.
Pour la dernière marche, le déploiement, les plateformes qui déploient un dépôt à chaque poussée ont remplacé la recopie de dossier que faisait Malik, et elles l'ont remplacée précisément en gardant la version précédente. Depuis la France, Clever Cloud et Scaleway le font en facturant en euros, ce qui compte pour une association qui doit présenter une facture à son trésorier, et OVHcloud reste le premier hébergeur du pays, incendie compris et leçon comprise. Un assistant dans l'éditeur écrit un fichier de chaîne passable tout de suite et se trompe avec aplomb sur les identifiants et les droits, c'est-à-dire à l'endroit où se tromper coûte cher plutôt qu'agace.
Reste ce qui se passe après le déploiement : la chose tourne, et il faut que quelqu'un remarque qu'elle s'est arrêtée. Ni le dépôt ni la chaîne ne répondent à cela, et la réponse commence par ce que le programme écrit dans ses journaux quand il va mal, ce qui se décide au moment où on l'écrit et non au moment où il tombe. Pour l'outil de Malik, la première alerte utile est la plus bête, une requête toutes les cinq minutes sur la page de réservation et un message si elle ne répond pas. Ce que la salle garde ensuite, et pendant combien de temps, est une question pour les bases de données.