配置 Slack 通知

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

准备工作

  • Enable the Cloud Build, Compute Engine, Cloud Run, Pub/Sub, and Secret Manager APIs.

    Enable the APIs

配置 Slack 通知

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

如需配置 Slack 通知,请执行以下操作:

  1. 创建 Slack 应用 创建所需的 Slack 工作区。

  2. 激活传入的网络钩子,将消息从 Cloud Build 发布到 Slack。

  3. 导航到您的 Slack 应用,找到传入的网络钩子的网址。您的网址将如下所示:

    http://hooks.slack.com/services/...
    
  4. 将传入的网络钩子网址存储在 Secret Manager 中:

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

      打开 Secret Manager 页面

    2. 点击创建密钥

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

    4. 密钥值下,为您的 Slack 应用添加传入的网络钩子网址。

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

  5. 虽然您的 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. 点击包含 Slack 应用的密钥的名称。

    5. 权限标签页中,点击添加成员

    6. 将与项目关联的 Compute Engine 默认服务账号添加为成员。

    7. 选择 Secret Manager Secret Accessor 权限作为角色。

    8. 点击保存

  6. 为您的 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. 点击保存

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

    在以下示例通知程序配置文件中,filter 字段使用通用表达式语言和可用变量 build 来过滤状态为 SUCCESS 的构建事件:

    apiVersion: cloud-build-notifiers/v1
    kind: SlackNotifier
    metadata:
      name: example-slack-notifier
    spec:
      notification:
        filter: build.status == Build.Status.SUCCESS
        params:
          buildStatus: $(build.status)
        delivery:
          webhookUrl:
            secretRef: webhook-url
        template:
          type: golang
          uri: gs://example-gcs-bucket/slack.json
      secrets:
      - name: webhook-url
        value: projects/project-id/secrets/secret-name/versions/latest
    

    其中:

    • buildStatus 是用户定义的参数。此参数采用 $(build.status) 的值,即 build 的状态。
    • webhook-url 是此示例中引用 Secret Manager 中存储的 Slack 网络钩子网址路径的配置变量。此处指定的变量名称应与 secrets 下的 name 字段匹配。
    • project-id 是您的 Google Cloud 项目的 ID。
    • secret-name 是您的 Secret 的名称,其中包含 Slack Webhook 网址。
    • uri 字段引用 slack.json 文件。此文件包含托管在 Cloud Storage 上的 JSON 模板,表示您发送到 Slack 空间的通知消息。

      JSON 模板文件利用了 Slack 的 blockkit 功能。如需查看模板文件示例,请参阅 cloud-build-notifiers 代码库中的 slack.json 文件

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

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

  8. 将通知程序配置文件上传到 Cloud Storage 存储分区

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

      gcloud storage buckets create gs://bucket-name/
      
    2. 将通知程序配置文件上传到您的存储分区:

      gcloud storage cp config-file-name gs://bucket-name/config-file-name
      

      其中:

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

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

    其中:

    • service-name 是您要将映像部署到的 Cloud Run 服务的名称。
    • config-path 是 Slack 通知程序的通知程序配置文件的路径,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 中找到以前的映像版本和标记。

  10. 授予 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 项目编号。
  11. 创建一个服务账号以表示您的 Pub/Sub 订阅身份:

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

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

  12. 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。

  13. 创建 cloud-builds 主题以接收通知程序的构建更新消息:

    gcloud pubsub topics create cloud-builds
    
  14. 为通知程序创建 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 项目的通知现已设置完毕。下次您调用构建时,如果构建与您已配置的过滤条件匹配,您将在 Slack 中收到通知。

使用 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

按图片过滤

要按图片过滤,请在 filter 字段中指定图片的值 使用 build.images,其中 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}$")

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

后续步骤