建立您的通知程式

Cloud Build 可以透過向所選管道傳送通知,通知您建構狀態的最新資訊。除了 Cloud Build 維護的通知器 (例如 SlackSMTP),您也可以使用 cloud-build-notifiers 存放區中提供的程式庫,建立自己的通知器。

本頁說明如何建立自己的通知器。

事前準備

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

    Enable the APIs

  • 安裝 Go 程式設計語言

  • 安裝 Google Cloud CLI

設定

  1. 在電腦上開啟終端機視窗。

  2. 複製並前往 cloud-build-notifiers 存放區:

      git clone https://github.com/GoogleCloudPlatform/cloud-build-notifiers.git && cd cloud-build-notifiers
    
  3. 為自己的通知器新增目錄並前往該目錄,其中 DIRECTORY_NAME 是目錄名稱:

      mkdir DIRECTORY_NAME && cd DIRECTORY_NAME
    
  4. 在新的目錄中初始化 go 模組,其中 DIRECTORY_NAME 是新目錄的名稱:

      go mod init github.com/GoogleCloudPlatform/cloud-build-notifiers/DIRECTORY_NAME
    

    目錄中現在應該會顯示 go.mod 檔案。

  5. go.mod 檔案中新增下列程式碼行,確保您使用的是最新版本的通知器:

     replace github.com/GoogleCloudPlatform/cloud-build-notifiers/lib/notifiers => ../
    

依附元件已設定完成,您可以建立自己的通知程式。

建立您的通知程式

cloud-build-notifiers 包含 lib/notifiers 目錄。在 lib/notifiers 目錄中,您會看到名為 notifier.go 的檔案。這個檔案包含可用來建立自訂通知器的架構。

您需要定義兩種方法,才能在主要檔案中建立通知器。

  1. 在新目錄中,建立名為 main.go 的檔案。

  2. main.go 中,匯入通知器程式庫架構和任何其他依附元件:

    package main
    
    import (
    	"context"
    	"fmt"
    
    	cbpb "cloud.google.com/go/cloudbuild/apiv1/v2/cloudbuildpb"
    	"github.com/GoogleCloudPlatform/cloud-build-notifiers/lib/notifiers"
    	log "github.com/golang/glog"
    	"google.golang.org/protobuf/encoding/prototext"
    )
    
  3. 定義通知器的主要方法。在這個範例中,logger 是通知器的名稱:

    func main() {
    	if err := notifiers.Main(new(logger)); err != nil {
    		log.Fatalf("fatal error: %v", err)
    	}
    }
    

    main 方法會使用 notifier.go 檔案中定義的 Main 方法,用於設定通知器二進位檔。

  4. 為通知器定義結構體,並在其中定義介面的變數。在這個範例中,logger 是通知器的名稱:

    type logger struct {
    	filter notifiers.EventFilter
    }
    
  5. 新增通知器功能。通知器介面是由兩種方法定義:

    • SetUpSetUp 方法會接受設定、擷取機密資料,並從設定中提取指定的篩選器,然後將其儲存為可用於傳送通知的 Common Expression Language 預設詞。如要進一步瞭解 CEL,請參閱 cel-spec 存放區
    • SendNotificationSendNotification 方法用於將通知傳送至所選頻道或服務。

      如需通知器的定義,請參閱 notifier.goGo 說明文件

      在以下範例中,通知器介面是使用 SetUpSendNotification 方法定義,以便列印建構記錄,其中 logger 是通知器的名稱:

      func (h *logger) SetUp(_ context.Context, cfg *notifiers.Config, _ notifiers.SecretGetter, _ notifiers.BindingResolver) error {
      	prd, err := notifiers.MakeCELPredicate(cfg.Spec.Notification.Filter)
      	if err != nil {
      		return fmt.Errorf("failed to create CELPredicate: %w", err)
      	}
      	h.filter = prd
      	return nil
      }
      
      func (h *logger) SendNotification(ctx context.Context, build *cbpb.Build) error {
      	// Include custom functionality here.
      	// This example logs the build.
      	if h.filter.Apply(ctx, build) {
      		log.V(1).Infof("printing build\n%s", prototext.Format(build))
      	} else {
      		log.V(1).Infof("build (%q, %q) did NOT match CEL filter", build.ProjectId, build.Id)
      	}
      
      	return nil
      }
      

      最終的 main.go 檔案應類似於以下檔案。在這個範例中,logger 是用來做為通知器的名稱。

      package main
      
      import (
      	"context"
      	"fmt"
      
      	cbpb "cloud.google.com/go/cloudbuild/apiv1/v2/cloudbuildpb"
      	"github.com/GoogleCloudPlatform/cloud-build-notifiers/lib/notifiers"
      	log "github.com/golang/glog"
      	"google.golang.org/protobuf/encoding/prototext"
      )
      
      
      func main() {
      	if err := notifiers.Main(new(logger)); err != nil {
      		log.Fatalf("fatal error: %v", err)
      	}
      }
      
      
      type logger struct {
      	filter notifiers.EventFilter
      }
      
      
      func (h *logger) SetUp(_ context.Context, cfg *notifiers.Config, _ notifiers.SecretGetter, _ notifiers.BindingResolver) error {
      	prd, err := notifiers.MakeCELPredicate(cfg.Spec.Notification.Filter)
      	if err != nil {
      		return fmt.Errorf("failed to create CELPredicate: %w", err)
      	}
      	h.filter = prd
      	return nil
      }
      
      func (h *logger) SendNotification(ctx context.Context, build *cbpb.Build) error {
      	// Include custom functionality here.
      	// This example logs the build.
      	if h.filter.Apply(ctx, build) {
      		log.V(1).Infof("printing build\n%s", prototext.Format(build))
      	} else {
      		log.V(1).Infof("build (%q, %q) did NOT match CEL filter", build.ProjectId, build.Id)
      	}
      
      	return nil
      }
      

    接下來,請設定通知器。

