⚠️
GitHub ActionsのCI失敗をSlackに通知する
みなさん、GitHub Actionsが失敗したときの通知はどうしているでしょうか?正直なところ「こうするのがベスト!」というのがいまいちわからず、結局のところ自前で組む結論に至っている今日このごろです。
はじめに
GitHub Actionsを使用したCIプロセスでは、ジョブの失敗を迅速に検知することが重要です。が、デフォルトではこれをいい感じに設定できる方法がありません(少なくとも私は発見できていません)。本記事では、Slackを使用して失敗通知を実装する方法を説明します。
実際の作り方や詳しい画面に関しては動画でウォークスルーしているので、時間があれば見てみてください。
結果だけ知りたい人は下記リポジトリを参考にしてもらえたらと思います。
Slack appの準備
まず、Slack appを作成し、Webhook URLを取得します。
- Slackの管理画面から新しいappを作成します。
- 「Incoming Webhooks」機能を有効にします。
- Webhookを追加し、通知を送信するチャンネルを選択します。
- 生成されたWebhook URLを保存します(これは後で使用します)。
GitHub Actionsワークフローの基本設定
次に、サンプルのGitHub Actionsのワークフローを設定し、意図的に途中でエラーを発生させておきます。
name: Test Job
on: push # 確認しやすくしたいのでpushしたら必ず実行させる
jobs:
job1:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run tests
run: |
echo "Running tests1..."
exit 0
job2:
runs-on: ubuntu-latest
needs: job1
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run tests
run: |
echo "Running tests2..."
exit 1 # ←意図的に失敗させる
job3:
runs-on: ubuntu-latest
needs: job2
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run tests
run: |
echo "Running tests3..."
exit 0
Slackへの通知ジョブの実装
失敗時にSlackに通知を送るジョブを実装します。
- 新しいジョブ「notify-slack」を追加します。
-
if
条件を使用して、前のジョブが失敗またはスキップされた場合にのみ実行されるようにします。
notify-slack:
runs-on: ubuntu-latest
needs: job3 # job3に依存させます(job1→job2→job3は直列なので、job3だけ依存すればOK)
if: ${{ always() && needs.job3.result == 'failure' || needs.job3.result == 'skipped' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Slack Notification(failure)
uses: ./.github/actions/notify-failure-to-slack
with:
slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }}
message: 'ほげほげジョブに失敗しました!'
- Slack通知の部分は再利用したいので、別Actionとして作ります
-
.github/actions/notify-failure-to-slack/action.yml
に作ります
name: Notify Action Failure to Slack
description: 'Notify Slack when a workflow fails'
inputs:
slack_webhook_url:
description: 'Slack webhook URL'
required: true
message:
description: 'Message to send to Slack'
required: true
default: 'Actionが失敗しました'
runs:
using: composite
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create JSON payload # Slackへ送るJSONは独立したStepで作ります
shell: bash
run: |
echo '{
"blocks": [
{
"type": "rich_text",
"elements": [
{
"type": "rich_text_section",
"elements": [
{
"type": "emoji",
"name": "warning"
},
{
"type": "text",
"text": "${{ inputs.message }}"
},
{
"type": "emoji",
"name": "warning"
}
]
}
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "<https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}|GitHub Actions>"
}
}
]
}' > payload-slack-content.json
- name: Send custom JSON data to Slack workflow
id: slack
uses: slackapi/slack-github-action@v1.26.0
with:
# 前のステップで作ったJSONを送ります
payload-file-path: './payload-slack-content.json'
env:
SLACK_WEBHOOK_URL: ${{ inputs.slack_webhook_url }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
このActionを作っておくことで、ローカルからは以下のようにどのJobからも呼べるようになります。
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Slack Notification(failure)
uses: ./.github/actions/notify-failure-to-slack
with:
slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }}
message: 'ほげほげジョブに失敗しました!' # カスタムメッセージに変えられる
これでCI失敗時に以下のように通知を受け取ることができ、さらに対象となるGitHub Actionsにリンクから飛ぶこともできます。
まとめ
この実装により、以下のような利点が得られます:
- CIジョブの失敗を迅速に検知できる
2. 再利用可能なActionとして実装することで、複数のワークフローで簡単に使用できる
ただし、この実装にも制限事項があって、「各ワークフローに個別に通知ジョブを追加する必要がある」というものです。一箇所で全部キャッチしてくれると楽なのですが。。。その方法は見つけられていません。(どなたか知っていたら教えて下さい)
Discussion