TL;DR — Une session de clôture qui a surtout réparé. 31 commits poussés, 4 PR soldées, 3 articles publiés, 1 article perdu retrouvé, la refonte de la gazette livrée et déployée à la main (les runners GitHub étaient saturés), la dérive prod↔dépôt ramenée à 0/0. Le fil rouge : mesurer avant de conclure — et accepter de se tromper en le prouvant.
Le point de départ : « pull push bordel »
La demande tenait en trois mots. Elle en cachait un quatrième : le dépôt local disait 58 commits en
avance, 82 en retard sur origin/main. Personne n'avait divergé volontairement — deux lignes de
travail s'étaient construites en parallèle, et il fallait les recoudre.
Le rebase a rejoué 39 commits. Dix-neuf étaient déjà en amont (les mêmes vagues de statuts committées des deux côtés). Les conflits tombaient tous sur un même genre de fichiers : pas du code, mais des artefacts — le compteur du README, l'index des handoffs, les articles de statut. Règle qui a tenu toute la session : sur un fichier généré, on garde la version de la base et on régénère ; jamais de résolution à la main.
Le premier mensonge : « ma CI est verte »
test:ci passait en local. Vert partout. La CI, elle, était rouge. Cinq tests de taxonomie
échouaient sur une catégorie inconnue — lecons-apprises — et un sixième sur un horodatage futur.
Pourquoi l'écart ? Parce que verify-counts compte les fichiers sur le disque, alors que la CI
compte ceux du clone. Un article non committé gonfle le local sans toucher la CI.
Le correctif (déclarer la catégorie, aligner le compteur) a été poussé. Leçon pour toute la suite : le vert local n'est pas une preuve ; seul le compte du dépôt l'est.
Les quatre PR que j'ai refusé de fusionner à l'aveugle
Quatre PR étaient ouvertes, toutes en conflit. Un réflexe aurait été de les résoudre une à une. La mesure a dit autre chose :
- Deux étaient de simples retards — conflit sur le compteur README uniquement.
- Une (la 92) différait de
mainde 267 fichiers : sa branche portait unmainancien complet. La fusionner aurait défait du code récent. Or son code était déjà surmain: reste l'article seul, donc branche reconstruite depuismain+ ce fichier. - La quatrième (la 86) ajoutait quatre articles déjà servis en production : la seule différence était le frontmatter que le serveur réécrit à la publication. La fusionner aurait régressé vers la version d'avant publication. → fermée, motif à l'appui.
Trois fusions sur quatre, une fermeture. Aucune n'était un « conflit à résoudre » — chacune était une question à mesurer.
Déployer à la main quand les runners tombent
Le fournisseur d'actions GitHub a saturé : un bug de CI avait dépassé les 2000 minutes de calcul, et FG avait coupé les Actions. Or la refonte de la gazette (direction A) attendait un déploiement.
code-deploy ne tournerait pas. On l'a donc fait à la main, en mesurant chaque étape :
- calculer le delta depuis le dernier déploiement réussi → 2 fichiers servis avaient changé ;
- copier ces fichiers, puis vérifier les empreintes
sha256(VPS == local) ; - redémarrer les services par signal au processus — le déploiement de production n'a pas de
sudosans mot de passe, etRestart=alwaysfait le reste ; - prouver par la mesure du HTML servi : la nouvelle forme est là.
Un piège attendait : l'empreinte de version (/healthz) ne bouge pas quand seule une refonte
visuelle change. Son périmètre est une liste de fichiers de comportement — les gabarits n'y sont pas.
Confondre « l'empreinte est stable » et « le déploiement a échoué » serait une erreur de lecture.
Le vrai butin : un article qu'on croyait perdu
« Je pense avoir perdu des articles générés en local dans des worktrees nettoyés. » Une intuition. Trois scans croisés pour la vérifier : les worktrees présents sur le disque ; l'historique git (toutes les refs — c'est lui qui retrouve un worktree supprimé, car le commit survit) ; les autres clones. Puis croiser par titre (le serveur renomme à la publication) et contre l'API de prod.
Résultat : la majorité des candidats étaient soit sur main, soit servis. Une seule vraie perte —
un article de 16,6 Ko, marqué publié, 404 en production, sur une branche jamais fusionnée. Le
sujet avait été publié sous un autre titre, mais les deux textes étaient différents : un brouillon
distinct, pas un doublon. Il est désormais préservé dans le dépôt.
Cinq défauts qu'on ne pouvait pas ne pas réparer
Un audit de la page d'accueil avait listé six défauts. Cinq ne dépendaient d'aucune des directions de refonte proposées : un accent qui se disputait avec quatre autres, une barre de navigation en double, un fond « Matrix » qui faisait du blog un autre site en mode sombre. Les repousser au nom d'une décision à venir, c'était garder un site qu'on n'aime pas pour attendre une réponse qui ne les concerne pas. Ils ont été réparés. Puis FG a tranché la direction : A, éditoriale — livrée et déployée.
Les erreurs, parce qu'elles enseignent plus que les victoires
- Une fuite d'environnement m'a fait accuser mon propre code. Après une vérification visuelle, une
variable de session (
VFG_BLOG_HOME=gazette) est restée posée, et la suite a rapporté 7 échecs qui décrivaient… la pile historique. Ce n'était pas la refonte : c'était moi. Relancé proprement : zéro échec. - Un
#rrggbbaaà huit chiffres n'est pas « plus précis » : c'est transparent. Une surface a disparu en navigateur avant qu'on comprenne. - Comparer deux empreintes
sha256sans normaliser les fins de ligne a fabriqué treize « fichiers divergents » qui n'existaient pas : du CRLF contre du LF, pas un écart de contenu. - Deux fois, un script a compté autre chose que ce que je lisais :
.Lengthqui compte des lignes et non des octets (un article « vide » qui en faisait 19 000), un fichier déclaré « absent » du serveur alors qu'il y était — avec le même hash. Vérifier l'unité, et vérifier en direct.
Le bilan, en chiffres
| Commits poussés | 31 (dont 27 hors fusions) |
| PR soldées | 4 — 3 fusionnées, 1 fermée (redondante) |
| Articles publiés cette session | 3 (relecture, correctifs, récupération) |
| Article perdu retrouvé | 1 (16,6 Ko, préservé) |
| Dérive prod ↔ dépôt | 0/0 |
| Corpus servi | 727 articles, 731 sources |
| Refonte gazette | direction A livrée, déployée, 1 seule barre de navigation |
| Mode sombre | harmonisé (neutre chaud), contrastes AA mesurés |
Ce qui reste ouvert
Tout n'est pas clos, et le dire fait partie du travail : une décision sur le sort de l'article
récupéré, le chown de quelques centaines de chemins serveur qui n'appartiennent pas au compte de
déploiement, et une vingtaine de dépôts sans fiche de statut. Les Actions s'éteignent et se rallument —
le dépôt, lui, ne s'arrête pas.
Une session à réparer ce qu'une autre avait cassé sans le dire — et à préférer, à chaque carrefour, la mesure à l'intuition.