SMTP 通知の構成

Cloud Build は、Slack や SMTP サーバーなどの選択したチャネルに通知を送信することで、ビルド更新を通知します。このページでは、 SMTP Notifier を使用して通知を構成する方法について説明します。

始める前に

  • Cloud Build、Compute Engine、Cloud Run、Pub/Sub、Secret Manager API を有効にします。

    API を有効にするために必要なロール

    API を有効にするには、serviceusage.services.enable 権限が必要です。プロジェクトを作成した場合は、オーナーロール(roles/owner)を介してこの権限が付与されている可能性があります。それ以外の場合は、Service Usage 管理者ロール(roles/serviceusage.serviceUsageAdmin)を介してこの権限を取得できます。ロールを付与する方法をご覧ください

    API を有効にする

メール通知を構成する

メール通知を送信するには、SMTP サーバーが稼働している必要があります。また、そのサーバーのアカウントに対するアクセス権も必要です。通知の送信に使用するアカウントのユーザー名とパスワードが必要になります。既存の SMTP サーバーを使用できますが、サーバー名とポートにアクセスする必要があります。たとえば、Gmail のサーバー名は smtp.gmail.com で、ポートは 587 です。生成されるメールの量が SMTP サーバーの配信割り当てを超えないようにする必要があります。

次のセクションでは、SMTP Notifier を使用してメール通知を手動で構成する方法について説明します。構成を手動で行わず、自動化する場合は、通知の構成の自動化をご覧ください。

