1. はじめに

GitHub Actionsを用いてECSにデプロイしています。デプロイ結果をSlackに通知するGitHub Actionsの実装を紹介します。

通知には、成功・失敗のステータスだけでなく、デプロイ所要時間や変更されたファイル一覧も含め、チーム開発で役立つ情報を整形して送信しています。

2. 通知のサンプル

GitHubActionsが動くと、以下のようにslackに通知されます。

3. GitHubActionsの流れ

以下のように動きます。それぞれのステップごとにGitHub Actionsの定義を解説します。

3.1. デプロイ所要時間を計算

このステップでは、deploy-start ステップで記録しておいたUnixタイムスタンプとの差分から、デプロイにかかった分・秒単位の所要時間を計算します。結果は後続のステップで使用するため、GITHUB_OUTPUT に出力します。

- name: Calculate deploy duration
  id: deploy-duration
  if: always()
  run: |
    end_time=$(date -u +%s)
    duration=$((end_time - ${{ steps.deploy-start.outputs.start_time }}))
    minutes=$((duration / 60))
    seconds=$((duration % 60))
    echo "duration=${minutes}分${seconds}秒" >> $GITHUB_OUTPUT    
yaml

3.2. コミットの変更内容を取得

最新のコミット(HEAD)と一つ前のコミット(HEAD~1)との差分を取得し、変更ファイル数(changed_files)最大5件の変更ファイル一覧(files_list)を整形して出力します。

- name: Get commit changes
  id: commit-changes
  if: always()
  run: |
    changed_files=$(git diff --name-only HEAD~1 HEAD | wc -l)
    echo "changed_files=${changed_files}" >> $GITHUB_OUTPUT
    
    files_list=$(git diff --name-only HEAD~1 HEAD | head -5 | sed 's/^/• /' | tr '\n' '\n')
    echo "files_list<<EOF" >> $GITHUB_OUTPUT
    echo "$files_list" >> $GITHUB_OUTPUT
    echo "EOF" >> $GITHUB_OUTPUT    
yaml

3.3. Slack通知の送信

Slack通知はSlack Block Kit形式で整形され、視認性の高いレイアウトになります。通知には以下の情報が含まれます。

最低限必要なのは、成功したか失敗したかのステータスです。そして、成功や失敗したステータスについて詳細に参照するためのGitHubへのリンクを入れるのも必要だと思います。

  • 成功 or 失敗のステータス(アイコン付き)
  • 実行者、ブランチ名
  • デプロイ所要時間、変更ファイル数
  • コミットメッセージと変更ファイル一覧
  • コミットとGitHub Actionsのワークフローへのリンク
- name: Slack Notification
  if: always()
  env:
    STATUS_ICON: ${{ job.status == 'success' && '✅' || '❌' }}
    STATUS_TEXT: ${{ job.status == 'success' && 'デプロイ成功' || 'デプロイ失敗' }}
    STATUS_COLOR: ${{ job.status == 'success' && 'good' || 'danger' }}
    DEPLOY_STATUS: ${{ job.status == 'success' && 'ECSへのデプロイが完了しました!' || 'ECSへのデプロイに失敗しました。' }}
    COMMIT_URL: ${{ github.event.head_commit.url }}
    WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
    DEPLOY_DURATION: ${{ steps.deploy-duration.outputs.duration }}
    CHANGED_FILES: ${{ steps.commit-changes.outputs.changed_files }}
    FILES_LIST: ${{ steps.commit-changes.outputs.files_list }}
  uses: slackapi/slack-github-action@v2.1.1
  with:
    webhook: ${{ env.SLACK_WEBHOOK_URL }}
    webhook-type: webhook-trigger
    payload: |
      {
        "text": "ECSデプロイ通知",
        "attachments": [
          {
            "color": "${{ env.STATUS_COLOR }}",
            "blocks": [
              {
                "type": "section",
                "text": {
                  "type": "mrkdwn",
                  "text": "${{ env.STATUS_ICON }} *${{ env.STATUS_TEXT }}*: ${{ env.DEPLOY_STATUS }}"
                }
              },
              {
                "type": "section",
                "fields": [
                  { "type": "mrkdwn", "text": "*実行者*\n${{ github.actor }}" },
                  { "type": "mrkdwn", "text": "*ブランチ*\n${{ github.ref_name }}" },
                  { "type": "mrkdwn", "text": "*デプロイ時間*\n${{ env.DEPLOY_DURATION }}" },
                  { "type": "mrkdwn", "text": "*変更ファイル数*\n${{ env.CHANGED_FILES }}件" }
                ]
              },
              {
                "type": "section",
                "text": {
                  "type": "mrkdwn",
                  "text": "*コミットメッセージ*\n${{ github.event.head_commit.message }}"
                }
              },
              {
                "type": "section",
                "text": {
                  "type": "mrkdwn",
                  "text": "*変更されたファイル*\n${{ env.FILES_LIST }}"
                }
              },
              {
                "type": "section",
                "text": {
                  "type": "mrkdwn",
                  "text": "*イメージタグ*\n`${{ env.IMAGE_TAG }}`"
                }
              },
              {
                "type": "actions",
                "elements": [
                  {
                    "type": "button",
                    "text": { "type": "plain_text", "text": "コミット詳細" },
                    "url": "${{ env.COMMIT_URL }}"
                  },
                  {
                    "type": "button",
                    "text": { "type": "plain_text", "text": "ワークフロー詳細" },
                    "url": "${{ env.WORKFLOW_URL }}"
                  }
                ]
              }
            ]
          }
        ]
      }      
yaml

上記のようにGitHub Actionsを用いて、ECSデプロイの可視化とSlackへの自動通知を組み込んでます。

通知は失敗時にも送信されるため、トラブルにも素早く対応できるようになります。特に開発期間はこういう通知があると初動が早くなるのでおすすめです。