React SPA Monorepo CI/CD: cómo automatizar pruebas y desplegar solo lo que cambió
La mayoría de los artículos sobre monorepos se detienen en la estructura de carpetas. Te muestran cómo organizar aplicaciones y paquetes, quizás agregar una configuración compartida, y lo dan por terminado. Pero la estructura de carpetas no es lo que hace que un monorepo esté listo para producción. Lo que realmente importa es si tu pipeline de CI/CD puede detectar qué cambió, ejecutar las puertas de validación correctas y desplegar solo las aplicaciones que necesitan moverse.
Esa es la diferencia entre un monorepo que se ve limpio y uno que entrega de manera confiable. El repositorio react-spa-monorepo-cicd está construido alrededor de esa distinción. Es una arquitectura de referencia con 7 puertas de validación, detección inteligente de cambios, cobertura E2E con Playwright, ramas de staging y producción, y rollback automatizado sobre SSH y rsync. Este artículo desglosa por qué cada una de esas piezas importa y cómo encajan en un sistema de entregas que escala.
Por qué CI/CD es el verdadero valor en un monorepo SPA
Un monorepo por sí solo no reduce el riesgo de despliegue. Poner tres aplicaciones en un repositorio sin automatización compartida es simplemente una carpeta compartida con conflictos de merge adicionales. El beneficio real proviene de la validación consistente, la automatización compartida y el despliegue selectivo, ninguno de los cuales ocurre automáticamente porque tus aplicaciones comparten un package.json raíz.
El pipeline importa más que el árbol de carpetas. Un monorepo con CI/CD sólido le da a cada aplicación los mismos estándares de validación, la misma ruta de despliegue y el mismo proceso de rollback. Un monorepo sin CI/CD te da tres aplicaciones que son más difíciles de liberar independientemente que si vivieran en repositorios separados.
Por esto el repositorio react-spa-monorepo-cicd se posiciona como una arquitectura de referencia para múltiples aplicaciones con despliegue automatizado y validación CI/CD completa, no solo como una plantilla inicial. El valor está en el sistema de entregas, no en la disposición del workspace.
Cómo funciona el pipeline desde el pull request hasta producción
La ruta de entrega sigue un modelo de promoción lineal con validación en cada etapa:
- Abrir un pull request — CI detecta qué áreas cambiaron y ejecuta la suite completa de validación
- Merge a staging — las mismas verificaciones se re-ejecutan contra el resultado del merge, luego las aplicaciones afectadas se despliegan al entorno de staging
- Verificar staging — pruebas de humo manuales o automatizadas confirman que el despliegue está saludable
- Merge de staging a main — la validación se ejecuta nuevamente, y las aplicaciones afectadas se despliegan a producción
- Health checks post-despliegue — el pipeline confirma que cada aplicación desplegada responde correctamente
Las pruebas se re-ejecutan intencionalmente después del merge. Un pull request valida la rama de forma aislada, pero el estado después del merge puede diferir debido a conflictos o cambios concurrentes. La validación post-merge asegura que el código exacto del merge aún pasa cada puerta antes de que se despliegue algo.
Esto es más seguro que desplegar directamente desde ramas de features porque cada despliegue a producción ha sido validado al menos tres veces: en el PR, después del merge a staging, y después del merge a main. Cada validación detecta una categoría diferente de problemas.
Las siete puertas de validación que protegen cada despliegue
El pipeline aplica siete categorías de verificaciones antes de que ocurra cualquier despliegue, ordenadas de la más barata a la más costosa:
- Verificación de formato — Prettier detecta inconsistencias de estilo en segundos
- Lint — ESLint señala problemas de calidad de código y errores potenciales
- Verificación de tipos — el compilador de TypeScript verifica la corrección en todos los paquetes
- Pruebas unitarias — Vitest ejecuta pruebas rápidas y aisladas para componentes y utilidades
- Build — Vite compila cada aplicación en activos estáticos listos para producción
- Auditoría de seguridad — el escaneo de dependencias señala vulnerabilidades conocidas
- Pruebas E2E — Playwright ejecuta pruebas a nivel de navegador contra las aplicaciones construidas
El orden es deliberado. Las verificaciones de formato y lint no cuestan casi nada de ejecutar. Si fallan, no hay razón para gastar tiempo construyendo tres aplicaciones y levantando un stack de Docker para E2E. Falla temprano en verificaciones baratas para que solo gastes recursos en verificaciones costosas cuando lo básico ya está limpio.
Este es el mismo principio de fallo rápido que hace eficiente cualquier pipeline de CI. La diferencia es que este repositorio lo aplica consistentemente a través de un monorepo con múltiples aplicaciones desplegables, lo que significa que los ahorros de costos se componen. Si un error de lint en el admin SPA hace fallar el pipeline en 15 segundos, evitas minutos de builds innecesarios, escaneos de seguridad y pruebas de navegador para ambos SPAs y el sitio principal.
Por qué los despliegues selectivos son la mayor ventaja del monorepo
Sin detección de cambios, cada push reconstruye y redespliega cada aplicación. Eso desperdicia cómputo, ralentiza la retroalimentación y aumenta el radio de impacto de cada entrega. Un error en el admin SPA no debería requerir redesplegar el portal SPA y el sitio de marketing.
El repositorio usa detección inteligente de cambios para mapear cambios de archivos a objetivos de despliegue:
- Cambios en
apps/admin-spa/despliegan solo el admin SPA - Cambios en
apps/portal-spa/despliegan solo el portal SPA - Cambios en
apps/main-site/despliegan solo el sitio principal (un sitio HTML estático, no un React SPA) - Cambios en
packages/activan ambos despliegues SPA porque el código compartido podría afectar a cualquier consumidor - Cambios en documentación o solo markdown omiten el despliegue por completo
Esto afecta directamente tres cosas que les importan a los equipos: costo de CI, velocidad de retroalimentación y riesgo de entrega. Construir y desplegar una aplicación en lugar de tres reduce el tiempo de cómputo proporcionalmente. Un pipeline dirigido termina más rápido, lo que significa ciclos de revisión de código más rápidos. Y desplegar solo la aplicación que cambió reduce la superficie para regresiones en código no relacionado.
El despliegue selectivo es donde los monorepos justifican su existencia. Sin él, los monorepos rápidamente se vuelven lentos y costosos a medida que crece el número de aplicaciones. Con él, agregar una nueva aplicación al repositorio no ralentiza los despliegues de todas las demás aplicaciones.
Dónde encaja Playwright en un proceso serio de entrega frontend
Las pruebas E2E son la capa final de confianza antes del despliegue. Validan el comportamiento desplegable en un entorno similar a producción, lo cual es fundamentalmente diferente de las pruebas unitarias ejecutándose contra componentes aislados.
El repositorio ejecuta pruebas de Playwright contra artefactos construidos servidos por Docker y nginx, no contra un servidor de desarrollo. Esa distinción importa porque los servidores de desarrollo usan hot module replacement, omiten optimizaciones y sirven activos de manera diferente. Ejecutar E2E contra la salida del build de producción detecta problemas que solo aparecen en condiciones reales de despliegue.
La suite E2E cubre:
- Carga de aplicación — cada SPA renderiza su componente raíz
- Límites de rutas — el enrutamiento del lado del cliente funciona dentro de cada aplicación
- Navegación entre aplicaciones — los enlaces entre SPAs se resuelven sin errores
- Regresión visual — las capturas de pantalla se comparan contra líneas base para detectar cambios no intencionados en la UI
- Accesibilidad — las verificaciones de axe-core señalan violaciones críticas antes del despliegue
Esta es confianza a nivel de pipeline, no depuración a nivel de desarrollador. Las pruebas E2E no deberían reemplazar las pruebas unitarias. Deberían responder una pregunta diferente: “¿Funciona correctamente el artefacto construido cuando se sirve de la forma en que producción lo servirá?” Si la respuesta es no, el despliegue no ocurre.
Por qué staging y producción deberían comportarse de manera diferente
El repositorio separa los entornos por rama. Los pushes a staging construyen con modo staging, usan secretos de staging y despliegan al servidor de staging. Los pushes a main construyen con modo producción, usan secretos de producción y despliegan al servidor de producción. No cambia ningún código de aplicación entre entornos — solo difieren el modo de build, los secretos y el objetivo de despliegue.
Staging no es un entorno de demostración. Es una capa de confianza. El propósito de staging es detectar problemas que solo aparecen en un entorno desplegado — variables de entorno incorrectas, configuración del servidor rota, activos obsoletos — antes de que esos problemas lleguen a los clientes.
Los despliegues a producción pueden requerir aprobación manual a través de las reglas de protección de Environment de GitHub. Después de que la validación pasa, el job de despliegue se pausa y espera a que un miembro autorizado del equipo apruebe la entrega. Esto es automatización controlada: el pipeline maneja la mecánica, los humanos manejan la decisión. Completamente automatizado no tiene que significar completamente sin revisión.
El modelo de despliegue: rsync, backups y rollback
El repositorio despliega usando rsync sobre SSH. Cada aplicación tiene su propia ruta destino en el servidor, por lo que desplegar el admin SPA no corre el riesgo de sobrescribir los archivos del portal SPA. Los scripts de despliegue soportan modo dry-run para que puedas verificar la intención antes de transferir archivos.
Antes de cada despliegue, el pipeline crea un backup con marca de tiempo de la versión actual. Si un despliegue introduce un problema, el rollback es un solo comando que restaura el backup más reciente. Esto no es una idea de último momento para emergencias — es parte del diseño de entrega.
Los health checks post-despliegue cierran el ciclo. Una transferencia de archivos exitosa no garantiza una aplicación funcionando. La configuración del servidor podría estar mal, las variables de entorno podrían faltar, o el build podría haberse creado con el modo incorrecto. Los health checks confirman que la aplicación desplegada realmente responde, y si fallan, el pipeline reporta un fallo aunque el despliegue en sí haya sido exitoso.
Los mecanismos de despliegue simples suelen ser más mantenibles que la complejidad excesiva de plataformas sobredimensionadas. Rsync, SSH y backups con marca de tiempo son tecnologías aburridas, pero son predecibles, depurables y comprendidas por cada ingeniero de operaciones del equipo.
Si también estás pensando en asegurar lo que fluye a través de tu pipeline, consulta Seguridad de la cadena de suministro de software en la era de la IA para estrategias de integridad de dependencias y SBOM, y Asegurando flujos de trabajo de agentes de codificación con IA para sandboxing y puertas de revisión cuando código generado por IA entra en pull requests de monorepos.
GitHub Actions y GitLab CI en el mismo monorepo
El repositorio incluye tanto .github/workflows/validate-and-deploy.yml como .gitlab-ci.yml con documentación de configuración para cada uno. Soportar ambos es útil para equipos migrando entre plataformas, atendiendo diferentes clientes o evaluando qué sistema de CI se adapta mejor a su flujo de trabajo.
El punto más importante es que el patrón de CI/CD importa más que el proveedor. La misma escalera de validación, la misma lógica de despliegue selectivo y el mismo modelo de entorno basado en ramas funcionan en ambos sistemas. La sintaxis de implementación difiere, pero la arquitectura es portable. Si entiendes el patrón, puedes implementarlo en cualquier sistema de CI.
Lo que los equipos suelen hacer mal con CI/CD de monorepos
Los errores más comunes no son fallos técnicos. Son omisiones arquitectónicas:
- Tratar la estructura de carpetas como la solución completa. Un workspace limpio no te protege de merges rotos o minutos de CI desperdiciados.
- Omitir la detección de cambios. Sin ella, cada push reconstruye todo, lo que elimina la ventaja de velocidad de un monorepo.
- Ejecutar E2E demasiado temprano o demasiado tarde. E2E antes del build desperdicia tiempo en pruebas que no pueden ejecutarse. E2E después del despliegue significa que los fallos llegan a un entorno antes de ser detectados.
- Desplegar todo en cada merge. Esto convierte cada entrega en un evento de stack completo sin importar qué cambió realmente.
- No tener plan de rollback. Si tu única opción de recuperación es “enviar un fix hacia adelante”, estás a un mal despliegue de un tiempo de inactividad prolongado.
- Mezclar el comportamiento de staging y producción. Si staging se despliega automáticamente pero producción también se despliega automáticamente, staging no está realmente filtrando nada.
La mayoría de estos problemas se resuelven diseñando el pipeline intencionalmente en lugar de dejarlo evolucionar orgánicamente. El repositorio react-spa-monorepo-cicd existe específicamente para demostrar cómo luce un pipeline intencional.
Para quién es mejor este tipo de configuración
Esta arquitectura se adapta a equipos que ejecutan múltiples SPAs o una mezcla de aplicaciones estáticas y SPA desde un solo repositorio. Eso incluye:
- Equipos de producto que gestionan aplicaciones separadas orientadas al usuario que comparten sistemas de diseño o clientes de API
- Agencias que construyen y mantienen múltiples superficies frontend para clientes
- Equipos de plataforma interna con paquetes compartidos consumidos por varias aplicaciones
- Desarrolladores que quieren CI/CD simple pero capaz para producción sin adoptar un framework de monorepo pesado
Si ya estás usando Nx o Turborepo y estás satisfecho con la complejidad, este enfoque puede parecer demasiado manual. Pero si quieres entender qué abstraen esas herramientas, o quieres una alternativa más ligera que controles completamente, este es un buen punto de partida.
Qué hacer a continuación
Si quieres implementar este pipeline de forma práctica, sigue el tutorial complementario: Cómo configurar CI/CD y pruebas automatizadas para un monorepo React SPA. Te guía paso a paso desde clonar el repositorio hasta configurar las puertas de validación, ejecutar pruebas E2E con Playwright, configurar despliegues selectivos y configurar entregas a staging y producción.
Para equipos que ya ejecutan pipelines de CI/CD, considera mapear los patrones de este artículo a tu configuración existente:
- Agrega detección de cambios si estás reconstruyendo todo en cada push
- Ordena tus puertas de validación de la más barata a la más costosa
- Separa staging de producción con reglas de entorno basadas en ramas
- Agrega health checks post-despliegue para que una transferencia exitosa no sea el final de la historia
- Incorpora el rollback al pipeline en lugar de tratarlo como un procedimiento de emergencia
Si quieres un punto de partida en lugar de un documento de arquitectura en blanco, este repositorio te lo ofrece: un sistema de entregas de monorepo con puertas de validación, despliegue selectivo, pruebas E2E y rollback ya incorporados. El siguiente paso es adaptar esos patrones a tus propias aplicaciones y objetivos de despliegue en lugar de reinventar el CI/CD desde cero.
Obtén el repositorio react-spa-monorepo-cicd →
Sigue el tutorial paso a paso →
Preguntas frecuentes
¿Cuál es la diferencia entre un monorepo y un polyrepo para CI/CD?
Un monorepo mantiene múltiples aplicaciones y paquetes compartidos en un solo repositorio, lo que permite pipelines de CI/CD compartidos, validación consistente y despliegue selectivo basado en detección de cambios. Un polyrepo usa repositorios separados por aplicación, lo que simplifica los pipelines por aplicación pero requiere más coordinación para dependencias compartidas y pruebas entre aplicaciones.
¿Cómo funciona el despliegue selectivo en un monorepo?
El despliegue selectivo usa detección de cambios para mapear archivos modificados a objetivos de despliegue. Si solo cambió el directorio de una aplicación, solo esa aplicación se construye y despliega. Los cambios en paquetes compartidos activan despliegues para todas las aplicaciones que dependen de ellos. Esto reduce el costo de CI, acelera la retroalimentación y limita el radio de impacto de cada entrega.
¿Deberían ejecutarse las pruebas E2E antes o después del despliegue?
Las pruebas E2E deberían ejecutarse antes del despliegue, contra artefactos construidos servidos en un entorno similar a producción. Esto detecta problemas de integración y despliegue antes de que lleguen a staging o producción. Los health checks post-despliegue luego confirman que la aplicación desplegada responde correctamente.
¿Puedo usar este patrón de CI/CD con Nx o Turborepo?
Sí. La escalera de validación, la lógica de despliegue selectivo y el modelo de entorno basado en ramas son patrones de arquitectura, no configuraciones específicas de herramientas. Si ya usas Nx o Turborepo para orquestación de tareas y caché, puedes superponer estos patrones de CI/CD. El repositorio react-spa-monorepo-cicd demuestra los patrones sin un framework pesado para que puedas ver exactamente qué abstraen esas herramientas.
¿Cómo agrego una nueva aplicación al pipeline del monorepo?
Crea la aplicación bajo apps/, agrega su directorio al script de detección de cambios (scripts/changed-files.sh) y conecta los targets correspondientes de build, despliegue y E2E en el workflow de CI. El modelo de despliegue selectivo escala linealmente — cada nueva aplicación obtiene su propia ruta condicional sin ralentizar los despliegues de las aplicaciones existentes.
¿Cómo maneja este enfoque los cambios en paquetes compartidos?
Los cambios bajo packages/ activan reconstrucciones y despliegues para todas las aplicaciones que dependen de esos paquetes compartidos. Esto es intencional — un error en código compartido podría romper cualquier consumidor, por lo que cada aplicación dependiente debe ser reconstruida, re-testeada y redesplegada para detectar regresiones.