Un rollback ne s'improvise pas le jour de l'incident : il se prépare au
moment où tout va bien. Cette page montre comment revenir à la version
précédente sans rejouer le pipeline, pourquoi cancel-in-progress est
dangereux sur un job de déploiement, et ce que l'historique GitHub permet de
retrouver quand il faut décider vite.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Distinguer un rollback d'un correctif d'urgence, et savoir lequel appliquer
- Rejouer le digest précédent sans reconstruire ni retester
- Retrouver la version précédente dans l'historique des déploiements
- Sérialiser les déploiements avec
concurrency, sans annuler celui qui tourne - Préparer ce qui doit exister avant l'incident pour que tout cela marche
Rollback ou correctif : deux réponses différentes
Section intitulée « Rollback ou correctif : deux réponses différentes »Face à une régression en production, deux chemins existent, et les confondre coûte du temps au pire moment.
| Rollback | Correctif d'urgence | |
|---|---|---|
| Principe | Redéployer la version précédente, connue bonne | Corriger, tester, déployer une nouvelle version |
| Durée | Minutes | Le temps d'un cycle complet |
| Risque | Faible, l'artefact a déjà tourné | Celui d'un déploiement normal, sous pression |
| Quand | Régression fonctionnelle, panne | Faille de sécurité, corruption de données |
La règle par défaut est rollback d'abord, diagnostic ensuite. Le correctif direct se justifie quand revenir en arrière n'est pas sûr, typiquement après une migration de schéma irréversible, ou quand la version précédente porte la vulnérabilité qu'on vient de corriger.
La condition préalable : un artefact toujours disponible
Section intitulée « La condition préalable : un artefact toujours disponible »Un rollback n'est possible que si la version précédente existe encore, et qu'on sait la nommer. C'est la contrepartie de la chaîne de promotion : on ne redéploie pas un commit, on redéploie un digest.
Déploiement N-1 -> ghcr.io/mon-org/mon-app@sha256:3f1c... (toujours dans le registre)Déploiement N -> ghcr.io/mon-org/mon-app@sha256:9a47... (la régression)Rollback -> redéployer sha256:3f1c..., sans rebuildTrois conditions rendent cela vrai, et chacune se vérifie avant l'incident :
- l'image précédente n'a pas été supprimée du registre par une politique de nettoyage trop agressive ;
- le digest est retrouvable, par l'historique des déploiements ou par les tags du registre ;
- le workflow de déploiement accepte un digest en entrée, et ne se contente
pas de déployer
main.
Retrouver le digest précédent
Section intitulée « Retrouver le digest précédent »L'historique des déploiements de GitHub garde la trace de chaque déploiement par
environnement. En ligne de commande, la CLI gh l'interroge directement :
# Les derniers déploiements de l'environnement productiongh api "repos/mon-org/mon-app/deployments?environment=production&per_page=10" \ --jq '.[] | {id, sha, created_at, ref}'Pour retrouver les images disponibles côté registre, avec leurs digests :
# Les versions publiées du paquet de conteneurgh api "orgs/mon-org/packages/container/mon-app/versions" \ --jq '.[] | {id, digest: .name, tags: .metadata.container.tags, created_at}'Ces deux commandes sont à connaître avant d'en avoir besoin. Les taper pour la première fois pendant une panne, c'est ajouter un problème à un problème.
Le workflow de rollback
Section intitulée « Le workflow de rollback »Il n'y a pas de workflow de rollback spécifique : c'est le déploiement paramétré par digest, appelé avec la valeur précédente. Le même chemin, les mêmes contrôles, les mêmes approbations.
name: Deploy
on: workflow_dispatch: inputs: digest: description: "Digest à déployer (sha256:...), y compris pour un rollback" required: true type: string
permissions: {}
concurrency: group: deploy-production cancel-in-progress: false # on ne coupe jamais un déploiement en cours
jobs: deploy: runs-on: ubuntu-24.04 timeout-minutes: 15 environment: name: production url: https://mon-app.example.com permissions: contents: read env: IMAGE: ghcr.io/mon-org/mon-app DIGEST: ${{ inputs.digest }} steps: - name: Vérifier la provenance du digest demandé env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: gh attestation verify "oci://${IMAGE}@${DIGEST}" --owner mon-org - name: Déployer run: ./deploy.sh "${IMAGE}@${DIGEST}" env: DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}Maintenir la vérification de provenance dans le chemin de rollback est délibéré. C'est précisément sous pression qu'on accepterait de déployer n'importe quoi « juste pour que ça remarche », et c'est précisément le moment où un attaquant a intérêt à ce que vous le fassiez.
Concurrence : sérialiser sans annuler
Section intitulée « Concurrence : sérialiser sans annuler »Le bloc concurrency regroupe les exécutions et décide du sort de celles qui se
chevauchent. Sur une CI, on annule volontiers l'exécution précédente : elle
porte sur un commit dépassé. Sur un déploiement, l'annulation est
dangereuse.
# ✅ Déploiement : on met en file d'attente, on n'annule pasconcurrency: group: deploy-production cancel-in-progress: false# ❌ Sur un déploiement : coupe une mise en production au milieuconcurrency: group: deploy-production cancel-in-progress: trueUn déploiement interrompu en plein vol laisse le système dans un état intermédiaire : moitié des instances sur la nouvelle version, migration appliquée mais code non déployé, verrou non relâché. C'est exactement la situation que le rollback devra démêler, en partant d'un état qu'aucune version n'a jamais connu.
Le nom du groupe mérite attention. Un groupe par environnement
(deploy-production) sérialise les mises en production tout en laissant staging
avancer en parallèle :
concurrency: group: deploy-${{ github.event.inputs.environment || 'production' }} cancel-in-progress: falseSur la CI, en revanche, l'annulation reste la bonne réponse :
# CI : annuler les exécutions obsolètes de la même brancheconcurrency: group: ci-${{ github.ref }} cancel-in-progress: trueCe qu'il faut avoir préparé
Section intitulée « Ce qu'il faut avoir préparé »-
Un déploiement paramétrable par digest, pas seulement déclenché par un push sur
main. -
Une politique de rétention qui conserve au moins les quelques dernières versions déployées, images non taguées comprises.
-
Les commandes de recherche du digest précédent, écrites quelque part d'accessible hors de l'outil en panne.
-
Un groupe de concurrence par environnement, avec
cancel-in-progress: false. -
Une décision écrite sur les cas où le rollback est interdit, typiquement après une migration de schéma irréversible.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »- Rollback d'abord, diagnostic ensuite, sauf migration irréversible ou faille corrigée par la version en cours.
- Un rollback redéploie un digest, pas un commit : il n'y a ni rebuild, ni nouveaux tests, donc ni nouveau risque.
- La rétention du registre et des artefacts fixe la profondeur réelle du rollback ; 90 jours par défaut côté artefacts.
- Le workflow de rollback est le déploiement paramétré, avec les mêmes vérifications de provenance et la même approbation.
- Sur un déploiement,
cancel-in-progress: false: une mise en production coupée en deux laisse un état qu'aucune version n'a connu. - Un groupe de concurrence par environnement sérialise la production sans bloquer staging.
- Les commandes qui retrouvent le digest précédent se testent avant l'incident, pas pendant.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Concurrency : Le mécanisme de groupement détaillé, dont le
cancel-in-progressqu'un déploiement doit laisser àfalse. - Runners : introduction : Choisir et durcir les machines qui exécutent ces déploiements.