はじめに
Google Cloud でCI/CDと言えばCloud Buildですが、ビルド結果がどうなったのか毎回コンソールの履歴画面に行って確認するのは手間です。
今回はCloud Buildの通知をslackに送信する方法を紹介します。
Cloud Buildの通知はMonitoringの様にネイティブで対応しておらず、Google公式の方法として「Cloud Build Notifier」と言うCloud Runの公式イメージを使って通知機能を実装します。
(いずれネイティブ対応されるかなと思ったのですが、5年ぐらいこのやり方が続いてます)
構成
用意するものとしては、以下の通り
(図は公式ガイドより抜粋)
- 通知するpub/sub
- 公式イメージをデプロイするCloud Run
- 外付け設定のyamlとjsonを配置するCloud Storage
- WebhookURLを保存するSecretManager
- monitoringと違い、slackのbotトークンではない点に注意
IAM
以下の二つのサービスアカウントを作成
- Pub/Subのサービスアカウント
- サービストークン作成者
- Cloud Runのサービスアカウント
- Secret Manager シークレット アクセサー
- ストレージ オブジェクト閲覧者
Secret Manager
シークレットを作成し、slackアプリのWebHookURLを値に設定。(slack周りの解説は省略)
Cloud Run
コンテナイメージに以下を指定
- us-east1-docker.pkg.dev/gcb-release/cloud-build-notifiers/slack:latest
- 中身はGoアプリで、処理としては以下の通り(実際のソースコードはこちら)
-
- Pub/Subのリクエストを受信
- 外付けのメッセージテンプレートファイルを読み込んでメッセージ生成
- SecretManagerのwebhookURLに送る(slackモードの場合)
環境変数に以下の2つを設定
- CONFIG_PATH
- CloudStorageのyamlファイルのパス
- PROJECT_ID
- プロジェクトID
Pub/Sub
トピック
Cloud Build通知はデフォルトで「"cloud-builds"」で送られるため、それ用のトピックを作成
terraform
resource "google_pubsub_topic" "cloud_builds" {
name = "cloud-builds"
project = var.project_id
}
サブスクリプション
上記トピックを受け取り、Cloud Runを起動するサブスクリプション
terraform
resource "google_pubsub_subscription" "cloud_builds_slack" {
name = "cb-slack-notifier"
topic = google_pubsub_topic.cloud_builds.name
project = var.project_id
push_config {
push_endpoint = google_cloud_run_v2_service..uri
oidc_token {
service_account_email =
}
}
ack_deadline_seconds = 600
message_retention_duration = "86400s"
retry_policy {
minimum_backoff = "10s"
maximum_backoff = "600s"
}
}
CloudStorage
以下の二つを作成し、CloudStorageにアップロードする
1. メッセージテンプレート(slack.json)
Slack Block Kit方式で書かれたメッセージテンプレート
サンプルだと情報が少な過ぎるのと、「{{.Params.buildStatus}}」がNoValueで読めなかったので以下の様に修正しました。
.Buildで使える変数はこちら、.Build.Substitutionsで使える変数はこちらを参考にしました。
(ビルド時間は無いので、StartTimeとFinishTimeで代用)
[
{
"type": "header",
"text": {
"type": "plain_text",
"text": "{{.Build.Substitutions.TRIGGER_NAME}}: {{.Build.Status}}"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Project:*\n{{.Build.ProjectId}}"
},
{
"type": "mrkdwn",
"text": "*Branch:*\n{{.Build.Substitutions.BRANCH_NAME}}"
},
{
"type": "mrkdwn",
"text": "*Start Time (UTC):*\n{{.Build.StartTime.AsTime}}"
},
{
"type": "mrkdwn",
"text": "*Finish Time (UTC):*\n{{.Build.FinishTime.AsTime}}"
}
]
},
{
"type": "divider"
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "View Build Logs"
},
"accessory": {
"type": "button",
"text": {
"type": "plain_text",
"text": "Logs"
},
"value": "click_me_123",
"url": "{{.Build.LogUrl}}",
"action_id": "button-action"
}
}
]
2. 設定ファイル(slack.yaml)
失敗ステータスだけ欲しい場合など、このファイルでフィルター可能。
今回は全てのステータスで通知が飛ぶ様にします。また、読み込むシークレット名とテンプレートjsonのパスも設定します。
apiVersion: cloud-build-notifiers/v1
kind: SlackNotifier
metadata:
name: slack-notifier
spec:
notification:
filter: build.status == Build.Status.SUCCESS || build.status == Build.Status.FAILURE || build.status == Build.Status.TIMEOUT || build.status == Build.Status.INTERNAL_ERROR || build.status == Build.Status.CANCELLED
delivery:
webhookUrl:
secretRef: slack-webhook-url
template:
type: golang
uri: gs://-cb-notifier/slack-message-template.json
secrets:
- name: slack-webhook-url
value: projects//secrets/cb-slack-webhook/versions/latest
実際のslack通知
Cloud Buildがビルド完了するとこの様にメッセージテンプレートに基づいた通知が届きます。
さいごに
Cloud Build Notifierの良さは、自分の好きなチャネルに、必要な情報だけを届けられる柔軟性にあります。
今回紹介した設定をベースに、さらにフィルタリングや通知文面を自分好みにカスタマイズしてみてください。
最後までお読みいただき、ありがとうございました、

