freeeの開発情報ポータルサイト

社内SlackアプリをHubotからBoltに移行した

社内の自動テスト実行に使っているSlackアプリをHubotからBoltに移行したのでその際の流れや詰まりどころを話します。 BoltがLambdaからEC2のJenkinsサーバを叩いている点が典型的な構成とは少し異なり、詰まったところでもあるので、同じ構成の人の助けになればと思います

Hubotについて

Hubotとはチャットボットの開発や実行を行うフレームワークです。

hubot.github.com

freeeではStaging環境に向けて自動テストを実行したいときのChatOpsとしてHubotを利用しています。具体的にはSlackで決められたメッセージを送信します。Slackのメッセージの最初にqabotとつけると反応するようにしてあるので、qabot [実行したいテスト名]のようにSlackで打つことでHubotがEC2上にあるJenkinsを叩いて自動テストを実行しています。

ユーザーがqabot 実行したいテスト名とSlackで打つとHubotからJenkinsを実行する。JenkinsはSlackに自動テストの結果を返す

課題

自動テストで使っているHubotアプリには以下の課題がありました

  • CoffeeScriptベースなので社内に慣れてるメンバーが少なく、触るハードルが高い
  • EC2インスタンスの管理が必要。OSやミドルウェアのアップデートなど
  • EC2インスタンスをずっと起動しておく必要があり、無稼働の時でもコストがかかる
  • Hubotの開発が最近あまり活発でない(hubot-slackは開発が進められているが)

これからの課題を解決するためにHubotからBoltへの移行を行いました。

Boltについて

BoltとはSlackのための開発ツールでJS, Python, JavaのSDKがあります。

api.slack.com

  • TypeScriptで使える
  • サーバーのメンテナンスが不要
  • Lambda上で動くので必要なときだけ実行される

Boltを使えばHubotの課題を解決できると感じたので今回利用することにしました。

Hubotベースの仕組みからからBoltベースの仕組みへ移行するためにやったこと

優先度が高かったのが脱CoffeeScriptだったので、まずはCoffeeScriptを外すことを優先しました。そこからBoltで動くようにロジックを変更して、最後にTypeScriptに移行しました。

  1. CoffeeScriptからJavaScriptに移行
  2. ロジックをHubotからBoltに移行
  3. JavaScriptからTypeScriptに移行

1. CoffeeScriptからJavaScriptに移行

一気にTypeScriptに移行することはせず、CoffeeScript -> JavaScript -> TypeScriptと段階的に移行しました。 CoffeeScriptからJavaScriptへの移行はdecaffeinateを利用しました。 decaffeinateは機械的に変換するのでJavaScriptが冗長になることがあり、合わせて修正を行いました。

2. ロジックをHubotからBoltに移行

BoltはHubotと書き方が結構違うのでドキュメントを一通り読むのをオススメします。移行については公式のMigration Guideがあるのでそちらが参考になります。 slack.dev

3. JavaScriptからTypeScriptに移行

JavaScript-> TypeScriptはHubotからBoltに移行する際に合わせて行いました。 (公式ドキュメント)https://slack.dev/bolt-js/ja-jp/tutorial/using-typescriptはあるのですが、特に詳しく書かれていないので、自力で進めていく必要があります。

EC2からLambdaに移行するにあたって

インフラをEC2からLambdaに変更する際に詰まったところや変えたところについて説明します

EC2上にあるJenkinsが叩けない

BoltはLambdaにデプロイしているのでEC2が配置されているVPCの外にあり、VPC内に入れたとしてもでもネットワークのやりとりも制限されているのでLambdaからのリクエストが弾かれてしまいます。

LambdaからEC2にアクセスしたいがEC2がVPCの中にある

対応方法

まずはLambdaをVPC内に配置します。しかし、同一VPCであってもネットワークのやりとりは制限されているので、これだけではLambdaからのリクエストは弾かれてしまいます。

LambdaをEC2と同じVPCに配置する

その後LambdaにElastic IPを付与、JenkinsのEC2に割り当てているSecurity Groupに付与したIPアドレスを許可させました。

LambdaのIPアドレスを固定してSecurity Groupで許可する
詳しくは以下の記事が参考になりました

構成をサーバレスに変更

デプロイされているファイルを編集して上書きするコマンドがありました。Hubotの時はEC2上にデプロイしたファイルを読み込み-> 書き込みしていたのですが、BoltはLambda上にデプロイしており、S3上にファイルがある方が取り回しが楽なので変更しました

対応方法

まずはEC2にあったファイルをS3に配置して、Lambda 関数が Amazon S3 にオブジェクトをアップロードすることを許可する Lambda 実行ロールを作成。その後、S3から読み込み-> 書き込みするように変更しました。

最後に

素直にLambdaだけで完結させるのであれば公式ドキュメントだけで移行できました。そこから社内のユースケースに合わせて修正するのが大変なんだよなぁと思った開発でした。