配置 SMTP 通知

Cloud Build 可以通过向您的所需渠道(例如 Slack 或 SMTP 服务器)发送通知来通知您构建更新。本页介绍如何使用 SMTP 通知程序配置通知。

准备工作

  • 启用 Cloud Build, Compute Engine, Cloud Run, Pub/Sub, and Secret Manager API。

    启用 API

配置电子邮件通知

如需发送电子邮件通知,您需要运行 SMTP 服务器并访问该服务器上的账号,包括用于发送通知的账号用户名和密码。您可以使用任何现有的 SMTP 服务器,但需要访问服务器名称和端口。例如,Gmail 的服务器名称为 smtp.gmail.com,端口为 587。确保 SMTP 服务器的递送配额能够处理您希望生成的电子邮件量。

以下部分介绍如何使用 SMTP 通知程序来手动配置电子邮件通知。如果您希望改为自动配置,请参阅自动配置通知

如需配置电子邮件通知,请执行以下操作:

  1. 将发件人的电子邮件帐号密码存储在 Secret Manager 中。请注意,对于 Gmail,您将需要使用应用专用密码,而不是帐号登录密码。

    1. 在 Google Cloud 控制台中打开 Secret Manager 页面:

      打开 Secret Manager 页面

    2. 点击创建密钥

    3. 为您的密钥输入一个名称。

    4. 密钥值下,添加发件人的电子邮件账号密码。

    5. 如需保存您的密钥,请点击创建密钥

  2. 虽然您的 Cloud Run 服务账号可能拥有项目的 Editor 角色,但 Editor 角色不足以访问 Secret Manager 中的 Secret。您需要为 Cloud Run 服务账号授予对您的 Secret 的访问权限:

    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 Secret Accessor 权限作为角色。

    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. 添加以下角色:

      • Storage Object Viewer
    6. 点击保存

  4. 编写通知程序配置文件以配置您的 SMTP 通知程序并过滤构建事件:

    在以下示例通知程序配置文件中,filter 字段使用通用表达式语言和可用变量 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://example-gcs-bucket/smtp.html
      secrets:
      - name: smtp-password
        value: projects/project-id/secrets/secret-name/versions/latest
    

    其中:

    • buildStatus 是用户定义的参数。此参数将采用 $(build.status) 的值,即 build 的状态。
    • server-host-name 是 SMTP 服务器的地址。
    • port 是处理 SMTP 请求的端口。此值应指定为字符串。
    • sender-email 是指定的 server-host-name 看到的发件人账号的电子邮件地址。
    • from-email 是收件人看到的电子邮件地址。
    • recipient-email 是接收来自发件人的消息的一个或多个电子邮件地址的列表。
    • smtp-password 是此示例中用于引用 Secret Manager 中存储的发件人的电子邮件账号密码的配置变量。此处指定的变量名称应与 secrets 下的 name 字段匹配。
    • project-id 是您的 Google Cloud 项目的 ID。
    • secret-name是您的 Secret 的名称,其中包含发件人的电子邮件账号的密码。
    • uri 字段引用 smtp.html 文件。此文件引用 Cloud Storage 上托管的 HTML 模板,表示您的通知电子邮件。

    如需查看此示例,请参阅 SMTP 通知程序的通知程序配置文件

    如需了解可用于过滤的其他字段,请参阅构建资源。如需了解其他过滤示例,请参阅使用 CEL 过滤构建事件

  5. 将通知程序配置文件上传到 Cloud Storage 存储桶

    1. 如果您没有 Cloud Storage 存储桶,请运行以下命令创建一个存储桶,其中 bucket-name 是您要为存储桶指定的名称(须遵循命名要求)。

      gsutil mb gs://bucket-name/
      
    2. 将通知程序配置文件上传到您的存储桶:

      gsutil cp config-file-name gs://bucket-name/config-file-name
      

      其中:

      • bucket-name 是您的存储桶的名称。
      • config-file-name 是您的配置文件的名称。
  6. 将通知程序部署到 Cloud Run:

    gcloud run deploy service-name \
      --image=us-east1-docker.pkg.dev/gcb-release/cloud-build-notifiers/smtp:latest \
      --update-env-vars=CONFIG_PATH=config-path,PROJECT_ID=project-id
    

    其中:

    • service-name 是您要将映像部署到的 Cloud Run 服务的名称。

    • config-path 是 SMTP 通知程序的通知程序配置文件的路径,gs://bucket-name/config-file-name

    • project-id 是您的 Google Cloud 项目的 ID。

    gcloud run deploy 命令会从 Cloud Build 拥有的 Artifact Registry 拉取最新版本的托管映像。Cloud Build 支持通知程序映像 9 个月。9 个月后,Cloud Build 会删除映像版本。如果您想使用旧的映像版本,则需要在 gcloud run deploy 命令的 image 属性中指定映像标记的完整语义版本。您可以在 Artifact Registry 中找到以前的映像版本和标记。

  7. 授予 Pub/Sub 在项目中创建身份验证令牌的权限:

    gcloud projects add-iam-policy-binding project-id \
      --member=serviceAccount:service-project-number@gcp-sa-pubsub.iam.gserviceaccount.com \
      --role=roles/iam.serviceAccountTokenCreator
    

    其中:

    • project-id 是您的 Google Cloud 项目的 ID。
    • project-number 是您的 Google Cloud 项目编号。
  8. 创建一个服务账号以表示您的 Pub/Sub 订阅身份:

    gcloud iam service-accounts create cloud-run-pubsub-invoker \
      --display-name "Cloud Run Pub/Sub Invoker"
    

    您可以使用 cloud-run-pubsub-invoker或使用在您的 Google Cloud 项目中唯一的名称。

  9. cloud-run-pubsub-invoker 服务账号授予 Cloud Run Invoker 权限:

    gcloud run services add-iam-policy-binding service-name \
        --member=serviceAccount:cloud-run-pubsub-invoker@project-id.iam.gserviceaccount.com \
        --role=roles/run.invoker
    

    其中:

    • service-name 是您要将映像部署到的 Cloud Run 服务的名称。
    • project-id 是您的 Google Cloud 项目的 ID。
  10. 创建 cloud-builds 主题以接收通知程序的构建更新消息:

    gcloud pubsub topics create cloud-builds
    
  11. 为通知程序创建 Pub/Sub 推送订阅者:

    gcloud pubsub subscriptions create subscriber-id \
      --topic=cloud-builds \
      --push-endpoint=service-url \
      --push-auth-service-account=cloud-run-pubsub-invoker@project-id.iam.gserviceaccount.com
    

    其中:

    • subscriber-id 是您要为订阅指定的名称。
    • service-url是 Cloud Run 为新服务生成的网址。
    • project-id 是您的 Google Cloud 项目的 ID。

