Prueba, sincroniza y, luego, implementa tus DAG desde GitHub

Cloud Composer 1 | Cloud Composer 2

En esta guía, se explica cómo crear una canalización de CI/CD para probar, sincronizar y, luego, implementar DAG en tu entorno de Cloud Composer desde tu repositorio de GitHub.

Si solo deseas sincronizar datos de otros servicios, consulta Cómo transferir datos de otros servicios.

Descripción general de la canalización de CI/CD

Diagrama de la arquitectura en el que se muestran los pasos del flujo. El envío previo y la revisión de RR.PP. están en la sección de GitHub, y la verificación manual y de sincronización del DAG están en la sección de Google Cloud.
Figura 1. Diagrama de arquitectura en el que se muestran los pasos del flujo (haz clic para ampliar)

La canalización de CI/CD que probar, sincronizar e implementar los DAG sigue estos pasos:

  1. Realiza un cambio en un DAG y envíalo a una rama de desarrollo en tu repositorio.

  2. Abres una solicitud de extracción en la rama principal de tu repositorio.

  3. Cloud Build ejecuta pruebas de unidades para verificar que el DAG sea válido.

  4. La solicitud de extracción está aprobada y se combina con la rama principal de tu repositorio.

  5. Cloud Build sincroniza tu entorno de desarrollo de Cloud Composer con estos nuevos cambios.

  6. Verifica que el DAG se comporte como se espera en tu entorno de desarrollo.

  7. Si tu DAG funciona como se espera, súbelo a tu entorno de producción de Cloud Composer.

Objetivos

Antes de comenzar

  • En esta guía, se supone que trabajas con dos entornos idénticos de Cloud Composer: uno de desarrollo y uno de producción.

    A los fines de esta guía, debes configurar una canalización de CI/CD solo para el entorno de desarrollo. Asegúrate de que el entorno que usas no sea de producción.

  • En esta guía, se supone que tienes tus DAG y sus pruebas almacenados en un repositorio de GitHub.

    La canalización de CI/CD de ejemplo demuestra el contenido de un repositorio de ejemplo. Los DAG y las pruebas se almacenan en el directorio dags/, con los archivos de requisitos, el archivo de restricciones y los archivos de configuración de Cloud Build almacenados en el nivel superior. La utilidad de sincronización de DAG y sus requisitos se encuentran en el directorio utils.

    Esta estructura se puede usar para entornos de Airflow 1, Airflow 2, Cloud Composer 1 y Cloud Composer 2.

Crea un trabajo de verificación previa al envío y pruebas de unidades

El primer trabajo de Cloud Build ejecuta una verificación antes del envío, que ejecuta pruebas de unidades para tus DAG.

Cómo agregar pruebas de unidades

Si aún no lo hiciste, crea pruebas de unidades para tus DAG. Guarda estas pruebas junto con los DAG en tu repositorio, cada una con el sufijo _test. Por ejemplo, el archivo de prueba para el DAG en example_dag.py es example_dag_test.py. Estas son las pruebas que se ejecutan como una verificación previa al envío en tu repositorio.

Crea la configuración de YAML de Cloud Build para la verificación previa al envío

En tu repositorio, crea un archivo YAML llamado test-dags.cloudbuild.yaml que configure tu trabajo de Cloud Build para las verificaciones de envío previo. Hay tres pasos:

  1. Instala las dependencias que necesitan tus DAG.
  2. Instala las dependencias que necesitan tus pruebas de unidades.
  3. Ejecuta las pruebas del DAG.

steps:
  # install dependencies
  - name: python:3.8-slim
    entrypoint: pip
    args: ["install", "-r", "requirements.txt", "-c", "constraints.txt", "--user"]

  - name: python:3.8-slim
    entrypoint: pip
    args: ["install", "-r", "requirements-test.txt", "--user"]

  # run in python 3.8 which is latest version in Cloud Composer
  - name: python:3.8-slim
    entrypoint: python3.8
    args: ["-m", "pytest", "-s", "dags/"]

Crea el activador de Cloud Build para la verificación previa al envío

Sigue la guía Cómo compilar repositorios desde GitHub para crear un activador basado en una app de GitHub con los siguientes parámetros de configuración:

  • Nombre: test-dags

  • Evento: solicitud de extracción

  • Fuente: Repositorio: Elige tu repositorio.

  • Fuente: Rama base: ^main$ (cambia main por el nombre de la rama base del repositorio, si es necesario).

  • Fuente (Control de comentarios: no obligatorio)

  • Configuración de compilación: Archivo de configuración de Cloud Build: /test-dags.cloudbuild.yaml (la ruta de acceso al archivo de compilación)

