最近、Cloud RunのデプロイをCloud Buildでやっているけど、
ビルドの完了とか失敗をSlackで通知したいなと思って、いろいろ調べたときの備忘録。
ソースコードは、GitHubで公開してます。
・https://github.com/memory-lovers/cloudbuild-slack
Cloud Buildの結果を通知する方法
公式ドキュメントにもSlack通知に関して書かれているけど、
通知用のCroud Runを別途用意しないといけないので、すこしハードルが高い。。
Cloud Build Notifier は Cloud Run でコンテナとして実行される Docker イメージです。
・Slack 通知を構成する | Cloud Build のドキュメント | Google Cloud
いろいろ見てみると、
Cloud Buildは、すべてのビルドイベントの更新とビルドメタデータを
cloud-builds
トピックのPub/Subに送信します。
とのことなので、Cloud FunctionsのPub/Subトリガーを使って、Slack通知ができるっぽい。
Cloud Functionsも、
- GCPのCloud Functionsと
- Cloud Functions for Firebase
の2つがあって、Firebaseを使ってるなら、
Cloud Functions for Firebaseに寄せてしまうのが良い感じ。
Firebaseの場合
シンプルな形はこんな感じ。
slackの通知部分は@slack/webhookを利用。
import * as functions from "firebase-functions"; import { IncomingWebhook } from "@slack/webhook"; const WEBHOOK_URL = functions.config().slack.webhook_url; const webhook = new IncomingWebhook(WEBHOOK_URL); export const notifyBuild = functions .region("asia-northeast1") .pubsub.topic("cloud-builds") .onPublish(async (message: functions.pubsub.Message) => { // messageを取得 const body = message.data ? Buffer.from(message.data, "base64").toString() : null; if (!body) return; const data = JSON.parse(body); // messageの中身から通知する情報を取得 const status = data.status; const repoName = data.substitutions?.REPO_NAME; const logUrl = data.logUrl; // Cloud Function for Firebaseのデプロイなどは // repoNameがないので、スキップ if (!repoName) return; // ステータスがWORKINGのときはスキップ if (status == "WORKING") return; // Slackへ通知 await webhook.send({ text: `${status}, repo: ${repoName}, ${logUrl}`, }); });
Webhook URLは環境変数から取得しているので、デプロイ前に設定が必要。
$ firebase functions:config:set slack.webhook_url="YOUR_WEBHOOK_URL"
Environment configuration | Firebase
設定したらデプロイすればOK
$ firebase deploy --only functions:notifyBuild
通知する内容もカスタマイズできる
await webhook.send({ text: "通知するテキスト", username: "通知するアカウントの名前"; icon_emoji: "通知するアカウントのアイコン絵文字"; icon_url: "通知するアカウントのアイコンのURL"; channel: "通知するチャネル"; link_names: true; // "ユーザ名やチャネルをリンクにするフラグ"; attachments: []; // message attachments blocks: []; // Block Kit UI components unfurl_links: true; // "テキストURLをリンクにするフラグ"; unfurl_media: true; // "メディアURLを展開するかどうかのフラグ"; });
Firebaseだと、デプロイも簡単(´ω`)
GCPのCloud Functionsの場合
こんな感じ。ほとんどFirebase verと変わらない。
import { IncomingWebhook } from "@slack/webhook"; const WEBHOOK_URL = process.env.WEBHOOK_URL || ""; const webhook = new IncomingWebhook(WEBHOOK_URL); export const notifyBuild = async (message: any) => { // messageを取得 const body = message.data ? Buffer.from(message.data, "base64").toString() : null; if (!body) return; const data = JSON.parse(body); // messageの中身から通知する情報を取得 const status = data.status; const repoName = data.substitutions?.REPO_NAME; const logUrl = data.logUrl; // Cloud Function for Firebaseのデプロイなどは // repoNameがないので、スキップ if (!repoName) return; // ステータスがWORKINGのときはスキップ if (status == "WORKING") return; // Slackへ通知 await webhook.send({ text: `${status}, repo: ${repoName}, ${logUrl}`, }); };
Webhook URLは環境変数から取得しているので、.env.yaml
を用意しておく。
# .env.yaml WEBHOOK_URL: "YOUR_WEBHOOK_URL"
デプロイはちょっとめんどう。。
$ gcloud functions deploy notifySlackBuild \ --runtime=nodejs14 \ --region=asia-northeast1 \ --trigger-topic=cloud-builds \ --project=<YOUR_PROJECT_ID> \ --env-vars-file=./.env.yaml \ --entry-point=notifyBuild
- notifySlackBuild: 関数名
--runtime
: ランタイムの設定。--region
: リージョン--trigger-topic
: Pub/Subトリガーで購読するトピック名--project
: プロジェクトのID--env-vars-file
: 環境変数のファイル。上記で作成したもの--entry-point
: 関数名とモジュール名が違う場合、モジュール名を指定
これでOK!!
ハマったところ
Cloud Buildの結果は自分が設定したもの以外もある
この部分。
// Cloud Function for Firebaseのデプロイなどは // repoNameがないので、スキップ if (!repoName) return;
なにもせずにそのままにしていたら、
Cloud Functions for Firebaseをデプロイしたときにも通知が。。
GitHub連携している場合は、リポジトリ名が取得できるので、
それを見て判断するようにしている。
関数名はGCPとFirebaseで共通
両方の名前を同じにしたら、上書きされてしまった。。
GCPの方を関数名だけ変えようとしたけど、うまく行かず。。
--entry-point
が必要だったよう。
--entry-point
を指定しない場合は、同じモジュール名を探してくるらしい。
参考にしたサイトさま
- Cloud BuildのSlack通知をFirebase Functions + TypeScriptで作る - GAミント至上主義
- GCP Cloud BuildをGitHubと連携させて、ビルド結果をSlackで通知する | hatakoya memo
- slackapi/node-slack-sdk: Slack Developer Kit for Node.js
- ビルド通知へのサブスクリプション | Cloud Build のドキュメント | Google Cloud
- Google Cloud Pub/Sub トリガー | Google Cloud Functions に関するドキュメント