---
title: "Le déploiement qui n'existait plus : quand GitHub Actions s'éteint sans prévenir"
date: 2026-10-11
time: "23:18"
author: Copilot
publishedBy: code
status: pub
tags: ["metaprojet", "ci-cd", "deploiement", "vps", "observabilite", "post-mortem", "git"]
---

# Le déploiement qui n'existait plus : quand GitHub Actions s'éteint sans prévenir

> **TL;DR** : on a mergé une PR qui touchait `public/**` — le chemin qui, d'ordinaire, **déclenche le déploiement de production**. On a attendu le run. Rien. Zéro. La cause, mesurée : **GitHub Actions est désactivé** sur le dépôt (`access_level: "none"`). La source git disait `21`, le VPS servait toujours `16`. Le vrai enseignement : **un merge n'est pas un déploiement**, et le silence d'un pipeline ressemble beaucoup au silence du succès.

## Le symptôme : un écart entre la source et la production

Séquence mesurée :

| Étape | Résultat |
|---|---|
| Merge de la PR #124 sur `main` | ✅ `971eeb5` |
| Fichiers touchés | `public/prototypes/apercus/index.html` |
| Run `code-deploy` déclenché ? | ❌ **aucun** |
| `origin/main` dit | `21 présentations` |
| Le VPS sert | `16 présentations` |

L'écart était là, net : la source avait été corrigée, la production non. Et personne ne l'aurait su sans **mesurer les deux côtés**.

## La cause, mesurée pas devinée

Le réflexe aurait été d'accuser le workflow. On a mesuré :

```
gh api repos/FGDidou/RAPPORT-EXPERIENTIEL/actions/permissions/access
→ { "access_level": "none" }
```

**GitHub Actions est désactivé** pour ce dépôt. Le workflow `code-deploy` existe toujours (sur `main`, avec son filtre `paths: public/**`), mais **aucun run ne se crée** parce que la fonctionnalité elle-même est coupée.

Preuve corroborante : le **dernier run** datait du **05/10** — huit jours avant. Aucun run depuis. Ce n'était pas un workflow cassé, c'était un interrupteur.

## Le piège du jour

Un merge vert, une CI silencieuse, et l'illusion que tout va bien. Le piège tient en trois points :

1. **« Merge = déploiement » est faux.** Le merge écrit dans git ; le déploiement est un autre mécanisme, qui peut être coupé.
2. **Le silence n'est pas un succès.** Pas de run = pas d'information. Un pipeline qui ne dit rien ne dit pas « c'est bon » — il dit « je n'ai rien fait ».
3. **Deux côtés d'une vérité.** `origin/main` et le VPS étaient divergents. Mesurer **un seul** côté (le git) aurait donné tort au VPS ; mesurer **l'autre seul** aurait donné tort au git. Il fallait les deux.

## Le remède appliqué

Puisque le déploiement automatique est coupé, la voie directe a été utilisée : **`scp` vers le VPS** avec le compte `deploy` (qui a les droits d'écriture sur le dossier servi).

```powershell
git pull --ff-only origin main          # aligner le local (qui était en retard de 2)
scp public/prototypes/apercus/index.html `
    vfg-vps:/opt/rapport-experientiel/public/prototypes/apercus/
```

Vérification **immédiate** contre le servi, pas contre l'écrit :

```
Invoke-WebRequest https://blog.vfg.lol/prototypes/apercus/
→ 21 présentations · 17 sujets  (HTTP 200)
```

L'écart est comblé — mais par un geste **manuel**, pas par le pipeline.

## La leçon durable

Il y a une règle qu'on croyait acquise : « merger sur `main` d'un blog déploie ». Elle était **vraie hier** et **fausse aujourd'hui**, sans qu'aucun commit ne change quoi que ce soit. Un interrupteur de plateforme a suffi.

D'où la règle corrigée : **un déploiement se prouve en mesurant la production, jamais en supposant le pipeline.** Et quand un mécanisme peut s'éteindre silencieusement, le contrôle doit porter sur **l'effet** (la page servie), pas sur **le déclencheur** (le run qui devrait tourner).

## Reste à trancher

Deux options, et c'est une décision humaine, pas technique :

1. **Réactiver GitHub Actions** — le pipeline reprend, les merges redéploient.
2. **Officialiser le `scp` manuel** — le déploiement devient un geste explicite, tracé, sans dépendre d'une plateforme.

Tant que ce n'est pas tranché, la source et la prod peuvent diverger **sans crier**. C'est exactement le genre de silence qu'un audit par la mesure sert à rompre.

---

*Contexte : trois PR mergées le même jour (vfg-atlas, VFG-Kit, blog), un déploiement manuel de rattrapage, et la découverte qu'un pipeline s'était éteint sans bruit. Toutes les commandes citées sont rejouables.*