古いCircleCI Slack通知からの移行の道
この記事は、CircleCI Advent Calendar 2021 の3日目です。
昨日は、2021年のChangelogから振り返るCircleCI - その2 でした。そんなのあったのか、と気付かされる内容だったので、その3も楽しみです。
この記事でやることについて、3行まとめ
- 自社用のSlackアプリを登録する
- Orbsを利用してSlack通知のための設定を投入する
- 昔からあるSlack通知設定について、APIを直接コールして停止する
ことはじめ
CircleCI を使い始めて、早5年。途中で、プランを Performance プランに変えたり、CircleCI 2.x にバージョンがあがったりなど、対応しながら使っています。自分たちの開発チームでは、20プロジェクトほどのビルドや、デプロイをCircleCI上で行っています。
そんなこんなで昔から使っているため、もとからCircleCIの機能として用意されていたSlack Appを使っていました。というより、現在も、ほとんどがこの設定で動いています。
すでにヘルプ文章等には残ってなかったので、以下の記事や、Qiita等の古い記事を確認すると古い画面を確認することができます。
しかし、去年(2020年)の10月くらいだったかに、UI変更があったタイミングで、かつてCircleCI側にあった、SlackのWebHookを入力する画面が消えてしまいました。消えてしまったのに機能自体は今まで通り動いています。一方で、Orbsを利用したSlack通知を行うことがドキュメントに記載されています。今までに比べると、より柔軟な設定が可能になっていますし、Slack以外の対応等を考えると、方向性としては正しそうです。
これは、いつ今までの設定が完全に停止されるかはわからないけど、止まるのも時間の問題かな。。という不安と、そもそもどうやって止めるか。というのがぱっと画面上ではわからなかったため、同じような課題に詰まった人のために小ネタとして備忘録を残しておきます。
Orbsについて
この記事では、CircleCI Slack Orbs の 4.5.0
をベースに説明します。かつて出されていた3系では、環境変数 SLACK_WEBHOOK
を登録する仕組みだったようですが、現在の最新版では、自前のアプリを登録して、そのアクセストークンを環境変数 SLACK_ACCESS_TOKEN
として登録する必要があるなど、実装が変わっているようです。
古い記事を読むときは要注意ですね!
Slackのアプリを作成する
現状のOrbsは、CircleCIがSlackアプリを管理するのではなく、自前でSlackアプリを作成する必要があるので、まずはSlackアプリを作成しましょう。
基本的には、Orbsのドキュメントの流れに従うだけです。
https://api.slack.com/apps に行き、Create New App
を押下します。
From scratch
を選びます
アプリ名(わかりやすい文字) と、Slackのワークスペースを設定します
Permission (権限) の設定をします
Bot Token Scopes の設定から3つのOAuth Scopeを追加します。
chat:write
chat:write.public
files:write
ここまでの設定が終わったら、Slackワークスペースにインストールします。アプリの Install Appページから、Install to Workspace
を押下します。
これでBot用のアクセストークンが手に入ります。後々使うので今は控えておきましょう。
Botの名前などは Basic Information の Display Information から編集できるので、ここは雰囲気にあわせていい感じにしておくとよいと思います。
Orbsを利用してSlack通知のための設定を入れる
旧Slack通知の仕組み(Orbsを使わない場合)は、ワークフロー・コミットログなどに加え、失敗した場合は、代表的な失敗したJob名がまとめて出るような形になっています。
一方で、Orbsで設定する場合は、Jobごとに通知設定を行うため、今までの挙動とは異なります。
コンテキストでSlackの設定を共通化する
複数プロジェクトに横断するときは、いちいちそれぞれのプロジェクトでSlackの環境変数を設定するのは面倒です。そこで、コンテキスト を利用して、複数プロジェクトで同じ設定を使い回せるようにしましょう。
CircleCI画面の左のOrganization Settings に行きます
Create Context
から新たな設定を追加します
名前は、Slack通知とわかりそうなものにしておきましょう。
Add Environment Variable
から、アプリのインストールにより生成された Bot Access Token を SLACK_ACCESS_TOKEN
という環境変数名で保存します。
もう一つ、SLACK_DEFAULT_CHANNEL
という名前で、通知先のSlackチャンネル名を保存します。(特に #
は不要)
とりあえず、用意されているテンプレートを使う
Slack Orbs には、最初から、basic_fail_1
というテンプレートと、basic_success_1
というテンプレートが用意されていますので、まずはそれを使うと良さそうです。
version: 2.1
orbs:
# .. いろいろ ..
slack: circleci/slack@4.5.0
jobs:
build:
# .. いろいろ ...
steps:
# .. いろいろ ..
# 失敗したとき
- slack/notify:
event: fail
template: basic_fail_1
# うまくいったとき
- slack/notify:
event: pass
template: basic_success_1
workflows:
build_test_deploy:
jobs:
- build:
context:
# 先程用意したコンテキストを利用する
# このジョブ内ではコンテキストに登録された環境変数が使える
- slack-notification
これで、ジョブが成功 or 失敗すると設定したSlackチャンネルに通知が届くようになりました。
もうちょっとスリムに & 古い設定に近いフォーマットに
デフォルトのテンプレートは今までのものと比べると少し高さを使います。上がOrbsによるもので、下がCircleCIにもともとあった機能のものです。並んだときに少し見にくかったりを解消するために、自前でSlackへの投稿ペイロードを作ってみます。
Slack の BlockKit Builder を使いながら、いい感じの内容を作っていきます。
また、複数のJobで利用することを想定して、commandとして定義します。
version: 2.1
orbs:
# .. いろいろ ..
slack: circleci/slack@4.5.0
# 独自のコマンドを定義
commands:
slack_notify:
description: 'Send success / fail notification to Slack'
steps:
# CIRCLE_SHA1が長いので短くする加工をしたり、コミットメッセージを環境変数として扱えるようにしたり
- run:
name: Setup notificatoin related
command: |
echo "export SHA1_SHORT=${CIRCLE_SHA1:0:7}" >> $BASH_ENV
echo "export COMMIT_MSG='$(git log -1 HEAD --pretty=format:%s | sed s/\'/\\\\\'/g)'" >> $BASH_ENV
- slack/notify:
event: fail
# カスタムなSlackメッセージペイロードを custom で指定する
custom: |
{
"blocks": [{
"type": "section",
"text": {
"type": "mrkdwn",
"text": ":red_circle: Filed: ${CIRCLE_USERNAME}'s <https://circleci.com/workflow-run/${CIRCLE_WORKFLOW_ID}|workflow> (<${CIRCLE_BUILD_URL}|${CIRCLE_JOB} ${CIRCLE_NODE_INDEX}>) in <https://circleci.com/gh/${CIRCLE_PROJECT_USERNAME}/workflows/${CIRCLE_PROJECT_REPONAME}|${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}> (<https://circleci.com/gh/${CIRCLE_PROJECT_USERNAME}/workflows/${CIRCLE_PROJECT_REPONAME}/tree/${CIRCLE_BRANCH}|${CIRCLE_BRANCH}>)\n${COMMIT_MSG} (<https://github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commit/${CIRCLE_SHA1}|${SHA1_SHORT}>) by ${CIRCLE_USERNAME})"
}
}]
}
- slack/notify:
event: pass
custom: |
{
"blocks": [{
"type": "section",
"text": {
"type": "mrkdwn",
"text": ":white_check_mark: Success: ${CIRCLE_USERNAME}'s <https://circleci.com/workflow-run/${CIRCLE_WORKFLOW_ID}|workflow> (<${CIRCLE_BUILD_URL}|${CIRCLE_JOB} ${CIRCLE_NODE_INDEX}>) in <https://circleci.com/gh/${CIRCLE_PROJECT_USERNAME}/workflows/${CIRCLE_PROJECT_REPONAME}|${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}> (<https://circleci.com/gh/${CIRCLE_PROJECT_USERNAME}/workflows/${CIRCLE_PROJECT_REPONAME}/tree/${CIRCLE_BRANCH}|${CIRCLE_BRANCH}>)\n${COMMIT_MSG} (<https://github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commit/${CIRCLE_SHA1}|${SHA1_SHORT}>) by ${CIRCLE_USERNAME})"
}
}]
}
jobs:
build:
# .. いろいろ ...
steps:
# .. いろいろ ..
- slack_notify
workflows:
build_test_deploy:
jobs:
- build:
context:
- slack-notification
無駄に頑張ってみましたが、リンク等含めて結構いい感じになりまいした。
ジョブごとに出るので、ワークフロー上で複数ジョブを実行されると、次々に出てきて動いている感ありますね。(並列ジョブがある場合、その並列数分の通知が来るわけです。)
Orbsのジョブを使っている場合
aws-ecr Orbs を利用して、イメージをECRにプッシュする場合などは、build-and-push-image
Job を使うと便利そうですが、こちらを使っている場合はジョブの失敗時のSlack通知を行うことができません。
Jobではなく、Commandが定義されている場合は、そちらに変えましょう。
を使っていたのですが、それぞれコマンドでも置き換えることができたのでなんとかなりました。
version: 2.1
orbs:
aws-ecr: circleci/aws-ecr@7.3.0
workflows:
build_test_deploy:
jobs:
# .. いろいろJobがある ..
- aws-ecr/build-and-push-image:
name: build-staging
repo: "something"
tag: "${CIRCLE_SHA1}"
requires:
- lint
- test
filters:
branches:
only:
- staging
orbs:
slack: circleci/slack@4.5.0
aws-ecr: circleci/aws-ecr@7.3.0
commands:
# .. slack_notify を定義する ..
# .. 先程説明したものと同じなので省略 ..
jobs:
build-staging:
executor: aws-ecr/default
steps:
- aws-ecr/build-and-push-image:
repo: "staging"
tag: "${CIRCLE_SHA1}"
- slack_notify
workflows:
build_test_deploy:
jobs:
# .. いろいろJobがある ..
- build-staging:
requires:
- lint
- test
filters:
branches:
only:
- staging
古い設定の削除
今のままだと、Orbsによる通知と、旧設定のものが両方届いてしまうので、旧設定を解除します。しかし、画面がないのにどのように解除するのでしょうか? ということで、ヘルプを確認すると、APIを直接コールして解除せよ。とのことでした。。
パーソナルアクセストークンの取得
Create New Token
から、トークンを作ります。トークンは解除に使うので取っておきます。
解除
に従い、特定のプロジェクトの slack_webhook_url
を空文字に設定します。
curl -X PUT 'https://circleci.com/api/v1.1/project/{vcs}/{org}/{project}/settings' \
-H 'Content-Type: application/json' \
-H "Circle-Token: $CIRCLE_TOKEN" \
--data-binary '{"slack_webhook_url":""}'
これで、もともとあったWebHook設定での通知が来なくなります。
まとめ
率直に言うと、最初のセットアップ周りに関しては今までよりやること多い!!というのはありますが、通知方法をカスタマイズするのにはかなり良さそうはあります。
ひとまず、通知だけしたいという場合は、デフォルトで用意されているテンプレートを使うだけでも十分ではありそうなので、どんどん置き換えていったほうが良さそうです。
一方で、1ワークフローにつき、通知1つだけ (失敗したか、成功したかのみを)出したい。というケースでは、FAQを見る限り難しそうでした。
ワークフローの途中でジョブが失敗しても、絶対に最後に実行するジョブ的なものが定義できて(finnaly
的な) 、失敗したジョブ情報など、ワークフロー実行結果などがパラメータなどで参照できるとよいのだろうなぁ。とは感じています。
この点は、昨日のアドベントカレンダーの記事でも紹介されていた、WebHookを利用して対応できるのでしょうか。(まだやってません。)
あと、CircleCI Tシャツはほしい (観光地Tシャツと、技術イベント系のTシャツだけを着て生きる人間でありまして、オンラインイベント時代はTシャツが不足するのでした。。)
明日は、しーばさんがSpring Bootアプリの自動テストを書いてくれると思われます。
Discussion