amplifyでdeploy完了時、メールで通知することができるが、 いちいちメールが飛んでくるのが結構邪魔になるのでそのイベントを Slackに通知するようにしたい。
具体的にはAWS AmplifyのEmail notificationsを設定するとそのメールをもとにAWSのSNSが設定されるので その設定に相乗りする形でLambdaを使ってSlackに通知を送るというものです。
https://[YOUR_ORG].slack.com/apps から Incoming WebHooksを検索し、アプリを追加します。
新規のIncoming WebHooksを追加し、Webhook URLが発行されます。 Customize Name、Icon等は呼び出し時に上書きするでデフォルトのままで良いです。
SNSから送信されたメッセージをSlackのwebhookに送信する処理をNode.jsを使って記述します。
SNSからLambdaが起動されるとき、
第一引数のeventの中身は以下のようなオブジェクトになっているので、
Sns.Message
の部分をうまくパースして各状態(開始、成功、失敗)の値を取り出します。
// eventの中身
{
Records: [
{
EventSource: 'aws:sns',
EventVersion: '1.0',
EventSubscriptionArn: 'arn:aws:sns:ap-northeast-1:...',
Sns: {
Type: 'Notification',
MessageId: '5d6ef129-e0b3....',
TopicArn: 'arn:aws:sns:ap-northeast-1:....',
Subject: null,
Message: '"Build notification from the AWS Amplify Console for app: https://... Your build status is STARTED. Go to ..."',
Timestamp: '2019-07-09T10:41:43.599Z',
SignatureVersion: '1',
Signature: 'MwvX3GHzK...',
SigningCertUrl: '<https://sns.ap-northeast-1.amazonaws.com/xx.pem>',
UnsubscribeUrl: '<https://sns.ap-northeast-1.amazonaws.com/>...',
MessageAttributes: {}
}
}
]
}
Lambdaの関数は以下のようなします。
const https = require('https');
const AMPLIFY_STAT = {
STARTED: 'STARTED',
SUCCEED: 'SUCCEED',
FAILED: 'FAILED'
};
/**
* snsから送られてくるメッセージをparse
*/
const parseSnsMessage = (event) => {
if (!event.Records && Array.isArray(event.Records)) {
return {
text: 'deploy failed!(parse failed)'
};
}
if (!event.Records[0].Sns && !event.Records[0].Sns.Message) {
return {
text: 'deploy failed!(parse failed)'
};
}
const msg = event.Records[0].Sns.Message;
const mathcher = msg.match(/Your build status is (\\w+)./);
let text = '';
if (mathcher) {
const stat = mathcher[1];
switch (stat) {
case AMPLIFY_STAT.STARTED:
text = 'deploy started...';
break;
case AMPLIFY_STAT.SUCCEED:
text = 'deploy succeed!';
break;
default:
text = 'deploy failed!';
}
}
return {
text
};
};
exports.handler = async(event) => {
const { text } = parseSnsMessage(event);
// slackのincoming hookへ送信
const data = JSON.stringify({
channel: '#playground',
username: 'amplify-deploy-state',
text,
icon_emoji: ':smirk_cat:'
});
const options = {
hostname: 'hooks.slack.com',
port: 443,
path: '/services/xxxx/xxxx/xxxx', // ここにwebhookのURLを設定します。
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': data.length
}
};
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
res.on('data', (d) => {
resolve({ statusCode: res.statusCode });
});
});
req.on('error', (error) => {
console.error(error);
reject(error);
});
req.write(data);
req.end();
});
};
Lambdaの関数をテストする際はtemplateにAmazon SNS Topic Notification
があるのでそれを利用すると便利です。
冒頭で説明した通り、Amplifyでメール通知を設定した場合、snsのtopicがつかされているのでそれを参照します。
Create subscriptionから新しいSubscriptionを作成します。
ProtocolにAWS Lambda
を、Endpointに先程作成したLambda関数を指定します。
AWS Amplifyのコンソールからredeploy等を実行すると。 通知がslackに来ることが確認できます。
確認ができたらSNSについている、Emailの方のSubscriptionは削除してもらって問題ないと思います。(もし必要になったら再度つければいいと思います)