yasudacloudの日記

札幌に住むソフトウェアエンジニア

SlackワークフローをAWS上でビルド&デプロイする

最近仕事の関係でSlackのProプランに加入したのですが、あまり使っておらず少し勿体ない状況でした。せっかくなので独自のワークフローを作っていって日々の作業を効率化していきたいと思います。

まずはキャッチアップ編として簡単なSlackワークフローを作成し、CodePipeline等を駆使してクラウド上からワークフローのデプロイを自動化する環境を作ります。

大体こんな感じのものを作ります。

1. Slackコマンドのインストール

まずはローカル環境でslackコマンドを使えるようにします。下記の公式ドキュメントを参考にコマンド一発でインストールできます。

api.slack.com

2. ワークフローのテンプレートをダウンロード

同じくドキュメントにDenoのワークフローのサンプルテンプレートが記載されているのでこちらをcloneします。

github.com

次にslack loginコマンドを実行してワークスペースにログインします。サンプルは特にいじらなくても動くので、プロジェクト直下でslack runコマンドを実行してみます。

完了するとSlackアプリ上のメッセージ欄(DMとか)で/を入力するとワークフローが追加されているはずです。

上記を選択するとチャンネルとメッセージ内容の入力フィールド、そしてボタンのフォーム画面が表示されました。

ここまで出来ればあとはドキュメントの仕様を見ながら自分好みにコードを書いていけばワークフローは出来そうです。実装内容は次回にして今回はこのままいきます。

3. ワークフローをDockerでビルドする

クラウド上で先ほどのslackコマンドを自動化するためにDockerで動かせるようにします。

そこで気がかりなのがslack loginやslack runを実行する際にインタラクティブな操作を求められるという点です。しかし、この手のツールはきっと上手く出来てるはずなので何気なくslack login --helpと叩いてみます。

どうやらtokenを使って認証できそうですね。

そして他のコマンドを眺めているとslack auth tokenというコマンドを発見しました。こちらでトークンを発行できます。

トークンの使い方は簡単、実行したいコマンドに引数 --token xoxp-から始まるトークン を付けてあげれば良いみたいです。この辺結構苦労したんですが、、こちらのドキュメントに記載されていました。

上記を諸々まとめるとDockerfileは以下のようになりました。

FROM denoland/deno:debian-1.40.5
COPY ./ /var/app
WORKDIR /var/app
RUN apt-get update && \
apt-get install curl -y && \
curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | /bin/bash

これを先ほどのサンプルプロジェクトの直下に設置します。当初は横着してdeployコマンドもRUNに書いていたのですが、runする時にdeployをするようにしました。(後述)

4. CodePipelineで実行する

いよいよ自動化になります。

先ほどのイメージ図をもう一度。

手順はコードの変更をCodePipelineで検知して開始、CodeBuildで先ほどのDockerfileをビルドし、コンテナからslack deployコマンドを実行となります。
--tokenのトークンは機密情報なのでSecrets Managerから取得します。

ECRを使っているのはDockerのpull制限問題に回避するためで、先ほどのdenoland/deno:debian-1.40.5のイメージをローカルでタグだけ変えてECRのリポジトリにPushしておきます。Macだとアーキテクチャが違ってエラーになることがあるのでCloud Shellからpull&pushするのをおすすめします。

→ECR Publicに良さげなDenoのイメージがなかったのでプライベートなECRを利用しています。Dockerのログインも不要で扱いやすいのでこのやり方が個人的に好みです。

Dockerfileを修正

ECRを使う場合は先ほどのDockerfileのFROMを修正し、CodeBuildからECRのリポジトリを読み込めるように別途権限付与を行ってください。

FROM AWSアカウントID.dkr.ecr.ap-northeast-1.amazonaws.com/リポジトリ名:latest
COPY ./ /var/app
WORKDIR /var/app
RUN apt-get update && \
apt-get install curl -y && \
curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | /bin/bash

buildspec.ymlの記述

buildspec.ymlを以下のようにしました。こちらもワークフローのサンプルプロジェクトの直下に置きます。

gist.github.com

解説)

・環境変数SECRET_MANAGER_NAMEをCodeBuild側に設定します。(Secrets Managerのname)

・Secrets ManagerにSLACK_TOKENという名称でslack tokenコマンドで生成したトークンを保存しておきます。

・docker build -t slack_container .はサンプルプロジェクト直下にあるDockerfileを基にslack_containerというタグ付けをしています。

5. 結果

IAM周りやGitHubの連携など細かい所をいくつか省略しましたが、結果としてはCodePipeline(CodeBuild)からデプロイが成功しました( ✌︎'ω')✌︎

その他

今回は最小限のサービス構成になりますが、利便性を上げる拡張を幾つか考えてみます。

まず、デプロイ後にアプリに問題があってなるべく早く一個前に戻したいというケースが考えられます。それにはビルドしたイメージをECRに保持しておけば遡ったバージョンでdocker runすれば復旧できそうです。

ユーザー数の多い環境ではいきなりワークフローを更新したくない可能性があるので、環境(ワークスペース)ごとにPipelineを作ってTokenをそれぞれ設定すれば対応できます。

また、省略しましたがCodePipelineなのでデプロイ前にテストフェーズを挟むことも容易です。(サンプルプロジェクトにはテストコードも少し記述されています)

最後に

英語のドキュメントなのでちょっと読みにくいですが、やってみると結構面白いです。

Slackワークフローのアプリを自動デプロイできて何が嬉しいのか?という疑問があると思いますがそれは次回ご紹介します。