Crea un trabajo de sincronización de DAG y agrega una secuencia de comandos de utilidad de DAG

A continuación, configura un trabajo de Cloud Build que ejecute una secuencia de comandos de utilidad de DAG. La secuencia de comandos de utilidad en este trabajo sincroniza tus DAG con tu entorno de Cloud Composer después de que se combinan con la rama principal en tu repositorio.

Agrega la secuencia de comandos de utilidad de los DAG

Agrega la secuencia de comandos de utilidad del DAG a tu repositorio. Esta secuencia de comandos de utilidad copia todos los archivos DAG del directorio dags/ de tu repositorio en un directorio temporal ignora todos los archivos de Python que no son de DAG. Luego, la secuencia de comandos usa la biblioteca cliente de Cloud Storage para subir todos los archivos de ese directorio temporal al directorio dags/ en el bucket de tu entorno de Cloud Composer.

from __future__ import annotations

import argparse
import glob
import os
from shutil import copytree, ignore_patterns
import tempfile

# Imports the Google Cloud client library
from google.cloud import storage

def _create_dags_list(dags_directory: str) -> tuple[str, list[str]]:
    temp_dir = tempfile.mkdtemp()

    # ignore non-DAG Python files
    files_to_ignore = ignore_patterns("__init__.py", "*_test.py")

    # Copy everything but the ignored files to a temp directory
    copytree(dags_directory, f"{temp_dir}/", ignore=files_to_ignore, dirs_exist_ok=True)

    # The only Python files left in our temp directory are DAG files
    # so we can exclude all non Python files
    dags = glob.glob(f"{temp_dir}/*.py")
    return (temp_dir, dags)

def upload_dags_to_composer(
    dags_directory: str, bucket_name: str, name_replacement: str = "dags/"
) -> None:
    """
    Given a directory, this function moves all DAG files from that directory
    to a temporary directory, then uploads all contents of the temporary directory
    to a given cloud storage bucket
    Args:
        dags_directory (str): a fully qualified path to a directory that contains a "dags/" subdirectory
        bucket_name (str): the GCS bucket of the Cloud Composer environment to upload DAGs to
        name_replacement (str, optional): the name of the "dags/" subdirectory that will be used when constructing the temporary directory path name Defaults to "dags/".
    """
    temp_dir, dags = _create_dags_list(dags_directory)

    if len(dags) > 0:
        # Note - the GCS client library does not currently support batch requests on uploads
        # if you have a large number of files, consider using
        # the Python subprocess module to run gsutil -m cp -r on your dags
        # See https://cloud.google.com/storage/docs/gsutil/commands/cp for more info
        storage_client = storage.Client()
        bucket = storage_client.bucket(bucket_name)

        for dag in dags:
            # Remove path to temp dir
            dag = dag.replace(f"{temp_dir}/", name_replacement)

            try:
                # Upload to your bucket
                blob = bucket.blob(dag)
                blob.upload_from_filename(dag)
                print(f"File {dag} uploaded to {bucket_name}/{dag}.")
            except FileNotFoundError:
                current_directory = os.listdir()
                print(
                    f"{name_replacement} directory not found in {current_directory}, you may need to override the default value of name_replacement to point to a relative directory"
                )
                raise

    else:
        print("No DAGs to upload.")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
    )
    parser.add_argument(
        "--dags_directory",
        help="Relative path to the source directory containing your DAGs",
    )
    parser.add_argument(
        "--dags_bucket",
        help="Name of the DAGs bucket of your Composer environment without the gs:// prefix",
    )

    args = parser.parse_args()

    upload_dags_to_composer(args.dags_directory, args.dags_bucket)

Crear la configuración de YAML de Cloud Build para sincronizar DAG

En tu repositorio, crea un archivo YAML llamado add-dags-to-composer.cloudbuild.yaml que configure tu trabajo de Cloud Build para sincronizar DAG. En él, hay dos pasos:

  1. Instala las dependencias que necesita la secuencia de comandos de la utilidad DAG.

  2. Ejecuta la secuencia de comandos de utilidad para sincronizar los DAG en tu repositorio con tu entorno de Cloud Composer.

steps:
  # install dependencies
  - name: python
    entrypoint: pip
    args: ["install", "-r", "utils/requirements.txt", "--user"]

  # run
  - name: python
    entrypoint: python
    args: ["utils/add_dags_to_composer.py", "--dags_directory=${_DAGS_DIRECTORY}", "--dags_bucket=${_DAGS_BUCKET}"]

Crea el activador de Cloud Build

