#TL;DR
- AWS codepipelineで承認ボタンを押しても、ボタンが残るケースがある
- 自分の場合、Lambdaでcodepipelineをよしなにする処理を追加
- 他にいい方法ご存知の方は、コメントいただけると嬉しいです
#背景
以下のような形で承認付きのAWS+Docker+BlueGreenDeploymentを構築していました。
図のざっくりな流れとしては、
1.githubでmasterのマージ
2.AWS Codebuild経由で最新dockerイメージをGreen系にデプロイ
3.承認者へslackで通知し、AWSコンソールより承認ボタンpush
4.承認ボタンpush後、ELBのbluegreen切り替え
という感じです。
参考リンク:
https://aws.amazon.com/jp/blogs/news/bluegreen-deployments-with-amazon-ecs/
https://dev.classmethod.jp/cloud/aws/codepipeline-approval-action/
こちらをテスト運用してみたところ、
・問題なく承認してリリースした場合
・codepipelineで一度否認してから再度マージする場合
であれば問題ないんですが、
・否認するまえに再度マージしたpipeline処理が追いついてしまった
場合、codepipelineの承認ボタンを一度押してもまた残ってしまうケースがありました。
#対応
残った承認ボタンによる不要なpipelineの実行を防ぎたかったので、
pipeline実行時に
承認アクションの状態を確認→承認待ちなら自動的に否認
という処理をLambda(python,boto3)でなんとかしています。
以下参考ですがコードです。
import boto3
import logging
import time
logger = logging.getLogger()
logger.setLevel(logging.INFO)
elb = boto3.client('elbv2')
ecs = boto3.client('ecs')
asg = boto3.client('autoscaling')
cf = boto3.resource('cloudformation')
code_pipeline = boto3.client('codepipeline')
def reject_approve(pipeline):
# get pipeline state
response = code_pipeline.get_pipeline_state(
name = pipeline
)
target_stage_pos = response['stageStates'][xxx] //xxx にはApprovalステージの場所
target_action_json = target_stage_pos['actionStates'][0]
print target_action_json
print "-----------"
if 'latestExecution' not in target_action_json:
print "no execution history in this stage."
return
target_stage_name = target_stage_pos['stageName']
print "Check stage name."
print target_stage_name
print "-----------"
target_action_name = target_stage_pos['actionStates'][0]['actionName']
print "Check action name."
print target_action_name
print "-----------"
target_action_status = target_action_json['latestExecution']['status']
print "Check status."
print target_action_status
if target_action_status == 'InProgress':
print "-----------"
target_action_token = target_action_json['latestExecution']['token']
print "Get token."
print target_action_token
print "-----------"
if target_stage_name == 'YOUR_APPROVAL_STAGE_NAME' and target_action_name == 'Approve' and target_action_status == 'InProgress':
print "target check OK."
print "-----------"
print "Reject target approval."
reject_response = code_pipeline.put_approval_result(
pipelineName = pipeline,
stageName = target_stage_name,
actionName = target_action_name,
result={
'summary': target_action_status,
'status': 'Rejected'
},
token = target_action_token
)
print reject_response
else:
print "No action to reject."
def lambda_handler(event, context):
try:
# consts
pipeline_name = 'YOUR_PIPELINE_NAME'
job_id = event['CodePipeline.job']['id']
reject_approve(pipeline_name)
code_pipeline.put_job_success_result(jobId=job_id)
except Exception as e:
logger.error(e)
raise e
#まとめ
pipelineでの手動承認やslack通知についての記事は調べればいくつか出てきますが、
案外こういう細かいケースでの対応はまだ無かったので投稿してみました。
他にいいやり方などありましたら、コメントいただけると幸いです。