こんにちは!いつも開発お疲れ様です。あなたの頼れる先輩エンジニアです。
突然ですが、皆さんはCircleCIでテストが落ちたとき、どのように気づいていますか?
「メールを開いて、リンクをクリックして、CircleCIのダッシュボードにログインして、ビルドログをスクロールしてようやくエラーを確認する……」
「うーん、これ、もっと一瞬でエラーの原因までわかったら最高なのに!」
そう思ったことはありませんか?
標準のSlack連携やDiscord通知も便利ですが、ただ「Success」「Failed」とだけ書かれた無機質な通知では、デバッグのために結局毎回ブラウザを開くことになります。
そこで今回は、CircleCIのパイプラインから直接API(Webhook)を叩き、テストの成否、ビルド時間、コミットメッセージ、さらにはエラー箇所のサマリーまでを美しく整理してSlackやDiscordに詳細通知する「カスタムWebhook実装術」をお届けします。
この記事を最後まで読めば、初心者の方でも「かゆいところに手が届く極上の通知システム」を自作できるようになります。毎日の開発効率が劇的にアップしますので、ぜひ一緒に手を動かしながらマスターしていきましょう!
—
1. なぜ「標準の通知」では不十分なのか?
まずは、なぜ私たちがわざわざ「カスタムWebhook」を実装するのか、その思想を理解しておきましょう。
CircleCIには公式のSlack Orbなどが用意されています。これは導入が簡単な反面、以下のような細かいカスタマイズが困難です。
- 情報の取捨選択ができない:「誰が」「どのコミットで」「どのテストを落としたのか」を1画面に収めたいのに、レイアウトが固定されている。
- Discordへの対応が弱い:開発チームによってはDiscordをメインのチャットツールにしているケースも多いですが、公式のサポートがSlackほど手厚くありません。
- 「デバッグのヒント」を載せられない:失敗したテストの件数や、エラーログの最後の数行を通知に載せることができない。
今回実装するカスタムWebhookを使えば、通知のデザインを自由自在にコントロールでき、Slackの「Block Kit」やDiscordの「Embeds」というリッチなレイアウト機能を極限まで活かすことができます。
—
2. 全体像と仕組み
今回の仕組みは非常にシンプルです。
[CircleCI パイプライン実行]
│
├──> [テスト実行 (Pass / Fail)]
│
└──> [通知用シェルスクリプト起動]
│
├──> CircleCIの環境変数やテスト結果を収集
└──> JSONデータを構築して Webhook URL へ POST 送信
│
▼
[Slack / Discord] に美しいカード型で着信!
特別なツールは必要ありません。CircleCIのコンテナ内で最初から使える `curl` と `jq`(JSONを整形するコマンド)だけで、このリッチな通知を実現します。
—
3. 最も重要な基礎セットアップ(準備編)
まずは、通知の宛先となるSlackまたはDiscordの「Webhook URL」を取得し、CircleCIに安全に登録しましょう。
ステップ1:Webhook URLの取得
Slackの場合
1. Slackのワークスペースで、通知を送信したいチャンネルの「設定」または「アプリを追加」を開きます。
2. 「Incoming WebHooks」というアプリを検索して追加します。
3. 通知先のチャンネルを選択し、「Incoming Webhook インテグレーションの追加」をクリックします。
4. 発行された `https://hooks.slack.com/services/…` で始まるURLをコピーしておきます。
Discordの場合
1. Discordのサーバーで、通知用のチャンネルの「チャンネルの設定(歯車マーク)」を開きます。
2. 「連携サービス」を選び、「ウェブフックを作成」をクリックします。
3. Webhookの名前(例: `CircleCI Bot`)を設定し、「ウェブフックURLをコピー」をクリックします。
ステップ2:CircleCIへの環境変数登録
WebhookのURLは、他人に知られてはいけない極秘情報(認証情報)です。絶対にソースコードに直接書いてはいけません(GitHubに公開されて悪用されるリスクがあります)。
安全に保管するために、CircleCIの環境変数に登録します。
1. CircleCIのダッシュボードを開き、該当するプロジェクトの 「Project Settings」 をクリックします。
2. 左メニューから 「Environment Variables」 を選択します。
3. 「Add Environment Variable」 をクリックし、以下のように登録します。
- Name: `WEBHOOK_URL`
- Value: 先ほどコピーしたSlackまたはDiscordのWebhook URL
これで下準備は完璧です!
—
4. 極限のカスタム通知:CircleCI設定ファイルの実装
それでは、`.circleci/config.yml` を書いていきましょう。
今回は、テストが「成功したとき」と「失敗したとき」で通知内容を出し分け、かつビルド時間やコミット情報を美しくパッキングする設定を作成します。
`.circleci/config.yml` の完成サンプル
version: 2.1
ジョブの定義
jobs:
test_and_notify:
docker:
- image: cimg/base:stable # 軽量なLinux環境を使用
steps:
- checkout
# 1. 擬似的なテスト実行ステップ(ここでテストを行います)
- run:
name: Run Tests
command: |
echo “テストを実行中…”
# ここに実際のテストコマンド(npm test, pytest 等)を書きます。
# 今回は動作確認のため、10%の確率でランダムに失敗するスクリプトにしています。
if [ $((RANDOM % 10)) -eq 0 ]; then
echo “エラー: 特定のテストケースが失敗しました!” && exit 1
fi
echo “すべてのテストが正常に通過しました。”
# 2. テスト成功時の詳細通知
- run:
name: Notify Success to Slack/Discord
when: on_success # 前のステップが「成功」したときのみ実行
command: |
# 送信用Payloadの作成(Slack/Discord共通で使えるシンプルなテキスト、またはDiscord用Embeds)
# ここでは汎用性の高いDiscordのEmbedsレイアウトを例にします。
TIMESTAMP=$(date -u +”%Y-%m-%dT%H:%M:%SZ”)
# JSONの組み立て
JSON_PAYLOAD=$(jq -n \
–arg title “🟢 Build Success!” \
–arg desc “パイプラインが正常に完了しました。” \
–arg repo “$CIRCLE_PROJECT_REPONAME” \
–arg branch “$CIRCLE_BRANCH” \
–arg commit “$CIRCLE_SHA1” \
–arg author “$CIRCLE_USERNAME” \
–arg url “$CIRCLE_BUILD_URL” \
–arg time “$TIMESTAMP” \
‘{
embeds: [{
title: $title,
description: $desc,
url: $url,
color: 3066993, # 緑色 (Hex: #2ecc71)
timestamp: $time,
fields: [
{ name: “Repository”, value: $repo, inline: true },
{ name: “Branch”, value: $branch, inline: true },
{ name: “Author”, value: $author, inline: true },
{ name: “Commit Hash”, value: ($commit | sub(“.{32}$”; “”)), inline: false }
]
}]
}’)
# Webhookの送信
curl -H “Content-Type: application/json” -X POST -d “$JSON_PAYLOAD” $WEBHOOK_URL
# 3. テスト失敗時の詳細通知
- run:
name: Notify Failure to Slack/Discord
when: on_fail # 前のステップが「失敗」したときのみ実行
command: |
TIMESTAMP=$(date -u +”%Y-%m-%dT%H:%M:%SZ”)
JSON_PAYLOAD=$(jq -n \
–arg title “🔴 Build Failed!” \
–arg desc “テストまたはビルドステップでエラーが発生しました。至急確認してください。” \
–arg repo “$CIRCLE_PROJECT_REPONAME” \
–arg branch “$CIRCLE_BRANCH” \
–arg commit “$CIRCLE_SHA1” \
–arg author “$CIRCLE_USERNAME” \
–arg url “$CIRCLE_BUILD_URL” \
–arg time “$TIMESTAMP” \
‘{
embeds: [{
title: $title,
description: $desc,
url: $url,
color: 15158332, # 赤色 (Hex: #e74c3c)
timestamp: $time,
fields: [
{ name: “Repository”, value: $repo, inline: true },
{ name: “Branch”, value: $branch, inline: true },
{ name: “Author”, value: $author, inline: true },
{ name: “Commit Hash”, value: ($commit | sub(“.{32}$”; “”)), inline: false }
]
}]
}’)
curl -H “Content-Type: application/json” -X POST -d “$JSON_PAYLOAD” $WEBHOOK_URL
ワークフローの定義
workflows:
version: 2
build_and_test:
jobs:
- test_and_notify
—
5. ここがプロの技!設定ファイルの解説とポイント
この設定ファイルには、実務でトラブルを防ぎ、かつ開発を快適にするための「極意」がいくつか詰まっています。
① `jq` コマンドによる安全なJSON組み立て
シェルスクリプトでJSONを作るとき、`echo “{\”text\”: \”$VAR\”}”` のように文字列連結をしてしまいがちです。しかし、これだとコミットメッセージ等に `”`(ダブルクォーテーション)や改行が含まれていた場合にJSONが壊れて送信エラーになります。
ここでは `jq -n –arg name “value” …` を使うことで、特殊文字を自動的にエスケープした安全なJSONを生成しています。
② `when: on_success` と `when: on_fail` の使い分け
CircleCIはデフォルトでは、途中のステップが失敗するとそれ以降のステップをすべてスキップします。
しかし、`when: on_fail` を指定したステップは、「手前のステップが失敗したときだけ」実行されます。これにより、条件分岐(if文)を複雑に書くことなく、成功・失敗の出し分けがスマートに実現できます。
③ コミットハッシュの短縮化
Gitのフルコミットハッシュ(40文字)はチャット画面で見ると長すぎて不格好です。
`($commit | sub(“.{32}$”; “”))` という `jq` のフィルタ処理により、ハッシュの先頭8文字だけをスマートに切り出しています。
—
6. 【レイアウト別】デバッグ効率を最大化するテンプレート
チャットツールに合わせて、さらにデザインを磨き上げましょう。コピペしてそのまま使える2パターンの極上テンプレートを用意しました。
パターンA:Slack(Block Kit)用テンプレート
Slackで最も見やすく、ボタンなども配置できるリッチな形式です。
{
“blocks”: [
{
“type”: “header”,
“text”: {
“type”: “plain_text”,
“text”: “🚨 CircleCI Build Failed”,
“emoji”: true
}
},
{
“type”: “section”,
“fields”: [
{ “type”: “mrkdwn”, “text”: “Project:\nMy-Awesome-App” },
{ “type”: “mrkdwn”, “text”: “Branch:\nmain” }
]
},
{
“type”: “section”,
“text”: {
“type”: “mrkdwn”,
“text”: “Author: @developer\nCommit: `a1b2c3d4` – テストの修正”
}
},
{
“type”: “actions”,
“elements”: [
{
“type”: “button”,
“text”: {
“type”: “plain_text”,
“text”: “View Build Log”,
“emoji”: true
},
“style”: “danger”,
“url”: “https://circleci.com/gh/your-org/your-repo/123”
}
]
}
]
}
パターンB:Discord(Embeds)用テンプレート
Discordのカード型通知です。色をステータスごとに変えることで、視覚的に一瞬で状況を把握できます。
{
“embeds”: [
{
“title”: “🟢 Build Passed!”,
“description”: “すべてのテストが正常に通過しました。デプロイの準備が整いました。”,
“url”: “https://circleci.com/…”,
“color”: 3066993,
“fields”: [
{ “name”: “Branch”, “value”: “release/v1.0”, “inline”: true },
{ “name”: “Triggered by”, “value”: “Senior-Dev”, “inline”: true }
]
}
]
}
—
7. 動作確認(Hello World)とトラブルシューティング
セットアップが完了したら、実際にGitHubなどのリポジトリにプッシュしてCircleCIを動かしてみましょう!
正常に動いた時のワクワク感
プッシュ後、数秒〜数十秒すると、SlackまたはDiscordに以下のような美しい通知が届くはずです。
- Slack/Discordの画面に、あなたのコミット情報と、CircleCIへの直リンクボタンが表示されれば大成功です!
もし通知が届かない時のチェックリスト
1. 「環境変数は正しく設定されていますか?」
CircleCIの管理画面で `WEBHOOK_URL` の綴りが間違っていないか、値の末尾に不要なスペースや改行が入っていないか確認してください。
2. 「`jq` コマンドが入っていないイメージを使っていませんか?」
もしベースイメージ(`cimg/base` など)以外の自作コンテナを使う場合、`jq` がインストールされていないとエラーになります。その場合は、事前に `sudo apt-get install jq` などを実行するか、CircleCI公式の便利イメージ(`cimg/…` シリーズ)を使用してください。
3. 「JSONのフォーマットエラーが出ていませんか?」
CircleCIのビルドログを開き、`curl` コマンドを実行しているステップの出力を確認してください。`{“message”: “Invalid Payload”}` などのエラーが出ている場合、JSONのカッコの閉じ忘れや、変数の中身が空になっている可能性があります。
—
まとめ:ここから始まる、最高の自動化ライフ
お疲れ様でした!
今回作成したカスタムWebhookは、ただの「通知」に留まりません。
これを応用すれば、
- 「失敗したテストのログの末尾10行を自動で抜き出して通知に載せる」
- 「ビルドにかかった時間を計算して、前回のビルドと比較して遅くなっていたら警告する」
といった、チーム独自の「超お役立ちBot」へと進化させることができます。
「CI/CDの通知なんて、ただ動けばいい」と思われがちですが、ここの体験を極限まで高めることが、チーム全体の開発リズムを整え、バグの早期発見へと繋がります。
ぜひ今回のコードをベースに、皆さんのチームに合わせた最強の通知カスタマイズを楽しんでみてくださいね。
また次のステップでお会いしましょう。Happy Integrating!