メールによる通知を構成するには:

  1. 送信者のメール アカウントのパスワードをシークレット マネージャーに保存します。Gmail の場合、アカウントのログイン パスワードではなく、アプリのパスワードを使用する必要があります。

    1. コンソール Google Cloud で [Secret Manager] ページを開きます。

      [シークレット マネージャー] ページを開く

    2. [シークレットの作成] をクリックします。

    3. シークレットの名前を入力します。

    4. [シークレットの値] に、送信者のメール アカウントのパスワードを追加します。

    5. シークレットを保存するには、[シークレットの作成] をクリックします。

  2. Cloud Run サービス アカウントにはプロジェクトのエディタ ロールが存在する場合がありますが、エディタ ロールは Secret Manager のシークレットにアクセスするのには不十分です。 Cloud Run サービス アカウントにシークレットへのアクセス権を付与するには、次の操作を行います。

    1. コンソール Google Cloud で、[IAM] ページに移動します。

      [IAM] ページを開く

    2. プロジェクトに関連付けられている Compute Engine のデフォルトのサービス アカウントを見つけます。

      Compute Engine のデフォルトのサービス アカウントは次のようになります。

      project-number-compute@developer.gserviceaccount.com
      

      Compute Engine のデフォルトのサービス アカウントをメモしておきます。

    3. コンソール Google Cloud で [Secret Manager] ページを開きます。

      [Secret Manager] ページを開く

    4. 送信者のメール アカウント パスワードのシークレットを含むシークレット名をクリックします。

    5. [権限] タブで、[メンバーを追加] をクリックします。

    6. プロジェクトに関連付けられている Compute Engine のデフォルトのサービス アカウントをメンバーとして追加します。

    7. ロールとして Secret Manager のシークレット アクセサー権限を選択します。

    8. [保存] をクリックします。

  3. Cloud Run サービス アカウントに、Cloud Storage バケットの読み取り権限を付与します。

    1. コンソール Google Cloud で、[IAM] ページに移動します。

      [IAM] ページを開く

    2. プロジェクトに関連付けられている Compute Engine のデフォルトのサービス アカウントを見つけます。

      Compute Engine のデフォルトのサービス アカウントは次のようになります。

      project-number-compute@developer.gserviceaccount.com
      
    3. Compute Engine のデフォルトのサービス アカウントを含む行の鉛筆アイコンをクリックします。[アクセスを編集] タブが表示されます。

    4. [別のロールを追加] をクリックします。

    5. 次のロールを追加します。

      • ストレージ オブジェクト閲覧者
    6. [保存] をクリックします。

  4. Notifier 構成ファイルを作成し、ビルドイベントに SMTP Notifier とフィルタを構成します。

    次の Notifier 構成ファイルの例では、filter フィールドで Common Expression Language を使用し、変数 build を指定し、SUCCESS ステータスでビルドイベントをフィルタリングします。

    apiVersion: cloud-build-notifiers/v1
    kind: SMTPNotifier
    metadata:
      name: example-smtp-notifier
    spec:
      notification:
        filter: build.status == Build.Status.SUCCESS
        params:
          buildStatus: $(build.status)
        delivery:
          server: SERVER_HOST_NAME
          port: "PORT"
          sender: SENDER_EMAIL
          from: FROM_EMAIL
          recipients:
            - RECIPIENT_EMAIL
            # optional: more emails here
          password:
            secretRef: smtp-password
        template:
          type: golang
          uri: gs://BUCKET_NAME/smtp.html
      secrets:
      - name: smtp-password
        value: projects/PROJECT_ID/secrets/SECRET_NAME/versions/latest
    

    ここで

    • buildStatus は、ユーザー定義のパラメータです。このパラメータは、$(build.status) の値、ビルドのステータスです。
    • BUCKET_NAME はバケットの名前です。
    • SERVER_HOST_NAME は、SMTP サーバーのアドレスです。
    • PORT は、SMTP リクエストを処理するポートです。この値は文字列として指定する必要があります。
    • SENDER_EMAIL は、指定された SERVER_HOST_NAME に表示される送信者アカウントのメールアドレスです。
    • FROM_EMAIL は、受信者に表示されるメールアドレスです。
    • RECIPIENT_EMAIL は、送信者からメッセージを受信する 1 つ以上のメールアドレスのリストです。
    • smtp-password は、シークレット マネージャーに保存されている送信者のメール アカウントのパスワードを参照するためにこの例で使用する構成変数です。ここで指定する変数名は、secretsname フィールドに一致させる必要があります。
    • PROJECT_ID は、実際の Google Cloud プロジェクトの ID です。
    • SECRET_NAME は、送信者のメールアカウントのパスワードを含むシークレットの名前です。
    • uri フィールドは smtp.html ファイルを参照します。このファイルは Cloud Storage でホストされる html テンプレートを参照し、通知メールを表します。

    サンプルについては、Notifier の構成ファイルをご覧ください。

    フィルタに使用できるその他のフィールドについては、ビルドリソースをご覧ください。フィルタリングに関するその他の例については、CEL を使用してビルドイベントをフィルタリングするをご覧ください。

  5. 通知機能構成ファイルを Cloud Storage バケットにアップロードします。

    1. Cloud Storage バケットがない場合は、次のコマンドを実行してバケットを作成します。ここで、BUCKET_NAME命名要件に従って、バケットに付ける名前です。

      gcloud storage buckets create gs://BUCKET_NAME/
      
    2. Notifier 構成ファイルをバケットにアップロードします。

      gcloud storage cp CONFIG_FILE_NAME gs://BUCKET_NAME/CONFIG_FILE_NAME
      

      ここで

      • BUCKET_NAME はバケットの名前です。
      • CONFIG_FILE_NAME は構成ファイルの名前です。
  6. Notifier を Cloud Run にデプロイします。

     gcloud run deploy SERVICE_NAME \
       --image=us-east1-docker.pkg.dev/gcb-release/cloud-build-notifiers/smtp:latest \
       --no-allow-unauthenticated \
       --update-env-vars=CONFIG_PATH=CONFIG_PATH,PROJECT_ID=PROJECT_ID
    

    ここで

    • SERVICE_NAME は、イメージをデプロイする Cloud Run サービスの名前です。
    • CONFIG_PATH は、SMTP Notifier の Notifier 構成ファイルへのパスで、gs://BUCKET_NAME/CONFIG_FILE_NAME です。
    • PROJECT_ID は、実際の Google Cloud プロジェクトの ID です。

    gcloud run deploy コマンドは、ホストされたイメージの最新バージョンを Cloud Build が所有する Artifact Registry から pull します。Cloud Build は 9 か月間、Notifier イメージをサポートします。9 か月を過ぎると、イメージのバージョンは削除されます。以前のイメージ バージョンを使用する場合は、gcloud run deploy コマンドの image 属性でイメージタグの完全なセマンティック バージョンを指定する必要があります。以前のイメージ バージョンとタグは、Artifact Registry にあります。

  7. Pub/Sub サブスクリプション ID を表すサービス アカウントを作成します。

    gcloud iam service-accounts create SUB_IDENTITY_SERVICE_ACCOUNT \
      --display-name "SUB_IDENTITY_SERVICE_ACCOUNT_DISPLAY_NAME"
    

    ここで

    • SUB_IDENTITY_SERVICE_ACCOUNT は、サービス アカウントの名前です。

    • SUB_IDENTITY_SERVICE_ACCOUNT_DISPLAY_NAME は、サービス アカウントの表示名です。

    です。
  8. プロジェクトで認証トークンを作成するために必要な権限を Pub/Sub サブスクリプション ID サービス アカウントに 付与します。 Google Cloud

    gcloud iam service-accounts add-iam-policy-binding \
        SUB_IDENTITY_SERVICE_ACCOUNT@PROJECT_ID.iiam.gserviceaccount.com \
        --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
        --role=roles/iam.serviceAccountTokenCreator
    

    ここで

    • PROJECT_ID は、実際の Google Cloud プロジェクトの ID です。

    • PROJECT_NUMBER は Google Cloud プロジェクト番号です。

  9. SUB_IDENTITY_SERVICE_ACCOUNT サービス アカウントに Cloud Run Invoker ロールを付与します。

    gcloud run services add-iam-policy-binding SERVICE_NAME \
       --member=serviceAccount:SUB_IDENTITY_SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com \
       --role=roles/run.invoker
    

    ここで

    • SERVICE_NAME は、イメージをデプロイする Cloud Run サービスの名前です。

    • PROJECT_ID は、実際の Google Cloud プロジェクトの ID です。

  10. cloud-builds トピックを作成して、Notifier のビルド更新メッセージを受信します。

    gcloud pubsub topics create cloud-builds
    

    ビルド構成ファイルでカスタム トピック名を定義して 、メッセージがカスタム トピックに送信されるようにすることもできます。この場合は、同じカスタム トピック名でトピックを作成します。

    gcloud pubsub topics create topic-name
    

    詳細については、 ビルド通知の Pub/Sub トピックをご覧ください。

  11. Notifier に Pub/Sub push サブスクライバーを作成します。

     gcloud pubsub subscriptions create subscriber-id \
       --topic=cloud-builds \
       --push-endpoint=SERVICE_URL \
       --push-auth-service-account=SUB_IDENTITY_SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com

