Crea tu propio notificador

Cloud Build puede notificarte sobre actualizaciones del estado de la compilación enviándote notificaciones a los canales deseados, como Slack o el servidor SMTP. Actualmente, Cloud Build proporciona y mantiene imágenes implementables del notificador para Slack, SMTP, BigQuery y HTTP en el repositorio cloud-build-notifiers.

También puedes usar la biblioteca proporcionada en el repositorio cloud-build-notifiers para crear tu propio notificador a fin de enviar actualizaciones de notificaciones a otros canales. En esta página, se explica cómo puedes crear tu propio notificador.

Antes de comenzar

  • Habilita las API de Cloud Build, Cloud Run, Pub/Sub, and Secret Manager.

    Habilita las API

  • Instala el lenguaje de programación Go.

  • Instala el SDK de Cloud.

Configuración

  1. Abre una ventana de la terminal en tu máquina.

  2. Clona el repositorio cloud-build-notifiers y navega hacia él:

      git clone https://github.com/GoogleCloudPlatform/cloud-build-notifiers.git && cd cloud-build-notifiers
    
  3. Agrega un directorio para tu propio notificador y navega hasta él, en el que DIRECTORY_NAME es el nombre del directorio:

      mkdir DIRECTORY_NAME && cd DIRECTORY_NAME
    
  4. Inicializa los módulos de Go en tu directorio nuevo, en el que DIRECTORY_NAME es el nombre de tu directorio nuevo:

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

    Deberías ver un archivo go.mod en el directorio.

  5. Agrega la siguiente línea a tu archivo go.mod para asegurarte de usar la última versión de los notificadores:

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

Ahora tus dependencias están configuradas y estás listo para crear tu propio notificador.

Crea tu propio notificador

El cloud-build-notifiers contiene un directorio lib/notifiers. En el directorio lib/notifiers, verás un archivo llamado notifier.go. Este archivo contiene el framework que puedes usar para crear tu propio notificador.

Deberás definir dos métodos para crear un notificador en el archivo principal.

  1. En el directorio nuevo, crea un archivo llamado main.go.

  2. En main.go, importa el framework de la biblioteca de los notificadores y cualquier otra dependencia:

    package main
    
    import (
            "context"
            "fmt"
    
            cbpb "google.golang.org/genproto/googleapis/devtools/cloudbuild/v1"
            log "github.com/golang/glog"
            "github.com/GoogleCloudPlatform/cloud-build-notifiers/lib/notifiers"
            "github.com/golang/protobuf/proto"
    )
  3. Define un método principal para el notificador. En este ejemplo, logger es el nombre del notificador:

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

    El método main usa el método Main definido en el archivo notifier.go, que se usa para configurar objetos binarios del notificador.

  4. Define una estructura para tu notificador, en la que definirás las variables para tu interfaz. En este ejemplo, logger es el nombre del notificador. P. ej.

    type logger struct {
        filter notifiers.EventFilter
    }

A continuación, agregarás la funcionalidad del notificador. La interfaz del notificador se define mediante dos métodos:

  • SetUp: El método SetUp acepta una configuración, recupera secretos y extrae filtros específicos de la configuración, y los almacena como un predicado de Common Expression Language que se puede usar para enviar notificaciones. Para obtener más información sobre CEL, consulta el repositorio cel-spec.
  • SendNotification: El método SendNotification es el que se usa para enviar notificaciones al canal o servicio deseado.

    La definición de los notificadores está disponible en notifier.go y en la documentación de Go.

    En el siguiente ejemplo, la interfaz del notificador se define mediante el método SetUp y el método SendNotification para imprimir registros de compilación, con logger como el nombre de tu 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", proto.MarshalTextString(build))
        } else {
            log.V(1).Infof("build (%q, %q) did NOT match CEL filter", build.ProjectId, build.Id)
        }
    
        return nil
    }

    El archivo main.go final debería ser similar al siguiente archivo. En este ejemplo, logger se usa como nombre del notificador.

    package main
    
    import (
            "context"
            "fmt"
    
            cbpb "google.golang.org/genproto/googleapis/devtools/cloudbuild/v1"
            log "github.com/golang/glog"
            "github.com/GoogleCloudPlatform/cloud-build-notifiers/lib/notifiers"
            "github.com/golang/protobuf/proto"
    )
    
    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", proto.MarshalTextString(build))
        } else {
            log.V(1).Infof("build (%q, %q) did NOT match CEL filter", build.ProjectId, build.Id)
        }
    
        return nil
    }

    Ahora que definiste el notificador, puedes seguir los pasos que se indican a continuación para configurarlo.

