CodeDeployの結果をSlackに通知する

こちらはJoolen Advent Calendar 2019 6日目の記事です。
前日の記事は@kyoko2iさんの[Doctrineでちょっと複雑なSQLを発行する](https://qiita.com/kyoko2i/items/01a1675fbeee326c56b5)でした。
カレンダーのURLはこちら
[Joolen Advent Calendar 2019](https://qiita.com/advent-calendar/2019/joolen)

## 2021-03-09追記
アプリケーション単位で通知する場合、AWS Chatbotを使用することで、こちらの記事の内容より簡単にSlackに通知可能になりました。
そちらに関する記事は別途作成します。

デプロイグループ毎に通知を分ける場合はこちらの記事を参考にしてください。

## まえがき
CodeDeployを使用しての自動デプロイは便利ですが、デプロイが終わったのかわからずコンソールを開いて確認するのが面倒ですよね。
なので、デプロイの結果をSlackに通知しようというのが目的です。
CodeDeployを使用したデプロイ方法には触れません。

大まかな流れは
CodeDeploy->SNS->Lambda->Slack
という感じで通知します。

## SNSの設定
SNSのトピックを作成します。
名前と表示名を自由に設定してください。
その他は必須ではないので、自由に設定してください。
![スクリーンショット 2019-11-27 14.07.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193822/ef663d4b-1110-9edd-d9fb-b212075bf9dd.png)

## Lambda関数の作成

### SlackのWebhook設定
通知用チャンネルを作成した後下記のURLにアクセスしてwebhookを設定します。
https://slack.com/services/new/incoming-webhook

Post to Channelで作成した通知用チャンネルを選択してwebhookを設定し、Webhook URLを取得します。

![スクリーンショット 2019-11-27 14.14.58.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193822/ff2b32f6-de57-47cc-9275-fb96d2f792d2.jpeg)

### Lambdaの設定
今回Node.jsを使用して作成します。
関数名は自由に設定してください。
実行ロールは新しく作成するか、Lambdaへのアクセス権限を持ったロールを設定します。
![スクリーンショット 2019-11-27 14.29.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193822/36db1160-6036-3da6-4458-7f9fc1e86baa.png)

関数は以下の通りです
regionなどは適宜変更してください。

```javascript
const https = require('https');
const url = require('url');
// 取得したWebhook URLを設定
const slack_url = 'https://hooks.slack.com/services/xxxx/xxxx';
const region = 'ap-northeast-1';
const codedeploy_url = 'https://' + region + '.console.aws.amazon.com/codedeploy/home?region=' + region + '#/deployments/';
const slack_req_opts = url.parse(slack_url);
const slack_color = {
  'SUCCEEDED': 'good',
  'ABORTED': 'warning',
  'FAILED': 'danger',
};
slack_req_opts.method = 'POST';
slack_req_opts.headers = {'Content-Type': 'application/json'};

exports.handler = function(event, context) {
  (event.Records || []).forEach(function (rec) {
    if (rec.Sns) {
      var req = https.request(slack_req_opts, function (res) {
        if (res.statusCode === 200) {
          context.succeed('posted to slack');
        } else {
          context.fail('status code: ' + res.statusCode);
        }
      });
      
      req.on('error', function(e) {
        console.log('problem with request: ' + e.message);
        context.fail(e.message);
      });
      var message = JSON.parse(rec.Sns.Message);
      var str = `deploymentGroupName: ${message.deploymentGroupName}`
      + `\ndeploymentId: ${message.deploymentId}`
      + `\nstatus: ${message.status}`
      + `\n${codedeploy_url}${message.deploymentId}`;
      
      req.write(JSON.stringify({
        username: 'CodeDeploy',
        attachments: [
          {
            color: slack_color[message.status],
            fields:[
              {
                title: "deployment result",
                value: str,
              }
            ]
          }
        ]
      }));
      
      req.end();
    }
  });
};
```
リクエストの中身に関しては公式ドキュメントを確認してください。
https://api.slack.com/docs/message-formatting
https://api.slack.com/docs/message-attachments

### トリガーを追加
Lambdaからトリガーを追加します。

トリガーの設定画面でSNSを選択し、トピックは先ほど作成したトピックを選択します。
![スクリーンショット 2019-11-27 14.45.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193822/3a0febe8-a838-3620-b3af-337de9b2c5fd.png)

## CodeDeployの設定
通知したいデプロイグループの編集画面でトリガーセクションから「トリガーの作成」をクリックします。
なお、トリガーセクションは詳細として折りたたまれているので、お気をつけください。
![スクリーンショット 2019-12-06 7.12.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193822/921971b0-3205-7877-d03b-b433b14cea63.png)


トリガー名を適当に設定し、イベントは__デプロイの成功__、__デプロイの失敗__、__デプロイの停止__を選択
その他にも通知したいイベントがあれば選択します。
トピックはLambdaのトリガーに設定したものと同じトピックを選択します。
![スクリーンショット 2019-11-27 14.51.50.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193822/f9d265bc-ec3a-3e32-df39-e3a18bb4295b.jpeg)

以上で設定は終了です。
実際にCodeDeployを動かしてみます。
![スクリーンショット 2019-11-27 14.55.56.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193822/431a1ce1-1e48-4622-3f1d-8ea27aa432ff.jpeg)
通知が来ました!

これで逐一確認する手間から逃れることができました。

明日は@y_shiraiさん[]()です。