ここで + SUBSCRIBER_ID は、サブスクリプションに付ける名前です。 + SERVICE_URL は、Cloud Run によって生成された、新しいサービスの URL です。 + PROJECT_ID は、実際の Google Cloud プロジェクトの ID です。

Note: By default, [subscriptions expire after 31 days of inactivity](/pubsub/docs/subscription-overview#lifecycle).
You can adjust or disable the expiration period by including the
[`--expiration-period` flag](/sdk/gcloud/reference/pubsub/subscriptions/create#--expiration-period)
when creating the subscription.

これで Cloud Build プロジェクトの通知が設定されました。次にビルドを呼び出すときに、構成したフィルタとビルドが一致すると、recipients が通知を含むメールを受信します。

CEL を使用したビルドイベントのフィルタリング

Cloud Build は、ビルドリソースにリストされているフィールドの変数 build で CEL を使用して、トリガー ID、イメージリスト、置換変数などのビルドイベントと関連するフィールドにアクセスします。filter 文字列を使用すると、Build リソースに表示されているフィールドを使用してビルド構成ファイル内のビルドイベントをフィルタリングできます。フィールドに関連付けられた正確な構文を見つけるには、cloudbuild.proto ファイルをご覧ください。

トリガー ID によるフィルタリング

トリガー ID でフィルタリングするには、build.build_trigger_id を使用してトリガー ID の値をfilter フィールドに指定します。ここで、trigger-id は文字列であるトリガー ID です。

filter: build.build_trigger_id == trigger-id

ステータスによるフィルタリング

ステータスでフィルタリングするには、build.status を使用して、フィルタリングするビルドのステータスを filter フィールドに指定します。

次の例は、filter フィールドを使用して SUCCESS ステータスのビルドイベントをフィルタリングする方法を示しています。

filter: build.status == Build.Status.SUCCESS

さまざまなステータスのビルドをフィルタリングすることもできます。次の例は、filter フィールドを使用して、ステータスが SUCCESSFAILURE、または TIMEOUT のビルドイベントをフィルタリングする方法を示しています。

filter: build.status in [Build.Status.SUCCESS, Build.Status.FAILURE, Build.Status.TIMEOUT]

フィルタリングできるその他のステータス値を確認するには、ビルドリソース リファレンスのステータスをご覧ください。

タグによるフィルタリング

タグでフィルタリングするには、build.tags を使用して filter フィールドにタグの値を指定します。ここで、tag-name はタグの名前です。

filter: tag-name in build.tags

size を使用すると、ビルドイベントで指定されたタグの数に基づいてフィルタリングできます。以下の例では、filter フィールドにより、1 つのタグが v1 に指定されたタグがちょうど 2 つあるビルドイベントがフィルタリングされます。

filter: size(build.tags) == 2 && "v1" in build.tags

イメージによるフィルタリング

イメージでフィルタリングするには、build.images を使用して filter フィールドにイメージの値を指定します。ここで image-name は、us-east1-docker.pkg.dev/my-project/docker-repo/image-one などの Artifact Registry に表示されるイメージの完全な名前です。

filter: image-name in build.images

下の例では、filter がイメージ名として us-east1-docker.pkg.dev/my-project/docker-repo/image-one または us-east1-docker.pkg.dev/my-project/docker-repo/image-two が指定されているビルドイベントをフィルタリングします。

filter: "us-east1-docker.pkg.dev/my-project/docker-repo/image-one" in build.images || "us-east1-docker.pkg.dev/my-project/docker-repo/image-one" in build.images

時間によるフィルタリング

filter フィールドに build.create_timebuild.start_timebuild.finish_time のいずれかのオプションを指定すると、ビルドの作成時間、開始時間、終了時間に基づいてビルドイベントをフィルタリングできます。

下の例では、filter フィールドで timestamp を使用し、ビルドを作成するリクエスト時刻を 2020 年 7 月 20 日 午前 6 時に指定して、ビルドイベントをフィルタリングします。

filter: build.create_time == timestamp("2020-07-20:T06:00:00Z")

時刻の比較によりビルドイベントをフィルタリングすることもできます。下の例では、filter フィールドで timestamp を使用し、開始時刻を 2020 年 7 月 20 日午前 6 時と 2020 年 7 月 30 日午前 6 時の間に指定して、ビルドイベントをフィルタリングします。

filter: timestamp("2020-07-20:T06:00:00Z") >= build.start_time && build.start_time <= timestamp("2020-07-30:T06:00:00Z")

CEL での時間帯の表記方法に関する詳細については、時間帯の言語の定義をご覧ください。

ビルド時間でフィルタリングするには、duration を使用してタイムスタンプを比較します。下の例では、filter フィールドで duration を使用して、ビルドが 5 分以上実行されるビルドイベントをフィルタリングします。

filter: build.finish_time - build.start_time >= duration("5m")

置換によるフィルタリング

build.substitutions を使用して filter フィールドに置換変数を指定すると、置換によってフィルタリングできます。次の例では、filter フィールドは置換変数 substitution-variable を含むビルドを一覧表示し、substitution-variable が指定された substitution-value と一致するかどうかを確認します。

filter: build.substitutions[substitution-variable] == substitution-value

ここで

  • substitution-variable は置換変数の名前です。
  • substitution-value は、置換値の名前です。

また、デフォルトの置換変数値でフィルタリングすることもできます。次の例では、filter フィールドにブランチ名が master のビルドとリポジトリ名が github.com/user/my-example-repo のビルドが一覧表示されます。デフォルトの置換変数 BRANCH_NAMEREPO_NAME がキーとして build.substitutions に渡されます。

filter: build.substitutions["BRANCH_NAME"] == "master" && build.substitutions["REPO_NAME"] == "github.com/user/my-example-repo"

正規表現を使用して文字列をフィルタリングする場合は、組み込みの matches 関数を使用できます。以下の例では、filter フィールドは、ステータスが FAILURE または TIMEOUT であり、正規表現 v{DIGIT}.{DIGIT}.{3 DIGITS}) と一致する値を持つビルド置換変数 TAG_NAME のあるビルドでフィルタリングします。

filter: build.status in [Build.Status.FAILURE, Build.Status.TIMEOUT] && build.substitutions["TAG_NAME"].matches("^v\\d{1}\\.\\d{1}\\.\\d{3}$")

デフォルトの置換値のリストについては、デフォルトの置換の使用をご覧ください。

次のステップ