Sigue la guía Cómo compilar repositorios desde GitHub para crear un activador basado en una app de GitHub con los siguientes parámetros de configuración:

  • Nombre: add-dags-to-composer

  • Evento: envío a una rama

  • Fuente: Repositorio: Elige tu repositorio.

  • Fuente: Rama base: ^main$ (cambia main por el nombre de la rama base del repositorio, si es necesario).

  • Fuente - Filtro de archivos incluidos (glob): dags/**

  • Configuración de compilación: Archivo de configuración de Cloud Build: /add-dags-to-composer.cloudbuild.yaml (la ruta de acceso al archivo de compilación)

En la Configuración avanzada, agrega dos variables de sustitución:

  • _DAGS_DIRECTORY: Es el directorio en el que se encuentran los DAG en tu repositorio. Si usas el repositorio de ejemplo de esta guía, es dags/.

  • _DAGS_BUCKET: Es el bucket de Cloud Storage que contiene el directorio dags/ en tu entorno de desarrollo de Cloud Composer. Omite el prefijo gs://. Por ejemplo: us-central1-example-env-1234ab56-bucket

Prueba tu canalización de CI/CD

En esta sección, sigue un flujo de desarrollo de DAG que usa tus activadores de Cloud Build recién creados.

Ejecuta un trabajo previo al envío

Crea una solicitud de extracción a tu rama principal para probar la compilación. Busca la verificación previa al envío en la página. Haz clic en Detalles y elige Ver más detalles en Google Cloud Build para ver tus registros de compilación en la consola de Google Cloud.

Captura de pantalla de una verificación de GitHub llamada test-dags con una flecha roja que apunta al nombre del proyecto entre paréntesis
Figura 2: Captura de pantalla del estado de la verificación previa al envío de Cloud Build en GitHub (haz clic para ampliar)

Si falló la verificación previa al envío, consulta Soluciona errores de compilación.

Valida que tu DAG funcione en tu entorno de desarrollo de Cloud Composer

Después de aprobar tu solicitud de extracción, combínala con tu rama principal. Usa la consola de Google Cloud para ver los resultados de la compilación. Si tienes muchos activadores de Cloud Build, puedes filtrar tus compilaciones según el nombre del activador add-dags-to-composer.

Una vez que el trabajo de sincronización de Cloud Build se ejecute correctamente, el DAG sincronizado aparecerá en tu entorno de desarrollo de Cloud Composer. Allí, puedes validar que el DAG funcione como se espera.

Agrega el DAG a tu entorno de producción

Una vez que el DAG funcione como se espera, agrégalo de forma manual a tu entorno de producción. Para hacerlo, sube el archivo DAG al directorio dags/ en el bucket de tu entorno de producción de Cloud Composer.

Si tu trabajo de sincronización de DAG falló o si tu DAG no se comporta como se espera en tu entorno de desarrollo de Cloud Composer, consulta Soluciona errores de compilación.

Soluciona errores de compilación

En esta sección, se explica cómo abordar situaciones comunes de fallas de compilación.

¿Qué sucede si falla la verificación previa al envío?

Desde tu solicitud de extracción, haz clic en Detalles y elige Ver más detalles en Google Cloud Build para ver tus registros de compilación en la consola de Google Cloud. Utiliza estos registros para depurar el problema con tu DAG. Una vez que hayas resuelto los problemas, confirma la corrección y envíala a tu rama. La verificación previa al envío se ejecuta de nuevo, y puedes seguir iterando con los registros como herramienta de depuración.

¿Qué sucede si mi trabajo de sincronización de DAG falló?

Usa la consola de Google Cloud para ver los resultados de la compilación. Si tienes muchos activadores de Cloud Build, puedes filtrar tus compilaciones según el nombre del activador add-dags-to-composer. Examina los registros del trabajo de compilación y resuelve los errores. Si necesitas ayuda adicional para resolver los errores, usa los canales de asistencia.

¿Qué sucede si mi DAG no funciona correctamente en mi entorno de Cloud Composer?

Si tu DAG no funciona como se espera en tu entorno de desarrollo de Cloud Composer, no lo promuevas de forma manual a tu entorno de producción de Cloud Composer. Como alternativa, toma una de las siguientes medidas:

  • Revierte la solicitud de extracción con los cambios que rompieron tu DAG para restablecerlo al estado inmediatamente antes de los cambios (esto también revierte todos los demás archivos en esa solicitud de extracción).
  • Crea una solicitud de extracción nueva para revertir de forma manual los cambios en el DAG dañado.
  • Crea una solicitud de extracción nueva para corregir los errores en tu DAG.

Seguir cualquiera de estos pasos activa una nueva verificación previa al envío y, después de la combinación, el trabajo de sincronización de DAG.

¿Qué sigue?