開発合宿でhugo + github + CodeBuildを使ってブログ環境を構築したわけですが、 CodeBuildで処理が本当に始まっているのか、ちゃんと処理が完了したのかわからないとちょっと不安です。
そこでCodeBuildの処理の開始と終了を個人Slackに通知するようにしてみました。
最終構成はこんな感じです
SlackでIncoming WebHookのURLを取得する
まずSlackの設定から”Add an app”でIncoming WebHooks
を追加します。
こいつは特定のURLを叩くと任意の内容の通知をしてくれる便利なやつです。
ここでは#awsチャンネルに通知されるように設定しています。
設定したらwebhook用のURLが取得できるのでこれを後ほど使用します。
Lambda関数を作成する
次にAWS Lambda関数を作成します。
実はSlackに通知するテンプレートが用意されているのでこれを使用します。
nodejsでもいいのですが今回はpython3のcloudwatch-alarm-to-slack-python3
テンプレートを選択します。
基本情報は適当に入力します。 その下にSNSの設定がありますが今回は使用しないので削除してOKです。
次に環境変数を設定するのですが、その前に暗号化の設定をします。 暗号化の設定をすると環境変数に設定する値も暗号化されるので悪用されるのを防げます。
伝送中の暗号化のためのヘルパーの有効化にチェックを入れてください。
キーがない場合以下のようにエラーがでるのでリンクのキーを作成
からKMSキーを作成して設定してください。
暗号化キーを設定できたら、環境変数を設定します。
slackChannel
に通知するチャンネル名kmsEncryptedHookUrl
にIncoming WebHookのURL (https:// の部分は除いてください)
を設定して、kmsEncryptedHookUrl
を暗号化ボタンを押して暗号化してください。
暗号化したらこんな感じになります。
できたら関数を作成して、一旦CloudWatchの設定に移ります。
CouldWatchのイベントルールを作成する
CloudWatchを開いて、イベント→ルールの作成
イベントソースは
- サービス名: CodeBuild を選択
- イベントタイプ: CodeBuild Build State Change を選択
- 通知したいステートを選択
ターゲットは
- Lambda関数を選択
- 先程作成した関数名を選択
できたらこんな感じになります。この時、下に表示されるサンプルイベントのjsonをコピーしておいてください。
Lambdaコードを実装する
CloudWatchが設定できたら、先程作成したLambda関数に戻ります。 こんな感じでCloudWatch Eventsが設定されていたらOKです。
肝心のコードは、テンプレートをほんのちょっと変えるだけでOKです。 CodeBuildのプロジェクト名と状態をSlackに通知するには以下のようにすれば大丈夫です。
import boto3
import json
import logging
import os
from base64 import b64decode
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
ENCRYPTED_HOOK_URL = os.environ['kmsEncryptedHookUrl']
SLACK_CHANNEL = os.environ['slackChannel']
HOOK_URL = "https://" + boto3.client('kms').decrypt(CiphertextBlob=b64decode(ENCRYPTED_HOOK_URL))['Plaintext'].decode('utf-8')
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
logger.info("Event: " + str(event))
project = event["detail"]["project-name"]
state = event["detail"]["build-status"]
slack_message = {
'channel': SLACK_CHANNEL,
'text': "CodeBuild: %s - %s" % (project, state)
}
req = Request(HOOK_URL, json.dumps(slack_message).encode('utf-8'))
try:
response = urlopen(req)
response.read()
logger.info("Message posted to %s", slack_message['channel'])
except HTTPError as e:
logger.error("Request failed: %d %s", e.code, e.reason)
except URLError as e:
logger.error("Server connection failed: %s", e.reason)
コードが書けたらテストしてみます。メニューからテストが実行できるのですが、そのときに先程コピーしておいたサンプルイベントのjsonを貼り付けます。
こんな感じでテスト用にjsonを貼り付けて、実際にSlackに通知されたらOKです 🆗
実際にブログを更新して、githubにpushすると…
できました 🎉
ごちゃごちゃと設定しないといけないように見えますが設定してみれば意外と簡単でした。 他のCIにも使えそうですね。