Introducción: Es importante comprender el panorama general

¡Hola! En la primera parte, discutimos las razones para construir un sistema de despliegue automático utilizando GitHub Webhook y los materiales necesarios. En esta segunda parte, antes de proceder con la implementación del código, vamos a tomar un tiempo para diseñar la arquitectura general y los procesos de cómo va a funcionar nuestro sistema de despliegue automático.

Los entornos de desarrollo de cada uno pueden variar ligeramente. Algunas personas pueden utilizar Raspberry Pi, otras pueden usar un VPS en la nube, y la estructura del proyecto que se va a desplegar también puede diferir entre los usuarios. En un entorno tan diverso, para construir un sistema de manera flexible y poder resolver problemas de manera autónoma, es más importante que nada comprender el flujo y el contexto general que los detalles del código.

En esta parte, tratemos de visualizar el gran esquema del sistema que vamos a construir y ver claramente qué papel desempeña cada componente.

Diagrama de flujo del sistema de despliegue automático

Flujo de trabajo del despliegue automático: Resumen del flujo general

El sistema de despliegue automático que implementaremos operará a través de una serie de procesos como los siguientes.

  1. Cambio de código en la máquina de trabajo local y push a Git: El desarrollador modifica el código en el entorno local y envía los cambios a una rama específica del repositorio de GitHub (por ejemplo, main o develop).

  2. Evento de webhook en el repositorio de GitHub: Una vez que GitHub detecta el evento push, envía una solicitud HTTP POST a la URL especificada a través del webhook previamente configurado.

  3. Transmisión de la solicitud al endpoint del webhook en el servidor de staging: La solicitud del webhook enviada por GitHub se dirige a una URL específica de nuestro servidor de staging (por ejemplo, https://deployer.example.com/webhook). Esta solicitud incluye información sobre el commit enviado, así como una lista de archivos modificados y otras cargas útiles (Payload).

  4. Recepción del webhook por el servicio FastAPI del servidor de staging: Nuestra aplicación FastAPI, que se ejecuta en el servidor de staging, recibe esta solicitud de webhook. A partir de aquí comienza el papel del servicio FastAPI.

El papel clave del servicio Webhook de FastAPI

El servicio de webhook que implementaremos con FastAPI no solo recibirá solicitudes, sino que también desempeñará los siguientes roles importantes.

Recepción y procesamiento inicial del webhook

La aplicación FastAPI proporciona un endpoint (por ejemplo, /webhook) que puede recibir solicitudes POST HTTP enviadas desde GitHub. Este endpoint analiza los encabezados y el cuerpo (Payload) de la solicitud para extraer la información necesaria.

Verificación de Secret

La seguridad es lo más importante en un sistema de despliegue automático. GitHub Webhook proporciona un valor Secret a través del encabezado X-Hub-Signature-256, que permite verificar la integridad de la solicitud. Nuestro servicio FastAPI debe incluir la lógica para usar este valor Secret y verificar si la solicitud proviene realmente de GitHub y si no ha sido alterada en el proceso. Si falla esta verificación, la solicitud será rechazada inmediatamente para bloquear accesos no autorizados.

Respuesta inmediata y trabajos en segundo plano

GitHub Webhook considera que la solicitud ha caducado si no recibe respuesta en un tiempo determinado (por defecto 10 segundos) y, por lo tanto, intenta nuevamente o registra el intento como fallido. Sin embargo, el proceso de despliegue real (Git Pull, construcción/reinicio de Docker, etc.) puede llevar más tiempo.

Por lo tanto, nuestro servicio FastAPI, inmediatamente después de recibir la solicitud del webhook y completar el procesamiento inicial, enviará una respuesta 200 OK a GitHub de inmediato. Luego, la lógica de despliegue real se ejecutará asíncronamente en segundo plano utilizando la función BackgroundTasks de FastAPI. Esto nos permitirá evitar problemas de timeout con GitHub mientras ejecutamos el trabajo de despliegue de manera estable.

Detalles de la lógica del manejador de despliegue

El manejador de despliegue que se ejecutará en segundo plano realizará las siguientes tareas clave.

Gestión de múltiples proyectos: Lectura de rutas de repositorio

Diseñaremos el servicio de webhook de FastAPI para manejar despliegues automáticos de múltiples repositorios (proyectos) de GitHub desde un solo servicio. Para ello, mapearemos y gestionaremos las rutas de los repositorios de GitHub y las rutas locales donde se desplegará cada proyecto mediante variables de entorno o archivos de configuración. Después de verificar qué repositorio generó el evento en el payload del webhook, nos moveremos a la ruta de ese proyecto para realizar las tareas de despliegue.

Configuraciones personalizadas por proyecto: Análisis del archivo .env (opcional)

Cada proyecto puede tener variables de entorno o configuraciones únicas que son necesarias durante la construcción o el despliegue. Por ejemplo, pueden variar las etiquetas de las imágenes de Docker, las opciones de construcción o los comandos para reiniciar servicios. Para gestionarlas eficientemente, implementaremos un análisis de los valores necesarios en el archivo .env del camino local de cada proyecto y los utilizaremos en la lógica de despliegue. Esto es de gran ayuda para implementar una lógica de despliegue flexible y personalizada.

Actualización del código: Ejecución de git pull

Este es el paso más básico. Usamos el módulo subprocess para ejecutar el comando git pull origin <branch_name> en el repositorio local del proyecto para obtener el último código del repositorio de GitHub.

Decisión de reconstrucción de imágenes Docker: Uso de git diff

En el caso de proyectos basados en Docker, si solo se realizaron cambios en el código, solo será suficiente con docker compose up -d. Sin embargo, si se han modificado archivos que afectan la construcción de la imagen, como Dockerfile o requirements.txt (en proyectos de Python), la imagen deberá ser reconstruida.

Utilizaremos el comando git diff para determinar si ha habido cambios en el Dockerfile o en otros archivos relacionados con la construcción entre el commit reciente y el anterior. Si se detecta un cambio, ejecutaremos docker compose up -d --build y, de lo contrario, solo ejecutaremos docker compose up -d para evitar reconstrucción innecesaria de las imágenes y reducir el tiempo de despliegue.

Ejecución de Docker Compose: Uso del módulo subprocess

Después de obtener el último código y decidir sobre la reconstrucción de imágenes, utilizaremos el módulo subprocess para ejecutar el comando docker compose up -d o docker compose up -d --build para actualizar los contenedores de Docker a su estado más reciente y reiniciar el servicio.

Registro: Registro de todo el proceso

Todo el proceso de despliegue (recepción del webhook, verificación, resultado de git pull, logs de la construcción/reinicio de Docker, etc.) debe documentarse en detalle. Esto es esencial para identificar causas y depurar en caso de problemas. Utilizaremos el módulo logging de Python para implementar el registro en un archivo.

Estrategia de despliegue y operación del servicio FastAPI

El servicio webhook de FastAPI que implementaremos debe ejecutarse de manera estable y constante en el servidor de staging.

Importancia del uso de Systemd Service

En lugar de ejecutar la aplicación FastAPI directamente en un contenedor Docker, se recomienda encarecidamente ejecutarla como un Systemd Service. Las razones son las siguientes.

  • Eficiencia de recursos: Es probable que en el servidor de staging ya estén instaladas herramientas necesarias para el despliegue como git, docker y docker compose. Hacer del servicio de webhook de FastAPI un contenedor Docker y, dentro de este, instalar git o docker para controlar el daemon de docker aumentaría innecesariamente el tamaño del contenedor y podría causar problemas de configuración y seguridad complejos, como docker-in-docker o docker-out-of-docker.

  • Manejo simplificado: Systemd es el estándar para la gestión de servicios en sistemas Linux. Al registrar la aplicación FastAPI como un servicio de Systemd, estará disponible la opción de inicio automático al arrancar el servidor, comprobar el estado del servicio y reiniciar/detenerlo fácilmente, todo ello con una gestión integrada y simplificada a nivel del sistema operativo.

  • Uso de recursos del sistema: Al ejecutar la aplicación FastAPI mediante Systemd, la aplicación podrá llamar directamente a los comandos git y docker instalados en el sistema para realizar las tareas de despliegue, aprovechando así los recursos existentes del sistema de manera más eficiente.

En la próxima parte, detallaré cómo registrar y administrar la aplicación FastAPI como un servicio de Systemd.

Proxies reversos e HTTPS a través de Nginx/Apache2

Como se enfatizó en la primera parte, exponer directamente la aplicación FastAPI a Internet es muy inseguro. Por lo tanto, utilizaremos un servidor web como Nginx o Apache2 como Proxy Reverso para transmitir de manera segura las solicitudes webhook a la aplicación FastAPI.

Además, GitHub Webhook recomienda encarecidamente usar la comunicación HTTPS, por lo que debemos preparar un subdominio dedicado como deployer.example.com y obtener un certificado HTTPS a través de servicios como Let's Encrypt para aplicarlo en el servidor web. Esto permitirá que toda la comunicación externa esté encriptada, mejorando así la seguridad.

Monitoreo y depuración

Usaremos dos métodos para verificar si el sistema de despliegue automático está funcionando correctamente y para identificar causas en caso de problemas.

  • Archivos de registro del servicio FastAPI: La aplicación FastAPI que implementaremos registrará cada etapa del proceso de despliegue en su propio archivo de registro. Podemos consultar este archivo para saber si el despliegue fue exitoso y conocer los mensajes de error que puedan haber surgido.

  • Systemd journalctl: Dado que estamos gestionando el servicio FastAPI con Systemd, podemos verificar y analizar la salida estándar y los logs de error del servicio en tiempo real usando el comando journalctl -u your-fastapi-service.service.

Conclusión: Avance de la siguiente parte

En esta segunda parte, hemos explorado la arquitectura general del sistema de despliegue automático utilizando GitHub Webhook, así como el papel clave del servicio FastAPI y las estrategias de despliegue y operación. Espero que ahora tengan el gran esquema en mente.

En la tercera parte, basados en el diseño realizado hoy, abordaremos el proceso de codificación del servicio de webhook de FastAPI, la configuración del Webhook de GitHub y el registro como servicio de Systemd. ¡Estén atentos!


Serie para construir mi propio sistema de despliegue automático utilizando GitHub Webhook

Parte 1 - ¿Por qué hacerlo uno mismo?