Como criar seu próprio notificador

O Cloud Build pode notificar você sobre atualizações no status da versão enviando notificações para os canais desejados. Além dos notificadores mantidos pelo Cloud Build, como Slack ou SMTP, você também pode usar a biblioteca fornecida na cloud-build-notifiers para criar seu próprio notificador.

Nesta página, explicamos como criar seu próprio notificador.

Antes de começar

  • Ative as APIs Cloud Build, Cloud Run, Pub/Sub, and Secret Manager.

    Ative as APIs

  • Instale a linguagem de programação Go.

  • Instale o Google Cloud CLI.

Como configurar

  1. Abra uma janela de terminal na máquina.

  2. Clone e navegue até o repositório cloud-build-notifiers:

      git clone https://github.com/GoogleCloudPlatform/cloud-build-notifiers.git && cd cloud-build-notifiers
    
  3. Adicione um diretório para seu próprio notificador e navegue até ele, em que DIRECTORY_NAME é o nome do diretório:

      mkdir DIRECTORY_NAME && cd DIRECTORY_NAME
    
  4. Inicialize os módulos do Go no novo diretório, em que DIRECTORY_NAME é o nome do novo diretório:

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

    Agora você verá um arquivo go.mod no diretório.

  5. Adicione a seguinte linha ao arquivo go.mod para garantir que você esteja usando a versão mais recente dos notificadores:

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

Suas dependências agora estão configuradas e você está pronto para criar seu próprio notificador.

Como criar seu próprio notificador

O cloud-build-notifiers contém um diretório lib/notifiers. No diretório lib/notifiers, você verá um arquivo chamado notifier.go. Esse arquivo contém o framework que pode ser usado para criar seu próprio notificador.

Será necessário definir dois métodos para criar um notificador no arquivo principal.

  1. No novo diretório, crie um arquivo chamado main.go.

  2. Em main.go, importe o framework da biblioteca do notificador e outras dependências:

    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. Defina um método principal para o notificador. Neste exemplo, logger é o nome do notificador:

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

    O main usa o Main definido no arquivo notifier.go, que é usado para configurar binários de notificação.

  4. Defina uma estrutura para o notificador, em que você definirá as variáveis da interface. Neste exemplo, logger é o nome do notificador. Exemplo:

    type logger struct {
    	filter notifiers.EventFilter
    }
    

Em seguida, você adicionará a funcionalidade do notificador. A interface do notificador é definida por dois métodos:

  • SetUp: o método SetUp aceita uma configuração, busca secrets e extrai filtros especificados da configuração e os armazena como um predicado de Common Expression Language que pode ser usado para enviar notificações. Para saber mais sobre CEL, consulte o repositório cel-spec (em inglês).
  • SendNotification: o método SendNotification é usado para enviar notificações ao canal ou serviço desejado.

    A definição do notificador está disponível em notifier.go e na documentação do Go.

    No exemplo abaixo, a interface do notificador é definida usando o SetUp e o método SendNotification para imprimir registros de versão, com logger como o nome do notificador:

    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
    }
    

    O arquivo main.go final será semelhante ao arquivo a seguir. Neste exemplo, logger é usado como o nome do notificador.

    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
    }
    

    Agora que você tem o Notificador definido, siga as etapas abaixo para configurá-lo.

Como configurar notificações

  1. Grave um arquivo de configuração do notificador para configurar seu notificador e filtrar eventos de build:

    No arquivo de configuração do notificador do exemplo a seguir, o campo filter usa CEL com a variável disponível, build, para filtrar eventos do build com o status SUCCESS:

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

    Em que:

    • logging-sample é o nome do notificador.

    Para ver outros campos que podem ser filtrados, consulte o recurso Build. Para outros exemplos de filtragem, consulte Como usar a CEL para filtrar eventos de build.

  2. Faça o upload do arquivo de configuração do notificador em um bucket do Cloud Storage:

    1. Se você não tiver um bucket do Cloud Storage, execute o seguinte comando para criar um bucket, em que BUCKET_NAME é o nome que você quer dar ao bucket, sujeito aos requisitos de nomenclatura.

      gsutil mb gs://BUCKET_NAME/
      
    2. Faça o upload do arquivo de configuração do notificador para o bucket:

      gsutil cp CONFIG_FILE_NAME gs://BUCKET_NAME/CONFIG_FILE_NAME
      

      Em que:

      • BUCKET_NAME é o nome do bucket.
      • CONFIG_FILE_NAME é o nome do seu arquivo de configuração.
  3. Crie e implante o notificador:

    1. Crie um Dockerfile para o logging-sample:

      
      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. Crie e implante o notificador usando o arquivo cloudbuild.yaml a seguir.

      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

      Em que:

      • _CONFIG_PATH é o caminho para a configuração do notificador, como gs://BUCKET_NAME/CONFIG_FILE_NAME.yaml.

    Para executar o cloudbuild.yaml, transmita o caminho do notificador como uma variável de substituição.

     gcloud builds submit .  --substitutions=_CONFIG_PATH=gs://BUCKET_NAME/CONFIG_FILE_NAME
    
  4. Conceda permissões do Pub/Sub para criar tokens de autenticação no seu projeto:

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

    Em que:

    • PROJECT_ID é o ID do seu projeto do Google Cloud.
    • PROJECT_NUMBER é o número do projeto do Google Cloud.
  5. Crie uma conta de serviço para representar sua identidade de assinatura do Pub/Sub:

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

    Você pode usar cloud-run-pubsub-invoker ou um nome exclusivo no seu projeto do Google Cloud.

  6. Conceda à conta de serviço cloud-run-pubsub-invoker a permissão Invoker do Cloud Run:

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

    Em que:

    • SERVICE_NAME é o nome do serviço do Cloud Run em que você está implantando a imagem;
    • PROJECT_ID é o ID do seu projeto do Google Cloud.
  7. Crie o tópico cloud-builds para receber mensagens de atualização da build para seu notificador:

    gcloud pubsub topics create cloud-builds
    
  8. Crie um assinante de push do Pub/Sub para seu notificador:

     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
    

    Em que:

    • subscriber-id é o nome que você quer dar à sua assinatura.
    • service-url é o URL gerado pelo Cloud Run para o novo serviço.
    • project-id é o ID do seu projeto do Google Cloud.

Agora as notificações do seu projeto do Cloud Build estão configuradas. Da próxima vez que você invocar uma build, você receberá uma notificação no seu canal caso a build corresponda ao filtro que você configurou.

Notificações de teste

Para testar a funcionalidade de notificação para o exemplo usado neste guia, é possível invocar um build executando o comando gcloud builds submit.

No exemplo a seguir, especificamos success.yaml como o caminho de configuração. A execução desse comando deve resultar em um build bem-sucedido mínimo. Você também verá uma saída dos seus registros de criação.

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

Onde success.yaml é:

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

No exemplo a seguir, especificamos failure.yaml como o caminho de configuração. A execução desse comando deve resultar em uma criação com falha. Em vez de ver uma saída dos registros de compilação, você verá uma saída informando que não houve correspondência para os filtros CEL especificados na sua origem.

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

Onde failure.yaml é:

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

Se você criou um notificador configurado para executar outra tarefa diferente da geração de registros de saída para os registros de serviço do Cloud Run, também é possível executar o comando gcloud builds submit para testar a funcionalidade de notificações. Para examinar erros associados à versão, verifique os registros do Cloud Run do seu serviço. Para saber mais, consulte Como visualizar registros no Cloud Run.

A seguir