2017-06-22のアップデートでCodeBuildのビルド結果をCloudWatchEventsで捕捉できるようになりました。
そのままSNSで通知してもいいのですが、LambdaからIncoming Webhookを使ってSlackに通知してみようと思います。
事前準備
以下のことはすでに済んでいる前提で話を進めます。
- CodeBuildのプロジェクト作成
- SlackのIncoming Webhookの設定(URL発行)
実装
さくっと済ませたいのでServerlessフレームワークを使います。
serverless.yml設定
まあこいつを見てもらおうか
service: notify-build-result
provider:
name: aws
runtime: nodejs6.10
timeout: 180
stage: ${opt:stage, self:custom.defaultStage}
#profileオプション追加
profile: ${opt:profile, self:custom.defaultProfile}
#regionオプション追加
region: ${opt:region, self:custom.defaultRegion}
custom:
defaultStage: dev
#何も指定がなければ default profile
defaultProfile: default
#何も指定がなければ 北バージニア
defaultRegion: us-east-1
functions:
notify:
handler: handler.notify
memorySize: 128
events:
- cloudwatchEvent:
event:
source:
- "aws.codebuild"
detail-type:
- "CodeBuild Build State Change"
detail:
build-status:
- SUCCEEDED
- FAILED
- STOPPED
project-name:
- my-project-name
enabled: true
イベントの設定
今回キモになるeventsの設定項目は詳しめに説明します。
cloudwatchEventを指定することで、cloudwatchのイベントをトリガーにできます。
cloudwatchEvent.event 以下の項目は
項目名 | 解説 |
---|---|
source | cloudwatchで見る対象 今回はCodeBuildが対象なのでaws.codebuildでOK |
detail-type | 検知するイベントの種類 "CodeBuild Build State Change"を指定するとCodeBuildのステートが変化したタイミングでイベントが発火します。 |
detail | detail以下はCodeBuild特有の設定 |
detail.build-status | CodeBuildのステートがここで設定したものになるとイベントが発火します。用意されているのはSUCCEEDED(成功), FAILED(失敗), STOPPED(中断), PROGRESS(進行中)がありますが、今回は結果を教えてほしいのでPROGRESSは外してます。 |
detail.project-name | 監視対象のプロジェクト 配列の形で複数指定することもできます |
enabled | トリガーの有効/無効 |
Lambdaファンクション
payload確認
Lambdaファンクションの実装前に、cloudwatchEventからLambdaをコールしたときにevent引数に何が渡されるか確認しておきます。
いや、まじでトリガーによって引数全然違うから確認しとかないと死ぬ。
イベントの種類によってはLambdaのコンソールのテストイベントの設定からこんな感じで見れますが、
残念ながらCodeBuildのcloudwatchEventはこの方法では見られなかったので、Lambdaのコード内でconsole.log(event)
とかやって調べます。
その結果がこちら
{
"version": "0",
"id": "50639ce0-1497-4911-baa0-79d9ca880a21",
"detail-type": "CodeBuild Build State Change",
"source": "aws.codebuild",
"account": "account-number",
"time": "2017-06-26T07:10:43Z",
"region": "us-east-1",
"resources": [
"arn:aws:codebuild:us-east-1:account-number:build/my-project-name:9eb34205-9cba-40f2-a5d0-220497a9643a"
],
"detail": {
"build-status": "SUCCEEDED",
"project-name": "my-project-name",
"build-id": "arn:aws:codebuild:us-east-1:account-number:build/my-project-name:9eb34205-9cba-40f2-a5d0-220497a9643a",
"current-phase": "COMPLETED",
"current-phase-context": "[]",
"version": "1"
}
}
event.detail以下を見れば何とかなりそうですね。
ファンクション本体
それでは本体を実装していきましょう。
方針としては
- event引数からプロジェクト名とビルド結果を取得
- 予め用意したSlackのwebhook URLに送信
これだけです。
requestモジュールでPOSTするだけの簡単なお仕事ですね。
"use strict";
const request = require('request');
function sendRequest(url, message, callback){
const post = {
text: message
};
//ヘッダーを定義
const headers = {
"Content-Type":"application/json"
};
const options = {
url: url,
method: "POST",
headers: headers,
json: true,
body: post
};
request(options, (error, response, body) => {
console.log(body);
return callback();
})
}
module.exports.notify = (event, context, callback) => {
const url = "your-webhook-url";
const buildDetail = event.detail;
const message = `${buildDetail["project-name"]}のビルドが${buildDetail["build-status"]}デース!`;
sendRequest(url, message, () => {
callback(null);
});
};
結果確認
成功
失敗
なんでペガサスなの?
- SUCCEEDEDとかFAILEDとかわざわざ日本語に直すのがめんどくさかった
- かといって全部英文にして「英語で言われてもわかんねーよ」とか怒られるのも嫌だった
- せや、ペガサスだったら英語と日本語が混ざってても違和感ない!いけるやん!
実装してから気づいたこと、改善案
- cloudwatchEventの発火がめっちゃ早い
- CodePipeline内に設置したCodeBuildに仕込んでたところ、ペガサスの通知が来てから数十秒間はCodePipelineのコンソールではビルド中と表示されていた。
- メンション欲しいかも
- CodePipelineの手動承認とかと組み合わせるなら、担当者へのメンションが欲しい