前回のエントリーで、コミットをトリガーとしてCIが動作するようになりました。ですがCIの結果は、CircleCIのダッシュボードから確認する必要があります。コミットの度に発火するCIの結果を、都度確認しに行くのは面倒ですよね。そして人間は面倒なことはすぐサボってしまうものです。
そこで本エントリーでは、CircleCIのテスト結果をSlackに通知する方法について解説します。
Slack Integrationsの設定手順
CircleCIからSlackへ通知するためには、以下の手順が必要です。
- Slackワークスペースにアプリをインストールし、OAuthトークンを発行する
- 発行されたトークンをCircleCIのコンテキストに登録する
- CircleCIのワークフロー内に通知処理を実装する
ちなみに以前からCircleCIを利用されている方は、このSlackアプリとWebhookを利用して連携を行っていたかもしれません。ですが現在では、この方法は推奨されておらず、本エントリーで紹介するOrbを使う必要があるようです。
以下にて手順を解説します。なお具体的な手順はドキュメントにも詳しく記載されていますので、こちらも参照してください。
Slackワークスペースにアプリをインストールし、OAuthトークンを発行する
まずSlackのYour Appsを開き、Create New Appをクリックしてください。

今回はゼロからスクラッチするので、From scratchを選択します。

アプリの名前と、インストールするワークスペースを決めます。ここでは名前をCircleCI-testとしました。

アプリの設定画面に遷移しますので、左ペインからOAuth & Permissionsをクリックしてください。

画面を下へスクロールさせると、Scopesという項目の中にBot Token Scopesという項目があります。Add an OAuth Scopeをクリックして、アプリに必要な権限をつけましょう。CircleCIからの通知に必要な権限はchat:write、files:write、chat:write.publicの3つです。

今度は左ペインのInstall Appをクリックしてから、Install to Workspaceをクリックします。

インストールの確認画面が表示されます。インストール先と権限を確認したら、許可するをクリックしてください。

インストールが完了すると、OAuthトークンが表示されます。この文字列を控えておきましょう。

これでSlack側の準備は完了です。
発行されたトークンをCircleCIのコンテキストに登録する
続いてCircleCIのワークフロー内から、先ほど発行されたトークンを利用できるようにします。これにはコンテキストと呼ばれる仕組みを利用するのが一般的です。コンテキストは組織内の各プロジェクトで、環境変数を安全に共有できる仕組みです。
CircleCIにログインし、Organization Settings→Contextsを開いてCreate Contextをクリックします。

コンテキストの名前を決めましょう。ここではslack-tokenとしました。Create Contextをクリックします。

先ほどのコンテキスト一覧画面に、作成したslack-tokenコンテキストが表示されますので、コンテキスト名をクリックしてください。環境変数の登録画面に遷移します。Add Environment Variableをクリックします。

この画面で環境変数名と値を入力します。まずSLACK_ACCESS_TOKENという名前の環境変数を作成し、値には先ほど発行されたトークンを入力します。また同様にSLACK_DEFAULT_CHANNELという環境変数を作成し、デフォルトで通知を行うチャンネルIDを設定しておくとよいでしょう。なおここで設定するのは表示上のチャンネル名ではなく、チャンネルIDであることに注意してください。Slackのデスクトップアプリを利用しているなら、該当のチャンネル名を右クリックしてリンクをコピーし、得られるURLの末尾にある文字列がチャンネルIDです*1。

コンテキストはSlackのトークンだけでなく、AWSのアクセスキーやk8sのクレデンシャルなど、様々な機密情報を安全に保管するために利用できます。またコンテキストへのアクセスは、GitHubのOrganization内に設けたTeamsごとに制限することができます。デフォルトでコンテキストは全員が読み取ることが可能なため、他プロジェクトのメンバーに見えてはならない情報は、アクセス制限をかけることも検討してください。
CircleCIのワークフロー内に通知処理を実装する
それでは実際に、CIのワークフロー内からSlackへ通知を発行してみましょう。前回のエントリーでも使った、ShellcheckのCIジョブをそのまま流用することにします。Slack通知に対応したconfig.ymlは以下の通りです。
version: 2.1 orbs: # このワークフローでは、shellcheckとslackのふたつのOrbを利用する shellcheck: circleci/shellcheck@3.0.0 slack: circleci/slack@4.8.1 jobs: test: docker: # CIジョブを実行するコンテナイメージは、CircleCIのベースイメージ - image: 'cimg/base:2022.02' steps: # コードのチェックアウト - checkout # shellcheckを実行する - shellcheck/check: dir: ./ pattern: '*.sh' # shellcheckが失敗した場合(event: fail)に失敗通知を送信する - slack/notify: template: basic_fail_1 event: fail # shellcheckが成功した場合(event: pass)に成功通知を送信する - slack/notify: template: basic_success_1 event: pass workflows: my_workflow: jobs: - test: # このジョブでslack-tokenコンテキストを利用する context: - slack-token
Orbとはプログラミング言語に例えるなら、外部ライブラリをインポートして関数を使えるようにする機能に該当します。Orbを使えば様々なジョブやコマンドを再利用できます。また今回のSlack通知のような、一般的な機能は公式にOrb化され公開されているため、自分で実装する必要がありません。ここではOrbを利用することで、スクリプトの構文チェックを行うshellcheck/checkや、Slackに通知を行うslack/notifyというコマンドを利用可能にしています。
またワークフロー内では、Slackのトークンを読み込むため、コンテキストにアクセスする設定を行っています。context: コンテキスト名を指定しておけば、該当ジョブ内では環境変数にコンテキストの内容が自動的に読み込まれます。なおワークフロー内に複数のジョブがある場合、それぞれのジョブは独立したコンテナ内で実行されるため、コンテキストを利用する必要があるすべてのジョブそれぞれに、contextの記述を追加する必要がある点に気をつけてください。

このように、ワークフローの結果がSlackに通知できるようになりました。またslack/notifyコマンドは、通知を自由にカスタマイズすることも可能です。
さあ、君だけの最強の通知を作り上げて、ライバルに差をつけよう!!
*1:https://hoge.slack.com/archives/XXXXX の「XXXXX」の部分です。
