Une approbation manuelle dans AWS CodePipeline met une mise en production en pause jusqu’à ce qu’une personne clique sur Approuver. Cet article s’adresse aux équipes qui veulent ce contrôle avant la production sans qu’il bloque chaque déploiement. Le problème commence quand le seul approbateur est en réunion ou en vacances. Les mises en production s’accumulent, la notification ne donne aucun contexte, et après sept jours le pipeline échoue sans bruit. Tôt ou tard, quelqu’un propose de supprimer l’étape d’approbation.
La meilleure correction garde l’approbation et la rend rapide à traiter. Faites du staging un pipeline distinct sans approbation, et placez l’approbation seulement dans le pipeline de production. Envoyez la demande par Amazon SNS (Simple Notification Service) avec le commit, le lien vers le diff et l’URL de staging, pour que l’approbateur décide en quelques secondes. Donnez à deux personnes nommées le droit d’approuver, et alignez le délai d’expiration sur votre rotation de garde.
Ce qui se passe
L’action d’approbation manuelle par défaut de AWS::CodePipeline::Pipeline fait trois choses mal d’origine :
- La notification SNS est générique — elle dit « approbation nécessaire » avec un lien vers la console, mais aucun contexte sur ce qui est déployé, ce qui a changé, ou comment le staging a été validé.
- L’expiration de l’approbation est de 7 jours, et après expiration le pipeline passe à Failed, ce qui casse silencieusement les exécutions suivantes parce que la plupart des équipes ne surveillent pas les états d’échec restés en place.
- Il n’y a pas de concept d’« approbateur secondaire » natif dans CodePipeline — si l’approbateur principal est en congé, les releases s’accumulent jusqu’à son retour.
Le pattern qui corrige les trois a quatre pièces mobiles :
- Deux pipelines, pas un. Le staging est son propre pipeline sans approbation — les pushes vers
maindéploient en staging automatiquement. La production est un pipeline séparé déclenché par un tag de release (ou un déclenchement manuel) avec l’action d’approbation. Cela sépare « itération rapide » de « release considérée ». - Sujet SNS par environnement, abonné à un canal Slack et une liste de diffusion courriel. La notification porte le SHA du commit, le ticket JIRA (extrait du message de commit), l’URL staging et le diff. L’approbateur voit le vrai changement, pas juste l’ID de l’exécution du pipeline.
- L’expiration d’approbation est intentionnelle, pas par défaut. Réglez l’expiration sur un nombre qui correspond à la rotation de garde de l’équipe. Pour une équipe avec rotations hebdomadaires, 5 jours est juste — cela signifie que le même garde voit l’approbation et l’expiration dans la même semaine.
- Approbateur secondaire via IAM, pas via la config du pipeline. Deux personnes nommées ont
codepipeline:PutApprovalResultsur l’action d’approbation. L’une ou l’autre peut approuver. Si le principal est injoignable, le secondaire clique approuver et le déploiement procède.
L’état final est un pipeline où l’approbation est une confirmation de 30 secondes, pas un blocage de réunion.
Comment vérifier
L’action d’approbation avec un câblage SNS adéquat :
ApprovalTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: !Sub ${AppName}-prod-approval
Subscription:
- Endpoint: !Ref ApproverEmail
Protocol: email
- Endpoint: !Ref SlackWebhookSubscription
Protocol: https
ApprovalAction:
Name: ManualApproval
ActionTypeId:
Category: Approval
Owner: AWS
Provider: Manual
Version: '1'
Configuration:
NotificationArn: !Ref ApprovalTopic
CustomData: !Sub |
Commit: #{SourceVariables.CommitId}
Auteur: #{SourceVariables.AuthorDisplayName}
Message: #{SourceVariables.CommitMessage}
URL staging: https://staging.${DomainName}
Diff: https://github.com/${GitHubOwner}/${GitHubRepo}/commit/#{SourceVariables.CommitId}
ExternalEntityLink: !Sub https://staging.${DomainName}/healthz
Les substitutions de CustomData utilisent les variables d’action de CodePipeline — SourceVariables.CommitId, SourceVariables.AuthorDisplayName, SourceVariables.CommitMessage — peuplées par l’étape Source depuis l’action CodeStar Source. L’approbateur ouvre le courriel SNS et voit le vrai commit qu’il approuve, pas un « approbation nécessaire » générique.
Du côté Slack, le pattern SNS-vers-Slack utilise un abonné Lambda qui publie un message avec deux boutons : Approuver et Rejeter. Le Lambda appelle aws codepipeline put-approval-result contre le jeton de l’action d’approbation. Le jeton est inclus dans la charge utile SNS — le Lambda l’extrait, l’approbateur clique le bouton, l’appel se complète en moins d’une seconde. La politique IAM sur le rôle du Lambda :
{
"Effect": "Allow",
"Action": "codepipeline:PutApprovalResult",
"Resource": "arn:aws:codepipeline:ca-central-1:111111111111:app-prod-pipeline/Approval/ManualApproval"
}
Restreignez la ressource à l’ARN spécifique de l’action d’approbation, pas *. C’est le genre de piège « toute approbation de pipeline » qui devient une découverte « tout utilisateur peut approuver tout déploiement » dans le prochain audit.
Vérifier que l’expiration fonctionne comme prévu :
aws codepipeline get-pipeline \
--name app-prod-pipeline \
--query 'pipeline.stages[?name==`Approval`].actions[0].timeoutInMinutes'
Si la réponse est null, l’action utilise la valeur par défaut de 7 jours. Pour régler une expiration explicite, la propriété CloudFormation est TimeoutInMinutes sur l’action — notez que les actions d’approbation manuelle CodePipeline supportent des expirations jusqu’à 7 jours (10080 minutes). La régler plus bas que votre cycle de garde est intentionnel — cela force l’expiration à tomber sur le quart de quelqu’un, pas le dimanche matin où personne n’est de garde.
La correction
Le pattern complet, dans l’ordre :
-
Séparez staging de prod. Le staging est son propre pipeline déclenché à chaque push vers
main. La prod est déclenchée sur un tag de release (v*), ou manuellement viaaws codepipeline start-pipeline-execution. Utilisez le même projet CodeBuild pour les deux, le même artéfact, la même forme de cible de déploiement — seuls le déclencheur et l’approbation diffèrent. -
Sujet SNS par environnement. L’approbation prod contacte le gestionnaire de compte de garde (Slack + courriel). Les échecs du pipeline staging contactent le même sujet SNS mais avec une ligne d’objet différente. Les autres environnements — dev, qa — vont vers un canal Slack basse priorité uniquement.
-
La notification porte le lien diff. Le champ
CustomDatasur l’action d’approbation est votre seule chance de donner du contexte à l’approbateur. Incluez le SHA du commit, le message de commit, le lien diff et l’URL healthz du staging. Si vos messages de commit ne sont pas assez informatifs pour approuver, corrigez les messages de commit — c’est en amont du problème de pipeline. -
Deux approbateurs nommés, restreints par IAM. Créez un groupe IAM
prod-deploy-approversavec une seule déclaration :codepipeline:PutApprovalResultsur l’ARN de l’action d’approbation. Ajoutez deux personnes. Quand le principal est en congé, le secondaire couvre. Quand les deux sont injoignables, le déploiement attend — c’est le bon comportement, pas un bogue à contourner par l’ingénierie. -
L’expiration correspond au cycle de garde. Rotation hebdomadaire → 5 jours. Rotation quotidienne → 24 heures. Faites-la correspondre à la cadence qui garantit que la même personne voit les deux extrémités de la fenêtre d’approbation. Après l’expiration, le pipeline passe à Failed — une règle CloudWatch Events se déclenche sur
Pipeline Execution State Changeavecstate: FAILEDet la notification SNS se déclenche à nouveau, cette fois vers le groupe secondaire. -
La règle « automatique en staging, manuel en prod » n’est pas une religion. Une charge réglementée qui touche des transactions financières peut nécessiter une seconde approbation aussi en staging. Un site purement marketing peut ne pas nécessiter d’approbation du tout. La règle empirique : si un mauvais déploiement cause une corruption de données, vous avez besoin d’approbation. Si un mauvais déploiement cause un mauvais rendu de page pendant 10 minutes avant le rollback automatique, vous n’en avez pas besoin.
Le but de l’approbation manuelle est de faire en sorte que quelqu’un lise le diff avant la prod. Faites en sorte que ce soit facile pour eux de le faire, difficile pour eux d’approuver sans lire, et impossible pour le pipeline de pourrir silencieusement quand ils sont injoignables.
Stack Harbor bâtit et opère les workflows CodePipeline en production dans le cadre de l’onboarding Gestion AWS et de la couche Pipeline de déploiement en continu. Si votre chemin de release passe encore par SSH et un message Slack, commencez par une consultation d’infrastructure.