ADR 0004: Implementación de Pipeline de CI/CD con GitHub Actions
Contexto
El proyecto Bazaar requiere automatizar la validación del código y garantizar que la rama principal (main) esté siempre en un estado ejecutable, cumpliendo con las “Red Lines” y los Requisitos No Funcionales dictados por la cátedra. Al estar desarrollando un sistema distribuido con múltiples repositorios (microservicios backend, app mobile y backoffice), necesitamos una herramienta estandarizada para ejecutar pruebas, linters y gestionar la integración del código de todos los integrantes del equipo.
A partir del segundo checkpoint, el alcance del pipeline se extendió para cubrir también el despliegue continuo a producción (CD) de los cuatro microservicios backend sobre una instancia EC2 en AWS, y la generación automática de la APK de Android de la aplicación móvil mediante EAS Build.
Decisión
Se decide adoptar GitHub Actions como la plataforma oficial para la Integración Continua (CI) y Despliegue Continuo (CD) del proyecto.
CI — Integración Continua (todos los repositorios)
- Workflows automáticos: Se configuran pipelines en cada repositorio que se disparan automáticamente ante la creación o actualización de cada Pull Request.
- Validación de código: Los workflows ejecutan pruebas unitarias y herramientas de análisis estático (Linters/SAST).
- Bloqueo de merges: Se implementan reglas de protección en la rama
mainpara bloquear cualquier integración si los pasos de GitHub Actions fallan o no se alcanza la cobertura de código requerida (>80%).
CD — Despliegue continuo a producción (bazaar-user-api como repo raíz)
Se adopta bazaar-user-api como repositorio raíz del deploy. Al hacer push a main en ese repo, el workflow de GitHub Actions:
- Se conecta al servidor de producción (EC2 en AWS) vía SSH usando una clave almacenada como GitHub Secret.
- Clona o actualiza los cuatro repositorios de microservicios (
user-api,catalog-api,orders-api,payment-api) en la instancia EC2 usando HTTPS con un token de GitHub (GH_TOKEN). - Ejecuta
docker compose -f docker-compose.prod.yaml up -d --build --remove-orphanspara reconstruir y reiniciar únicamente los contenedores con cambios. - Elimina imágenes Docker huérfanas para liberar espacio en disco.
Los secrets necesarios se almacenan en GitHub Actions Secrets: EC2_HOST, EC2_USER, EC2_SSH_KEY, GH_TOKEN, GH_ORG.
La infraestructura de routing externo es un API Gateway en AWS con rutas /{proxy+} que apuntan a la IP pública de la instancia EC2 en los puertos correspondientes a cada servicio (8001–8004). No se utiliza nginx; el API Gateway maneja el routing externo y la red Docker interna (bazaar_net) maneja la comunicación entre servicios.
CD — Deploy web automático (bazaar-mobile → Vercel)
El repositorio bazaar-mobile está conectado directamente a Vercel. Cada push a main dispara automáticamente un nuevo deploy de la versión web de la aplicación (React Native Web), sin intervención manual ni configuración adicional en GitHub Actions. Vercel detecta el cambio, compila la app y publica la nueva versión en https://bazaar-mobile.vercel.app.
CD — Generación automática de APK (bazaar-mobile)
En el repositorio bazaar-mobile, un workflow de GitHub Actions separado se dispara al hacer push a main y ejecuta:
- Instalación de dependencias (
npm ci). - Autenticación con EAS usando
EXPO_TOKENalmacenado como GitHub Secret. eas build --platform android --profile preview --non-interactive, que compila la APK en los servidores de Expo Cloud (EAS Build) sin consumir recursos del runner de GitHub.- Descarga de la APK resultante y publicación como artifact del workflow, disponible para descarga directa desde la pestaña Summary de GitHub Actions durante 30 días.
El perfil preview en eas.json genera un .apk instalable directamente (sin Play Store), con las variables de entorno de producción (EXPO_PUBLIC_API_GATEWAY_URL, etc.) embebidas en el bundle en tiempo de build.
Consecuencias
Positivas
- Integración nativa: Al utilizar GitHub para alojar el código, Actions se integra de forma directa y transparente sin necesidad de configurar webhooks o plataformas de terceros.
- Aseguramiento de la calidad: Se previene automáticamente que código defectuoso o sin testear llegue a la rama principal, manteniendo el proyecto siempre en un estado desplegable.
- Trazabilidad: Cada Pull Request muestra visualmente el estado de las pruebas, facilitando la revisión de código entre los miembros del equipo.
- Deploy sin intervención manual: Un push a
mainenbazaar-user-apiactualiza los cuatro microservicios en producción sin necesidad de conectarse al servidor manualmente. - APK siempre actualizada: Cada push a
mainenbazaar-mobilegenera una APK nueva con el código más reciente, accesible para cualquier integrante del equipo sin depender de un build local ni de credenciales de Expo. - Separación de concerns: El pipeline de CI (validación) y el de CD (deploy/build) son workflows independientes, lo que permite que fallen de forma aislada sin bloquearse mutuamente.
Negativas y Riesgos
- Consumo de recursos: Existe un límite de minutos gratuitos mensuales en GitHub Actions. El build de la APK con EAS consume minutos adicionales del plan gratuito de Expo. El equipo debe monitorear el uso para no exceder las cuotas.
- Dependencia del proveedor: Si GitHub Actions o EAS Build sufren una caída, se bloquea tanto el flujo de validación como la generación de la APK y el deploy a producción.
- Build secuencial en EC2: La instancia
t3.micro(1 GB de RAM) no puede construir las cuatro imágenes Docker en paralelo sin quedarse sin memoria. El workflow construye los servicios de forma secuencial, lo que incrementa el tiempo total del deploy. - Deploy acoplado a un repo: Al usar
bazaar-user-apicomo repo raíz del deploy, un push en los otros repos no dispara automáticamente el pipeline de producción. El equipo debe hacer push o trigger manual desdebazaar-user-apipara reflejar cambios de otros servicios en producción. - Variables de entorno fuera del repo: Los
.envde producción viven en el servidor EC2 y no están versionados. Un cambio de variable de entorno requiere intervención manual en el servidor además del push al repo.