CloudWatch + Lambda + Trello APIで決まった時間にレビュー待ちタスクをSlackに投げる仕組みを作った

# 経緯
うちの会社では、マージする時間を13時と17時の2回に決めています。
ところが、開発に集中しすぎてマージの時間を過ぎてしまい、"レビューが終わっていなくてマージができない"という事態が頻発していました。
この状況をなんとか改善するために、今回の仕組を作ってみました。

# 業務の流れ
Trelloで全てのタスクを管理しています。基本左から右にカードを流していく感じになっています。
※我々は、StagingのことをSexyと呼んでいます

WIP -> Review -> Sexy review -> Sexy Done -> QA test done

WIP: 作業中タスク
Review: 開発が終わり、他の人にレビューしてもらうタスク
Sexy review: Stagingブランチにマージされ、Sexy環境にdeployされたタスク
Sexy Done: Sexy環境で開発者本人が動作確認を行って問題なかったタスク
QA test done: QAチームがSexy環境で動作確認を行って問題なかったタスク

<img width="1405" alt="スクリーンショット_2018-01-21_15_23_54.png" src="https://qiita-image-store.s3.amazonaws.com/0/104056/4327a637-9778-feb4-b8da-eacd3d22f586.png">

こんな感じで、日々の業務が流れています。
ただ、気づいたらレビューする時間を過ぎているんですよね。これだとQAチームにタスクが流れていかない状況になってしまうので、それを何とか解決したかった。

# Slackのリマインダーでいいじゃん
リマンドをするだけであれば、Slackで以下のコマンドを打てば、リマンドしてくれますよね。
`/remind @tec レビューしてください 12am weekday`
ただこれの問題点は、マンネリ化するところ。昔我々もこのリマインドをしてみたけど、いつも同じメッセージで、レビューする内容のタスクもそのリマインドでは確認できないのでやめました。

