こんにちは。百木田です。
CI、回してますか?
CodePipelineで実行するステージの進行状況を手軽に見たいと思い、Slackに流れるようにしたので共有します。
ポイントとしては、CodePipelineからLambda functionを呼ぶのではなく、CloudWatchイベントでCodePipelineステージのステータスの変化を検知してLambda functionを呼び出します。
今回はできるだけシンプルにするために、すでにCodePipelineは作成済みの想定で、すべてのステージにおけるSUCCEEDEDとFAILEDのステータスを通知します。なのでCodePipelineに変更は必要ありません。
また、Slack Botを作成しトークンを発行して使っていますがIncomming Webhookでも同じようなことはできるかと思います。
Serverless Frameworkを使ってCloudWatchイベントの設定と、slackに通知するためのLambda functionをデプロイします。
環境
1 2 3 |
$ serverless version 1.22.0 |
ディレクトリ構成
1 2 3 4 5 |
- functions/ - status_notification.py - serverless.yml - serverless.env.yml |
デプロイ
コードは記事の下の方に書いときます。上記のディレクトリ構成のように配置したらデプロイします。
1 2 |
$ serverless deploy |
デプロイできたらCodePipelineを動かしてみます。そうするとslackにこのような通知が来るかと思います。
いつの実行結果なのかをトレースできるようにCodePipelineの実行IDの前半7桁を表示しています。この辺はお好きにカスタマイズしてみてください。
まとめ
CloudWatchイベントの検知がリアルタイムじゃないので、CodePipelineの進行と通知にラグがあったり、前のステージの実行完了と次のステージの実行開始の通知が前後することなどもありますが、実行結果がわかればいいかなくらいの感じなので気にしないことにしてます。
ありがとうございました。
以下、コードたち
status_notification.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# -*- coding:utf-8 -*- """CloudWatch Eventから送られてきたCodePipelineのステージステータスの変更をSlackに通知する""" import os import boto3 import urllib.request, urllib.parse URL = 'https://slack.com/api/chat.postMessage' SLACK_BOT_TOKEN = os.environ['SLACK_BOT_TOKEN'] CHANNEL = os.environ['CHANNEL'] client = boto3.client('codepipeline') def handler(event, context): stage_name = event['detail']['stage'] state = event['detail']['state'] pipeline_execution_id = event['detail']['execution-id'] post_message = '[' + pipeline_execution_id[:7] + '] ' + ' ' + state.ljust(10) + ': ' + stage_name post_data = {} post_data['text'] = post_message post_data['token'] = SLACK_BOT_TOKEN post_data['channel'] = CHANNEL data_encoded = urllib.parse.urlencode(post_data).encode("utf-8") req = urllib.request.Request(URL, data_encoded) with urllib.request.urlopen(req) as response: response.read().decode('utf-8') return |
serverless.env.yml
1 2 3 4 |
slack: BOT_TOKEN: xoxb-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxx CHANNEL: XXXXXXXXX |
serverless.yml
※ detailのセクションを消すと、すべてのステータスが検知対象になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
service: slack-notification-sample frameworkVersion: ">=1.18.0 <2.0.0" provider: name: aws runtime: python3.6 region: ap-northeast-1 stage: dev environment: TZ: Asia/Tokyo package: include: - functions/** exclude: - serverless.yml - serverless.env.yml functions: statusNotification: handler: functions/status_notification.handler events: - cloudwatchEvent: event: source: - aws.codepipeline detail-type: - CodePipeline Stage Execution State Change detail: state: - SUCCEEDED - FAILED environment: CHANNEL: ${file(./serverless.env.yml):slack.CHANNEL} SLACK_BOT_TOKEN: ${file(./serverless.env.yml):slack.BOT_TOKEN} |