Configura notificaciones

  1. Escribe un archivo de configuración del notificador para configurar el notificador y filtrar los eventos de compilación:

    En el siguiente ejemplo de archivo de configuración del notificador, el campo filter usa CEL con la variable disponible, build, para filtrar los eventos de compilación con un estado SUCCESS:

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

    Aquí:

    • logging-sample es el nombre del notificador.

    Para ver campos adicionales por los que puedes filtrar, consulta el recurso Compilar. Para ver más ejemplos de filtrado, consulta Cómo usar CEL para filtrar eventos de compilación.

  2. Sube tu archivo de configuración de notificador a un bucket de Cloud Storage:

    1. Si no tienes un depósito de Cloud Storage, ejecuta el siguiente comando para crear un depósito, en el que BUCKET_NAME es el nombre que deseas asignar a tu depósito, sujeto a los requisitos de nombres.

      gsutil mb gs://BUCKET_NAME/
      
    2. Sube el archivo de configuración del notificador a tu bucket:

      gsutil cp CONFIG_FILE_NAME gs://BUCKET_NAME/CONFIG_FILE_NAME
      

      Aquí:

      • BUCKET_NAME es el nombre de tu depósito.
      • CONFIG_FILE_NAME es el nombre de tu archivo de configuración.
  3. Compila e implementa tu notificador:

    1. Crea un Dockerfile para 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. Compila e implementa el notificador con el siguiente archivo 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

      Aquí:

      • _CONFIG_PATH es la ruta a la configuración del notificador, como gs://BUCKET_NAME/CONFIG_FILE_NAME.yaml.

    Para ejecutar cloudbuild.yaml, pasa la ruta del notificador como una variable de sustitución.

     gcloud builds submit .  --substitutions=_CONFIG_PATH=gs://BUCKET_NAME/CONFIG_FILE_NAME
    
  4. Otorga permisos de Pub/Sub para crear tokens de autenticación en tu proyecto:

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

    Aquí:

    • PROJECT_ID es el ID de tu proyecto de Cloud.
    • PROJECT_NUMBER es el número de proyecto de Cloud.
  5. Crea una cuenta de servicio para representar tu identidad de suscripción de Pub/Sub:

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

    Puedes usar cloud-run-pubsub-invoker o un nombre único dentro de tu proyecto de Google Cloud.

  6. Otorga el permiso Invoker de Cloud Run a la cuenta de servicio de 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
    

    Aquí:

    • SERVICE_NAME es el nombre del servicio de Cloud Run en el que se implementa la imagen.
    • PROJECT_ID es el ID de tu proyecto de Cloud.
  7. Después de habilitar la API de Pub/Sub, deberías ver el tema cloud-builds que se creó de forma automática en la página Temas de Pub/Sub. Si no ves el tema cloud-builds, ejecuta el siguiente comando para crear de forma manual el tema a fin de recibir mensajes sobre la actualización de la compilación para tu notificador:

    gcloud pubsub topics create cloud-builds
    
  8. Crea un suscriptor de envío de Pub/Sub para tu 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
    

    Aquí:

    • SUBSCRIBER_ID es el nombre que quieres darle a tu suscripción.
    • SERVICE_URL es la URL generada por Cloud Run para tu nuevo servicio.
    • PROJECT_ID es el ID de tu proyecto de Cloud.

Las notificaciones de tu proyecto de Cloud Build ya están configuradas. La próxima vez que invoques una compilación, recibirás una notificación en tu canal si la compilación coincide con el filtro que configuraste.

Notificaciones de prueba

A fin de probar la funcionalidad de notificaciones para el ejemplo que se usa en esta guía, puedes invocar una compilación mediante la ejecución del comando gcloud builds submit.

En el siguiente ejemplo, especificamos success.yaml como la ruta de configuración. La ejecución de este comando debería generar una compilación exitosa mínima. También deberías poder ver un resultado de tus registros de compilación.

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

En el ejemplo anterior, success.yaml es:

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

En el siguiente ejemplo, especificamos failure.yaml como la ruta de configuración. La ejecución de este comando debería generar una compilación con errores. En lugar de ver un resultado de tus registros de compilación, verás un resultado que te informa que no hubo coincidencia con los filtros CEL que especificaste en la fuente.

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

En el ejemplo anterior, failure.yaml es:

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

Si creaste un notificador configurado para realizar otra tarea que no sea registrar el resultado en los registros del servicio de Cloud Run, también puedes ejecutar el comando gcloud builds submit para probar la funcionalidad de notificación. Para examinar los errores asociados con tu compilación, verifica los registros de Cloud Run correspondientes al servicio. Para obtener más información, consulta Visualiza registros en Cloud Run.

¿Qué sigue?