こちらの記事は「コドモン Advent Calendar 2022」と「GitHub Actions Advent Calendar 2022」の 19日目の記事です🎅
こんにちは! SREチームの田中です!
SREチームでは日々運用改善に取り組んでいるのですが、今回はある機能におけるデータをSlackへ通知したい!という要件に対して、GitHub ActionsとSlackのワークフローを活用することで、簡単に実装した例を紹介したいと思います。
要件
- 通知は日次で、通知時間は日中の業務時間であればいつでもOK
- 通知したい情報はDBのあるテーブルの件数
- 指定されたSlackチャンネルに関係者向けのメンションをつけて投稿
一般的な実装
コドモンではメインの基盤にAWSを利用しています。 AWSでDBの情報を取得してSlackに通知する手段としては以下のパターンが一般的かと思います。
この場合の以下の点の作業が必要になります。
- AWSリソースの作成(EventBridge/Lambda)
- Lambdaのコード開発
- Lambdaのデプロイパイプラインの作成
- Slackアプリの作成
今回の実装
既にGitHub Actionsを利用している場合、GitHub Actionsをデータ取得処理の実行基盤とすることで、以下のような簡単な構成で実装できます。
GitHub Actions
コドモンではアプリケーションのデプロイにGitHub Actionsを利用しています。 DBのテーブル変更などもGitHub Actionsにて実施しており、DBへの接続要件があるため、デプロイの実行基盤としてGitHub Actionsのセルフホストランナーを活用しています。
本番環境内にGitHub Actionsを実行するインスタンスが存在するため、セキュアにDBへの接続が可能です。
Slackワークフロー
Slackへの通知をするためのWebhook URLの発行手段としては、Slackアプリを作成して、Webhook URLを生成するのが一般的かと思います。
「Slack Webhook」で検索しても以下のSlackアプリを作成する手段がヒットします。
Slackにはワークフローというチャンネル上でタスクを自動化する機能があり、これを活用して日々の運用におけるSlackでのやり取りを自動化している方は多いと思います。
実はこのワークフローのトリガーとしてWebhookを作成することができます。
このワークフローのトリガーでWebhook URLを作成することで、Slackアプリを作成せずとも簡単に指定したチャンネルへ通知するためのWebhook URLが発行できます。
作り方
それでは実際に作っていきましょう!
今回は例として自身のtimesチャンネルに通知する仕組みを作っていきます。
1.Slackワークフローを作る
通知したいチャンネルのインテグレーションからワークフローを作成していきます。
ワークフローのトリガーとしてWebhookを選びます。
データベースから取得するデータは動的な値のため、Slack側では変数として扱えるようにします。
これでトリガーの設定は完了したので、続いてSlackチャンネルへの通知メッセージを作成していきます。
通知メッセージ内にデータベースから取得する動的な値が表示できるように、先ほど作成した変数をメッセージ内に追加します。
メッセージを通知するだけの処理であれば以上で完了なので、公開します。
WebhookのURLは次のGitHub Actions内で利用するため、値をコピーしておきます。
これでワークフローの作成が完了しました。
続いてGitHub Actionsにてデータを取得する処理を実装していきます。
2.GitHub Actionsを作る
今回はセルフホストランナーの実装については割愛します。 まだ利用したことがない方は以下の公式サイトや、他の記事を参考にしてみてください。
作成するワークフローは以下になります。
name: Daily Count Check on: schedule: - cron: '0 0 * * 2-6' #平日の毎日9時にチェック workflow_dispatch: jobs: build: runs-on: [self-hosted, sample] steps: - name: Get Count id: get-count env: DB_PASSWORD: ${{ secrets.DB_PASSWORD }} run: | COUNT=`echo "select count(*) from <テーブル名> where <取得条件>;" | mysql -h <DB_NAME> -u <DB_USER_NAME> -p${DB_PASSWORD} <DATABASE_NAME> -ss` echo "::set-output name=COUNT::$COUNT" exit $COUNT - name: Send custom JSON data to Slack workflow id: slack uses: slackapi/slack-github-action@v1.21.0 with: payload: | { "count": "${{ env.COUNT }}" } env: SLACK_WEBHOOK_URL: <Slackワークフローのトリガーにて生成したWebhook URL> COUNT: ${{ steps.get-count.outputs.COUNT }}
実行スケジュールの指定
on: schedule: - cron: '0 0 * * 2-6' #平日の毎日9時にチェック workflow_dispatch:
cron形式にて実行時間を指定します。時間はUTCでの指定になります。
注意:スケジュール機能は完全な実行時間を保証していません。 数分から10分程度ずれる可能性があるので、実行時間に厳密な処理には向いていないので注意してください。
また、workflow_dispatch:
も実行条件として指定することで、手動でも実行できるようにしておくと、テスト実行時などに利用でき便利です。
データベースパスワードの取得
env: PASS_WORD: ${{ secrets.DB_PASSWORD }}
データベースのパスワードについてはGitHub Secretsから取得するようにします。
GitHub Secretsを利用することで、データベースのパスワードをコードに直接記載せずセキュアに管理できます。
データベースから件数の取得
run: | COUNT=`echo "select count(*) from <テーブル名> where <取得条件>;" | mysql -h <DB_NAME> -u <DB_USER_NAME> -p${DB_PASSWORD} <DATABASE_NAME> -ss` echo "::set-output name=COUNT::$COUNT" exit $COUNT
件数を返すSQLを実行します。 取得結果は次のSlackへ通知するステップで利用できるようにoutputとして保存します。
なお、今回の例ではset-output
を利用し、ステップ間での値の受け渡しをしていますが、GitHubから2023年5月31日に無効化されるアナウンスが出ています。
現在では環境ファイルへ値を保存する形式が推奨されているため、現在も利用している方はご注意ください!!
Slackへの通知
- name: Send custom JSON data to Slack workflow id: slack uses: slackapi/slack-github-action@v1.21.0 with: payload: | { "count": "${{ env.COUNT }}" } env: SLACK_WEBHOOK_URL: <Slackワークフローのトリガーにて生成したWebhook URL> COUNT: ${{ steps.get-count.outputs.COUNT }}
Slackへの通知は公式が提供するActionsを利用します。
payload
には、Slackワークフロー作成時に指定した変数名をキー値とし、値には前のステップにて取得した値を入力します。
また、SLACK_WEBHOOK_URL
にはSlackワークフロー作成時にコピーしておいたWebhookURLを入力します。
3.通知
上記設定にてSlackチャンネルに通知されるメッセージが以下です。
本日のカウント数
はGitHub Actionsのセルフホストランナーで実行され、DBから取得した件数が値として表示されます。
まとめ
以前はSlack通知させるために、Slackアプリの作成からLambda作成など、複数のリソースの作成が必要なため、1日がかりで準備をしていました。
GitHub ActionsとSlackワークフローを活用することで、半分以下の時間でお手軽に同様の実装ができるようになりました!!
また、AWSのリソース作成が不要なので、SREが作業のボトルネックになることなく、開発メンバーが自分で管理できる範囲で実装できるのも利点だなと感じています。
コドモンでは業務の効率化のために、開発部全体でもGitHub Actionsの活用が盛んなので、こういった事例を社内で共有しながらさらなる運用改善を進めていきたいと思います!