設定通知

  1. 編寫通知器設定檔,設定通知器並篩選建構事件:

    在以下示例通知器設定檔中,filter 欄位會使用 CEL 搭配可用變數 build,篩選狀態為 SUCCESS 的建構事件:

    apiVersion: cloud-build-notifiers/v1
    kind: YourNotifier
    metadata:
      name: logging-sample
    spec:
      notification:
        filter: build.status == Build.Status.SUCCESS

    其中:

    • logging-sample 是通知器的名稱。

    如要瞭解可用於篩選的其他欄位,請參閱「Build」資源。如需其他篩選範例,請參閱「使用 CEL 篩選建構事件」。

  2. 將通知器設定檔上傳至 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 是設定檔的名稱。
  3. 建構及部署通知程式:

    1. logging-sample 建立 Dockerfile:

      
      FROM golang AS build-env
      COPY . /go-src/
      WORKDIR /go-src/
      RUN go build -o /go-app .
      
      # From the Cloud Run docs:
      # https://cloud.google.com/run/docs/tutorials/pubsub#looking_at_the_code
      # Use the official Debian slim image for a lean production container.
      # https://hub.docker.com/_/debian
      # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
      FROM debian:buster-slim
      RUN set -x && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
          ca-certificates && \
          rm -rf /var/lib/apt/lists/*
      
      FROM gcr.io/distroless/base
      COPY --from=build-env /go-app /
      ENTRYPOINT ["/go-app", "--v=1", "--alsologtostderr"]
      
    2. 使用下列 cloudbuild.yaml 檔案建構及部署通知器。

      steps:
      - # Build the binary and put it into the builder image.
        name: gcr.io/cloud-builders/docker
        args: ['build', '--tag=gcr.io/$PROJECT_ID/logging-sample', '.']
      
      - # Push the container image to Container Registry
        name: gcr.io/cloud-builders/docker
        args: ['push', 'gcr.io/$PROJECT_ID/logging-sample']
      
      - # Deploy to Cloud Run
        name: google/cloud-sdk
        args: 
          - gcloud
          - run
          - deploy
          - logging-sample-notifier
          - --platform=managed
          - --region=us-central1
          - --image=gcr.io/$PROJECT_ID/logging-sample
          - --no-allow-unauthenticated
          - --update-env-vars=CONFIG_PATH=${_CONFIG_PATH}
      
      # Push the image with tags.
      images:
      - gcr.io/$PROJECT_ID/logging-sample

      其中:

      • _CONFIG_PATH 是通知器設定的路徑,例如 gs://BUCKET_NAME/CONFIG_FILE_NAME.yaml

    如要執行 cloudbuild.yaml,請將通知器路徑做為替換變數傳入。

     gcloud builds submit .  --substitutions=_CONFIG_PATH=gs://BUCKET_NAME/CONFIG_FILE_NAME
    
  4. 授予 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 專案編號。
  5. 建立服務帳戶,代表您的 Pub/Sub 訂閱身分:

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

    您可以使用 cloud-run-pubsub-invoker,或使用不同於 Google Cloud 專案中其他服務帳戶的名稱。

  6. 將 Cloud Run Invoker 權限授予 cloud-run-pubsub-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。
  7. 建立 cloud-builds 主題,以便接收通知器的建構更新訊息:

    gcloud pubsub topics create cloud-builds
    

    您也可以在建構設定檔中定義自訂主題名稱,讓訊息改為傳送至自訂主題。在這種情況下,您會建立具有相同自訂主題名稱的主題:

    gcloud pubsub topics create topic-name
    

    詳情請參閱接收建構作業通知的 Pub/Sub 主題

  8. 為通知器建立 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 專案的通知。下次叫用版本時,如果版本符合您設定的篩選器,您就會在頻道中收到通知。

測試通知

如要測試本指南中所用範例的通知,您可以執行 gcloud builds submit 指令來叫用建構。

在以下範例中,我們將 success.yaml 指定為設定路徑。執行這個指令後,應該會產生最少的成功建構作業。您應該也會看到建構記錄的輸出內容。

 gcloud builds submit --no-source --config=success.yaml

其中 success.yaml 為:

 steps:
 - name: busybox
   args: ["true"]

在以下範例中,我們將 failure.yaml 指定為設定路徑。執行這個指令應該會導致建構失敗。您不會看到建構記錄的輸出內容,而是會看到輸出內容,說明您在來源中指定的 CEL 篩選器沒有任何相符項目。

gcloud builds submit --no-source --config=failure.yaml

其中 failure.yaml 為:

 steps:
 - name: busybox
   args: ["false"]

如果您建立的通知器已設定為執行其他任務 (而非將輸出內容記錄至 Cloud Run 服務記錄),您也可以執行 gcloud builds submit 指令來測試通知。如要檢查與建構相關的錯誤,請查看服務的 Cloud Run 記錄。詳情請參閱「在 Cloud Run 中查看記錄」。

後續步驟