- Configure workspace Git repository with comprehensive .gitignore - Add Odoo as submodule for ERP reference code - Include documentation: SETUP.md, GIT-STRUCTURE.md - Add gitignore templates for projects (backend, frontend, database) - Structure supports independent repos per project/subproject level Workspace includes: - core/ - Reusable patterns, modules, orchestration system - projects/ - Active projects (erp-suite, gamilit, trading-platform, etc.) - knowledge-base/ - Reference code and patterns (includes Odoo submodule) - devtools/ - Development tools and templates - customers/ - Client implementations template 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
480 lines
12 KiB
Markdown
480 lines
12 KiB
Markdown
# ADR-0001: Adopción de Arquitectura Monorepo
|
|
|
|
**Status:** ✅ Accepted
|
|
**Date:** 2025-11-01
|
|
**Deciders:** Tech Lead, Backend Team, Frontend Team
|
|
**Tags:** architecture, repository-structure, devops
|
|
|
|
---
|
|
|
|
## Context
|
|
|
|
### Situación Inicial
|
|
|
|
GAMILIT Platform originalmente estaba organizado en **4 repositorios separados**:
|
|
|
|
1. **gamilit-docs** (~2,000 archivos markdown)
|
|
- Documentación del proyecto
|
|
- Especificaciones técnicas
|
|
- ADRs y RFCs
|
|
- Guías de desarrollo
|
|
|
|
2. **gamilit-platform-backend** (~400 archivos TypeScript)
|
|
- API REST NestJS
|
|
- 13 módulos funcionales
|
|
- ~470 endpoints
|
|
|
|
3. **gamilit-platform-web** (~200 archivos TSX)
|
|
- Frontend React 19
|
|
- 33 mecánicas educativas
|
|
- 180+ componentes
|
|
|
|
4. **gamilit-deployment-scripts** (~50 archivos shell/yaml)
|
|
- Scripts de deployment
|
|
- Configuración PM2
|
|
- Workflows CI/CD
|
|
|
|
### Problemas Identificados
|
|
|
|
#### 1. Sincronización Manual Compleja
|
|
|
|
- **Cambios cross-repo:** Una feature que afectaba backend + frontend requería:
|
|
- 2 PRs separados en repos diferentes
|
|
- Coordinación manual de merges
|
|
- Riesgo de desincronización (backend mergeado pero frontend no)
|
|
|
|
- **Ejemplo real:** Agregar nuevo endpoint `/api/v1/gamification/achievements`
|
|
- Paso 1: PR en backend (crear endpoint)
|
|
- Paso 2: PR en frontend (consumir endpoint)
|
|
- **Problema:** Si frontend se mergea antes que backend → 404 errors en production
|
|
|
|
#### 2. Gestión de Versiones Fragmentada
|
|
|
|
- **4 sistemas de versionado independientes**
|
|
- Backend: v1.5.3
|
|
- Frontend: v2.1.0
|
|
- Docs: Sin versiones
|
|
- Scripts: Sin versiones
|
|
|
|
- **Problema:** Imposible saber qué versión de frontend es compatible con qué versión de backend
|
|
|
|
#### 3. Duplicación de Configuración
|
|
|
|
```
|
|
gamilit-platform-backend/
|
|
├── .eslintrc.js # Config ESLint
|
|
├── .prettierrc # Config Prettier
|
|
├── tsconfig.json # Config TypeScript
|
|
└── .github/workflows/ # CI/CD
|
|
|
|
gamilit-platform-web/
|
|
├── .eslintrc.js # ❌ DUPLICADO
|
|
├── .prettierrc # ❌ DUPLICADO
|
|
├── tsconfig.json # ❌ DUPLICADO
|
|
└── .github/workflows/ # ❌ DUPLICADO
|
|
```
|
|
|
|
**Impacto:**
|
|
- Cambiar regla de linting → Editar 2 archivos
|
|
- Actualizar workflow CI → Editar 2 archivos
|
|
- Riesgo de inconsistencias
|
|
|
|
#### 4. Onboarding Complejo
|
|
|
|
Nuevo desarrollador debe:
|
|
1. Clonar 4 repositorios diferentes
|
|
2. Setup de 4 entornos independientes
|
|
3. Configurar 4 .env files
|
|
4. Ejecutar 4 comandos de install separados
|
|
5. Coordinar 4 workflows de Git
|
|
|
|
**Tiempo de onboarding:** 4-6 horas (vs. 2-3 horas con monorepo)
|
|
|
|
#### 5. Búsqueda Global Imposible
|
|
|
|
- **Imposible buscar en todo el codebase** con un solo comando
|
|
- Buscar "ML_COINS" requería:
|
|
```bash
|
|
cd gamilit-platform-backend && grep -r "ML_COINS" .
|
|
cd ../gamilit-platform-web && grep -r "ML_COINS" .
|
|
cd ../gamilit-docs && grep -r "ML_COINS" .
|
|
```
|
|
|
|
#### 6. Refactoring Cross-Repo Riesgoso
|
|
|
|
**Ejemplo:** Renombrar `mlCoins` → `ml_coins` en toda la plataforma
|
|
|
|
Con repos separados:
|
|
1. ✅ Refactor backend (PR #123)
|
|
2. ✅ Refactor frontend (PR #456)
|
|
3. ❌ **Problema:** Entre merges, producción está rota
|
|
|
|
Con monorepo:
|
|
1. ✅ Refactor backend + frontend + docs en **1 PR atómico**
|
|
2. ✅ Tests CI validan ambos lados antes de merge
|
|
|
|
---
|
|
|
|
## Decision
|
|
|
|
**Adoptamos arquitectura de Monorepo** consolidando los 4 repos en una estructura unificada.
|
|
|
|
### Estructura Elegida
|
|
|
|
```
|
|
gamilit/projects/gamilit/
|
|
├── apps/ # Código de aplicaciones
|
|
│ ├── backend/ # NestJS backend
|
|
│ ├── frontend/ # React frontend
|
|
│ ├── database/ # PostgreSQL DDL/migrations
|
|
│ └── devops/ # Scripts DevOps
|
|
│
|
|
├── docs/ # Documentación
|
|
│ ├── 00-overview/
|
|
│ ├── 01-requerimientos/
|
|
│ ├── 02-especificaciones-tecnicas/
|
|
│ ├── 03-desarrollo/
|
|
│ ├── 04-planificacion/
|
|
│ ├── QUICK-REFERENCE/
|
|
│ ├── adr/ # Architecture Decision Records
|
|
│ └── standards/ # Estándares de código
|
|
│
|
|
├── orchestration/ # Orquestación de agentes IA
|
|
│ ├── 01-analisis/
|
|
│ ├── 02-planes/
|
|
│ ├── 03-subagentes/
|
|
│ ├── 04-logs/
|
|
│ └── 05-validaciones/
|
|
│
|
|
├── artifacts/ # Artefactos generados
|
|
│ ├── diagrams/
|
|
│ ├── changelogs/
|
|
│ └── reports/
|
|
│
|
|
├── package.json # Root package.json
|
|
├── .eslintrc.js # Shared ESLint config
|
|
├── .prettierrc # Shared Prettier config
|
|
├── tsconfig.json # Base TypeScript config
|
|
└── .github/ # Single CI/CD workflow
|
|
└── workflows/
|
|
```
|
|
|
|
### Principios Aplicados
|
|
|
|
1. **Single Source of Truth**
|
|
- Un solo repo → Una sola fuente de verdad
|
|
- Una sola versión del proyecto
|
|
|
|
2. **Atomic Changes**
|
|
- Cambios cross-app en un solo commit
|
|
- Tests CI validan toda la plataforma antes de merge
|
|
|
|
3. **Shared Tooling**
|
|
- Configuraciones compartidas (ESLint, Prettier, TS)
|
|
- Scripts compartidos (build, test, deploy)
|
|
|
|
4. **Clear Boundaries**
|
|
- Carpetas separadas por propósito (`apps/`, `docs/`, `orchestration/`)
|
|
- Cada app mantiene su independencia dentro del monorepo
|
|
|
|
---
|
|
|
|
## Alternatives Considered
|
|
|
|
### Alternativa 1: Mantener Repos Separados
|
|
|
|
**Pros:**
|
|
- ✅ Repos más pequeños (menos commits/history)
|
|
- ✅ Permisos granulares por repo
|
|
- ✅ CI/CD más rápido (solo testea repo modificado)
|
|
|
|
**Cons:**
|
|
- ❌ Sincronización manual compleja
|
|
- ❌ Refactoring cross-repo riesgoso
|
|
- ❌ Duplicación de configuración
|
|
- ❌ Onboarding complejo
|
|
|
|
**Decisión:** **Rechazada** - Los cons superan los pros
|
|
|
|
---
|
|
|
|
### Alternativa 2: Monorepo con Workspaces (Lerna/Nx)
|
|
|
|
**Pros:**
|
|
- ✅ Herramientas especializadas (Nx, Lerna, Turborepo)
|
|
- ✅ Build caching inteligente
|
|
- ✅ Dependency graph management
|
|
- ✅ Soporte para shared packages
|
|
|
|
**Cons:**
|
|
- ❌ Complejidad adicional de setup
|
|
- ❌ Learning curve de Nx/Lerna
|
|
- ❌ Overhead para proyecto pequeño-mediano (2 apps)
|
|
|
|
**Decisión:** **Pospuesta para Fase 2** - Consideraremos Nx cuando tengamos 5+ apps
|
|
|
|
---
|
|
|
|
### Alternativa 3: Monorepo Simple (RFC-0001)
|
|
|
|
**Pros:**
|
|
- ✅ Setup simple sin herramientas adicionales
|
|
- ✅ Estructura clara basada en carpetas
|
|
- ✅ Fácil de entender y mantener
|
|
- ✅ Suficiente para 2-3 apps
|
|
|
|
**Cons:**
|
|
- ⚠️ Sin build caching automático
|
|
- ⚠️ CI/CD debe testear todo siempre
|
|
|
|
**Decisión:** **✅ ELEGIDA** - Balance perfecto simplicidad/funcionalidad
|
|
|
|
---
|
|
|
|
## Consequences
|
|
|
|
### Positivas ✅
|
|
|
|
#### 1. Cambios Atómicos Cross-App
|
|
|
|
**Antes:**
|
|
```bash
|
|
# 2 PRs separados
|
|
cd gamilit-platform-backend
|
|
git checkout -b feature/new-endpoint
|
|
# ... hacer cambios ...
|
|
git push # PR #123
|
|
|
|
cd ../gamilit-platform-web
|
|
git checkout -b feature/consume-endpoint
|
|
# ... hacer cambios ...
|
|
git push # PR #456
|
|
```
|
|
|
|
**Ahora:**
|
|
```bash
|
|
# 1 PR atómico
|
|
cd gamilit/projects/gamilit
|
|
git checkout -b feature/new-endpoint
|
|
# Editar apps/backend/ y apps/frontend/
|
|
git add apps/backend apps/frontend
|
|
git commit -m "feat: add achievements endpoint + UI"
|
|
git push # PR único, tests validan ambos lados
|
|
```
|
|
|
|
#### 2. Búsqueda Global
|
|
|
|
```bash
|
|
# Buscar en TODO el codebase
|
|
grep -r "ML_COINS" .
|
|
|
|
# Buscar solo en código
|
|
grep -r "ML_COINS" apps/
|
|
|
|
# Buscar solo en docs
|
|
grep -r "ML_COINS" docs/
|
|
```
|
|
|
|
#### 3. Refactoring Seguro
|
|
|
|
**Ejemplo:** Renombrar constante
|
|
|
|
```bash
|
|
# 1. Buscar todas las ocurrencias
|
|
grep -r "OLD_NAME" apps/
|
|
|
|
# 2. Reemplazar en todo el monorepo
|
|
find apps/ -type f -exec sed -i 's/OLD_NAME/NEW_NAME/g' {} +
|
|
|
|
# 3. Commit atómico
|
|
git add apps/
|
|
git commit -m "refactor: rename OLD_NAME to NEW_NAME across platform"
|
|
|
|
# 4. CI testa backend + frontend juntos
|
|
# Si algo falla, el commit no se mergea
|
|
```
|
|
|
|
#### 4. Configuración Compartida
|
|
|
|
**Un solo .eslintrc.js:**
|
|
```json
|
|
{
|
|
"extends": ["../../.eslintrc.js"], // Hereda config root
|
|
"rules": {
|
|
// Overrides específicos si necesario
|
|
}
|
|
}
|
|
```
|
|
|
|
**Beneficio:** Cambiar regla de linting → Editar 1 archivo, afecta todo el repo
|
|
|
|
#### 5. Onboarding Simplificado
|
|
|
|
**Antes (4 repos):**
|
|
```bash
|
|
git clone repo1 && cd repo1 && npm install
|
|
git clone repo2 && cd repo2 && npm install
|
|
git clone repo3 && cd repo3 && npm install
|
|
git clone repo4 && cd repo4 && npm install
|
|
```
|
|
|
|
**Ahora (monorepo):**
|
|
```bash
|
|
git clone gamilit
|
|
cd gamilit/projects/gamilit
|
|
npm install # Install root + workspaces
|
|
npm run dev # Start todo
|
|
```
|
|
|
|
#### 6. Versionado Unificado
|
|
|
|
**Un solo package.json root:**
|
|
```json
|
|
{
|
|
"name": "gamilit-monorepo",
|
|
"version": "2.0.0", // Version única del proyecto
|
|
"workspaces": [
|
|
"apps/backend",
|
|
"apps/frontend"
|
|
]
|
|
}
|
|
```
|
|
|
|
### Negativas ⚠️
|
|
|
|
#### 1. Repo Más Grande
|
|
|
|
**Tamaño total:** ~130 MB (vs. 4 repos de ~30 MB cada uno)
|
|
|
|
**Mitigación:**
|
|
- Git LFS para archivos grandes
|
|
- .gitignore agresivo (node_modules, dist, logs)
|
|
- Shallow clones en CI: `git clone --depth 1`
|
|
|
|
#### 2. CI/CD Más Lento
|
|
|
|
**Problema:** Cambio en frontend → CI testea también backend (innecesario)
|
|
|
|
**Mitigación (Fase 2):**
|
|
```yaml
|
|
# .github/workflows/ci.yml
|
|
- name: Check changes
|
|
run: |
|
|
if git diff --name-only HEAD~1 | grep "^apps/backend"; then
|
|
echo "Backend changed, run backend tests"
|
|
fi
|
|
```
|
|
|
|
#### 3. Permisos Menos Granulares
|
|
|
|
**Problema:** No se puede dar acceso solo a "docs" sin dar acceso a "apps"
|
|
|
|
**Mitigación:**
|
|
- Branch protection rules
|
|
- CODEOWNERS file:
|
|
```
|
|
/apps/backend/ @backend-team
|
|
/apps/frontend/ @frontend-team
|
|
/docs/ @tech-writer @tech-lead
|
|
```
|
|
|
|
#### 4. Git History Más Complejo
|
|
|
|
**Problema:** `git log` muestra commits de todas las apps mezclados
|
|
|
|
**Mitigación:**
|
|
```bash
|
|
# Ver solo commits de backend
|
|
git log -- apps/backend/
|
|
|
|
# Ver solo commits de frontend
|
|
git log -- apps/frontend/
|
|
|
|
# Conventional commits ayudan a filtrar
|
|
git log --grep="^feat(backend)"
|
|
```
|
|
|
|
---
|
|
|
|
## Implementation Plan
|
|
|
|
### Fase 1: Migración (✅ Completada - 2025-11-01)
|
|
|
|
- [x] Crear estructura RFC-0001
|
|
- [x] Migrar gamilit-docs → `docs/`
|
|
- [x] Migrar gamilit-platform-backend → `apps/backend/`
|
|
- [x] Migrar gamilit-platform-web → `apps/frontend/`
|
|
- [x] Migrar gamilit-deployment-scripts → `apps/devops/`
|
|
- [x] Setup de workspaces en root package.json
|
|
- [x] Compartir configs (ESLint, Prettier, TS)
|
|
- [x] Actualizar CI/CD workflows
|
|
|
|
### Fase 2: Optimización (Planeada - Q1 2025)
|
|
|
|
- [ ] Evaluar Nx/Turborepo para caching
|
|
- [ ] Implementar selective CI (solo testear apps modificadas)
|
|
- [ ] Setup de Git LFS para assets grandes
|
|
- [ ] Mejorar CODEOWNERS granularity
|
|
|
|
---
|
|
|
|
## Metrics
|
|
|
|
### Before (4 Repos)
|
|
|
|
| Métrica | Valor |
|
|
|---------|-------|
|
|
| **Repos totales** | 4 |
|
|
| **Tiempo onboarding** | 4-6 horas |
|
|
| **PRs para cambio cross-app** | 2-4 PRs |
|
|
| **Riesgo de desincronización** | Alto |
|
|
| **Búsqueda global** | Imposible |
|
|
| **Config duplicada** | Sí (4x) |
|
|
|
|
### After (Monorepo)
|
|
|
|
| Métrica | Valor |
|
|
|---------|-------|
|
|
| **Repos totales** | 1 |
|
|
| **Tiempo onboarding** | 2-3 horas ✅ |
|
|
| **PRs para cambio cross-app** | 1 PR ✅ |
|
|
| **Riesgo de desincronización** | Bajo ✅ |
|
|
| **Búsqueda global** | `grep -r` ✅ |
|
|
| **Config duplicada** | No ✅ |
|
|
|
|
---
|
|
|
|
## Lessons Learned
|
|
|
|
### ✅ Qué funcionó bien
|
|
|
|
1. **Migración gradual:** Migrar un repo a la vez en sprints separados redujo riesgo
|
|
2. **RFC-0001 como guía:** Tener estructura definida antes de migrar fue clave
|
|
3. **Conventional commits:** Ayudaron a mantener history limpio durante migración
|
|
4. **CODEOWNERS:** Permitió mantener ownership claro post-migración
|
|
|
|
### ⚠️ Qué mejorar
|
|
|
|
1. **CI time:** Actualmente testa todo siempre, necesitamos selective testing
|
|
2. **Docs discovery:** Con 2,000+ archivos, navigation puede ser compleja → SIMCO helps
|
|
3. **Build scripts:** Necesitamos scripts de build más inteligentes
|
|
|
|
---
|
|
|
|
## References
|
|
|
|
- [RFC-0001: Estructura de Monorepo](../standards/RFC-0001-monorepo-structure.md)
|
|
- [Monorepos in Git (Martin Fowler)](https://martinfowler.com/bliki/MonorepoPattern.html)
|
|
- [Why Google Stores Billions of Lines in a Single Repository](https://cacm.acm.org/magazines/2016/7/204032-why-google-stores-billions-of-lines-of-code-in-a-single-repository/fulltext)
|
|
- [Monorepo Tools: Lerna, Nx, Turborepo Comparison](https://monorepo.tools/)
|
|
|
|
---
|
|
|
|
**Status:** ✅ Accepted and Implemented
|
|
**Date Created:** 2025-11-01
|
|
**Last Updated:** 2025-11-07
|
|
**Supersedes:** N/A (primera ADR)
|
|
**Superseded by:** N/A
|
|
|
|
**Revisión:** Esta decisión se revisará en Q2 2025 para evaluar migración a Nx/Turborepo si el proyecto crece a 5+ apps.
|