您的 Cloud Build 项目的通知现已设置完毕。下次您调用构建时,如果构建与您已配置的过滤条件匹配,则指定的 recipients 将收到包含通知的电子邮件。

使用 CEL 过滤构建事件

Cloud Build 在构建资源中列出的字段上搭配使用 CEL 与变量 build,以便访问与构建事件关联的字段,例如触发器 ID、图片列表或替换值。您可以使用 filter 字符串,通过构建资源中列出的任何字段,来过滤通构建配置文件中的构建事件。如需查找与您的字段关联的具体语法,请参阅 cloudbuild.proto 文件。

按触发器 ID 过滤

要按触发器 ID 过滤,请使用 build.build_trigger_idfilter 字段中指定触发器 ID 的值,其中 trigger-id 是字符串形式的触发器 ID:

filter: build.build_trigger_id == trigger-id

按状态过滤

要按状态过滤,请使用 build.statusfilter 字段中指定要过滤的构建状态。

以下示例展示了如何使用 filter 字段过滤状态为 SUCCESS 的构建事件:

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

您也可以过滤具有不同状态的构建。以下示例展示了如何使用 filter 字段过滤状态为 SUCCESSFAILURETIMEOUT 的构建事件:

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

要查看您可以作为过滤依据的其他状态值,请参阅“构建资源参考”下的状态

按标记过滤

要按标记过滤,请使用 build.tagsfilter 字段中指定标记的值,其中 tag-name 是标记的名称:

filter: tag-name in build.tags

您可以使用 size 根据构建事件中指定的标记数量进行过滤。在以下示例中,filter 字段会过滤仅指定了两个标记且其中一个标记指定为 v1 的构建事件:

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

按图片过滤

如需按映像过滤,请使用 build.imagesfilter 字段中指定映像的值,其中 image-name 是 Artifact Registry 中列出的映像的全名,例如 us-east1-docker.pkg.dev/my-project/docker-repo/image-one

filter: image-name in build.images

在以下示例中,filter 会过滤将 us-east1-docker.pkg.dev/my-project/docker-repo/image-oneus-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:00 的构建事件。

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

您还可以按时间比较过滤构建事件。在以下示例中,filter 字段会使用 timestamp 过滤开始时间介于 2020 年 7 月 20 日上午 6:00 到 2020 年 7 月 30 日上午 6:00 之间的构建事件。

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 过滤包含至少运行了五分钟的构建的构建事件:

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

按替换过滤

您可以使用 build.substitutionsfilter 字段中指定替换变量,从而按替换进行过滤。在以下示例中,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 的构建,并且有一个构建替代变量 TAG_NAME,以及一个与正则表达式 v{DIGIT}.{DIGIT}.{3 DIGITS}) 匹配的值。

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

要查看默认替换值的列表,请参阅使用默认替换

后续步骤