# Trello APIを使ってカードの情報を取得してどうにかできないか
Trello APIは結構色々出来ることに気づきました（[公式Docs](https://trello.readme.io/reference#introduction)）。
Board id -> List idでReview Listのidを取得し、そのListの全てのカード情報を取得することができました。

```
https://api.trello.com/1/lists/<list_id>/cards?key=<key>&token=<token>&fields=url,name
```

※key, tokenは、[ここ](https://trello.com/app-key)から発行してください

# バックエンドをどうするか
EC2インスタンス立ち上げて、、、。メンテが面倒だし、通知だけのために常に起動しているのは、もったいない。
そこで、Lambdaを使うことにした。今まで、あんまり使う場面がピンとこなかったので、手を出していなかったが、先にいうとメチャクチャ便利。インフラの人間でない自分からしたら、サーバーレスとか聞いても何も響かなかったけど、Lamdbaは呼び出されてから処理が終わるまでの数秒（もちろん処理の重さによるが）だけ課金される。それ以外の時間はもちろん課金されない。サーバーレスっていいね！ってなりました（無料枠まであるじゃないか。詳しい料金表は[こちら](https://aws.amazon.com/jp/lambda/pricing/)）。しかも、言語を選ぶだけでよくて、メンテとかもいらない。サーバーレスっていいね！！ってなりました。
※最近、Go言語もサポート言語に加わりました。
(20180120時点のサポート言語: C#, Go, Java, Node.js, Python)

# 定期実行するにはどうすれば…
まさか、CloudWatchでできるとは知らなかった。CloudWatch=log参照のイメージがあったので、恥ずかしながらCronでイベントを発火させられる機能があることを知りませんでした。これで、指定した日時にLambdaを発火させることができます。

# 以上の3つで、やりたいことが実現できる
一旦ここまでの流れをまとめると、
1. CloudWatchでCronを設定し指定した日時にLambdaを発火させる
2. Lambda内の処理でTrello APIを叩きカード情報を取得する
3. 取得したカードの内容を整形し、Slackに投げる
っていう感じになります。

ここから実際に設定を行っていきます。

# Step1. Lambdaの設定
Lambdaを選択し、画面の右上にある「関数の作成」をクリック。
<img width="1521" alt="step1.png" src="https://qiita-image-store.s3.amazonaws.com/0/104056/af5a484a-90a4-ffca-41ea-de2a54b7b433.png">


Lambda関数の内容を以下のように設定してください。
※ロールの話はここでは割愛します
※最後に自分が作ったサンプルコードがあるので、それを実行したい場合はPythonを選んでください
<img width="1514" alt="step2.png" src="https://qiita-image-store.s3.amazonaws.com/0/104056/4529cb8d-786d-0b04-0a04-e6e653cc4fe0.png">


Lambda関数を作成すると以下の画面が出てきます。
<img width="1520" alt="step3.png" src="https://qiita-image-store.s3.amazonaws.com/0/104056/c16b8bb3-e1c1-386c-6535-ecd5ce0388a3.png">


Lambda関数の関数コードと環境変数を設定していきます。
関数コードのコード エントリ タイプを「.ZIPファイルをアップロード」を選択してください。
アップロードするコードは、[Github](https://github.com/walkersumida/lambda-trello-slack-notice)で公開しています。git cloneしたら、READMEに書いてる Install packagesとCreate zip file for lambdaの手順を実行してください。そしたら、upload.zipを画面の「アップロード」から選択してください。
次に、環境変数を設定してください。環境変数のサンプルは、[このファイル](https://github.com/walkersumida/lambda-trello-slack-notice/blob/master/.env.sample)を参考にして設定してください。
※TRELLO_API_URLで使用するkey, tokenは、api専用のユーザを作って発行することをおすすめします。自分のを使ってもいいですが、Private Boardなども取得できてしまうため、あまりおすすめしません
全ての設定が完了したら、画面右上の「保存」をクリック。
<img width="1407" alt="step4.png" src="https://qiita-image-store.s3.amazonaws.com/0/104056/265007e8-dc19-8236-b2c9-d057f1dbebf5.png">


# Step2. CloudWatchの設定
CloudWatchを選択し、左にある「ルール」をクリックし、「ルールの作成」をクリック。
「スケジュール > Cron式」を選択し、Cronを設定します。今回はマージ時間の１時間前に通知したいので、12, 16時に実行するように設定します。
設定する時間はGMTなので、-9して設定しています。Cronの書き方は[こちら](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html)。
※20180120時点では、左から2番目の曜日設定の部分が、?以外設定すると登録できない。平日設定をしたかったのに。。。しょうがなく、平日か否かは、Lambda内でチェックしてます。
<img width="1522" alt="step5.png" src="https://qiita-image-store.s3.amazonaws.com/0/104056/7a6863e3-4a94-2ac5-6aec-755877f89bb9.png">


「設定の詳細」をクリックし、名前を付け「ルールの作成」で設定は完了！
<img width="1521" alt="step6.png" src="https://qiita-image-store.s3.amazonaws.com/0/104056/7daad1e5-ce7c-a042-0cc6-69787b742ec7.png">


CloudWatchとLambdaがうまく紐づくと、先程のLambda画面にCloudWatch Eventsが追加されます。
<img width="1409" alt="step7.png" src="https://qiita-image-store.s3.amazonaws.com/0/104056/a00f0128-be9d-0b73-e601-808ca48eb41c.png">


あとは、時間が来ると、以下のようにSlackにPOSTされます。
<img width="458" alt="step8.png" src="https://qiita-image-store.s3.amazonaws.com/0/104056/174b631d-3f1f-957b-c2b6-817720f322f9.png">


# まとめ
これで、きっとReviewにタスクがたまることはなくなるでしょう！
今回は、Reviewを促すメッセージをSlackに投げましたが、環境変数を変えれば、例えば「以下のカードの動作確認をStaging環境で行ってください」とテストを促すことにも使用できます。もしよければ色々組み替えて使ってみてください。