Saltar al contenido
# ⚙️ CI/CD — klaUS-aicalc-roi ## 🤔 ¿Qué hago? ¿Cómo lo hago? ¿Y para qué lo hago? **¿Qué hago?** Soy el pipeline de integración continua del proyecto. Verifico automáticamente que cada push y cada PR no rompe el backend ni el frontend — lint, tipos estáticos, tests y build de producción. **¿Cómo lo hago?** Un único workflow de GitHub Actions (`.github/workflows/ci.yml`) con tres jobs paralelos: - `lint`: ruff + mypy sobre el código Python del backend - `test`: pytest con upload de cobertura a Codecov - `frontend`: tsc + `npm run build` sobre la capa Next.js Los tres jobs se ejecutan en `ubuntu-latest` sin dependencias entre sí — fallan de forma independiente y en paralelo, maximizando la velocidad de feedback. **¿Y para qué lo hago?** Garantizar que `main` siempre está en estado desplegable. Sin CI, un error de tipos o un build roto del frontend puede colarse en `main` silenciosamente. Con los tres jobs cubriéndolo, cualquier regresión — Python o TypeScript — se detecta antes de que la PR se mergee. --- ## 🗺️ Flujo del pipeline ```mermaid flowchart TD A[Push / PR abierta] --> B{Trigger CI} B --> C[🐍 lint\nruff check + mypy] B --> D[🧪 test\npytest + codecov] B --> E[🖥️ frontend\ntsc + npm build] C --> F{ruff OK?} F -- ❌ --> G[Fallo: lint error] F -- ✅ --> H{mypy OK?} H -- ❌ --> I[Fallo: tipo incorrecto] H -- ✅ --> J[✅ Lint passed] D --> K{Tests OK?} K -- ❌ --> L[Fallo: test roto] K -- ✅ --> M[Upload coverage Codecov] M --> N[✅ Tests passed] E --> O{tsc OK?} O -- ❌ --> P[Fallo: error TypeScript] O -- ✅ --> Q{npm build OK?} Q -- ❌ --> R[Fallo: build Next.js] Q -- ✅ --> S[✅ Frontend passed] J & N & S --> T[✅ CI verde — PR mergeable] ``` --- ## 📋 Jobs detallados ### 🐍 `lint` — Lint Python | Paso | Herramienta | Qué verifica | | --- | --- | --- | | `ruff check .` | Ruff | Estilo, imports, anti-patrones PEP8 | | `mypy backend/` | mypy (strict) | Tipos estáticos en todo el backend | - Python 3.12 + `pip` cacheado - Instala dependencias dev con `pip install -e ".[dev]"` - **No** verifica el frontend — eso lo hace el job `frontend` --- ### 🧪 `test` — Tests Python | Paso | Herramienta | Qué verifica | | --- | --- | --- | | `pytest` | pytest | Suite completa: engine, data catalog, API REST | | `codecov-action@v4` | Codecov | Upload de cobertura (no bloquea si falla) | - `fail_ci_if_error: false` en Codecov — si Codecov no está disponible, el CI no falla - Cobertura objetivo: **≥ 80%** en el engine (`tco_engine/`) **Tests incluidos:** | Fichero | Qué cubre | | --- | --- | | `backend/tests/test_tco_engine.py` | Motor de cálculo CAPEX/OPEX, Pareto, recomendación | | `backend/tests/test_data_catalog.py` | Catálogo estático — 30 modelos, 10 GPU, integridad de datos | | `backend/tests/test_api.py` | Endpoints FastAPI — /health, /v1/models, /v1/hardware, /v1/analyze | --- ### 🖥️ `frontend` — Verificación Next.js | Paso | Herramienta | Qué verifica | | --- | --- | --- | | `npm ci` | npm | Instalación limpia desde `package-lock.json` | | `npx tsc --noEmit` | TypeScript compiler | Tipos estáticos — sin emitir ficheros | | `npm run build` | Next.js (Turbopack) | Build de producción completo | - Node 22 LTS + caché npm sobre `frontend/package-lock.json` - `working-directory: frontend` — todos los pasos se ejecutan en `frontend/` - `npm run build` ejecuta Next.js build completo — detecta errores de importación, módulos faltantes y páginas que no compilan --- ## 🔁 Cuándo se ejecuta | Evento | Ramas | Jobs que corren | | --- | --- | --- | | `push` | `main`, `GH-*` | lint + test + frontend | | `pull_request` | contra `main` | lint + test + frontend | Todas las ramas de trabajo siguen el formato `GH-{N}-descripcion` — el trigger `GH-*` cubre el 100% del flujo de desarrollo. --- ## 📊 Estado actual de cobertura | Módulo | Tests | Cobertura estimada | | --- | --- | --- | | `tco_engine/engine.py` | ✅ | ~85% | | `tco_engine/calculators.py` | ✅ | ~90% | | `tco_engine/models.py` | ✅ (indirecto) | ~100% | | `api/app.py` | ✅ | ~95% | | Frontend (Next.js) | ❌ No hay tests unitarios | — | > 📝 Tests de frontend (jest/playwright) están planificados para **Fase 2**. --- ## 🔒 Seguridad del pipeline - Sin secrets en el workflow — Codecov usa token anónimo (`fail_ci_if_error: false`) - `actions/checkout@v4`, `actions/setup-python@v5`, `actions/setup-node@v4` — versiones fijadas con major tag pinning - No se expone `NEXT_PUBLIC_API_URL` en CI — el job `frontend` solo verifica la compilación, no levanta la API --- ## ➕ Añadir un nuevo job ```yaml nuevo-job: name: Descripción del job runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # ... pasos ``` Añadir el `job-id` al diagrama Mermaid de este documento y actualizar la tabla de jobs. --- ## 🔗 Documentos relacionados - [TCO Engine](tco-engine.md) — motor Python que cubren los tests de `test_tco_engine.py` - [API REST](api.md) — endpoints que cubre `test_api.py` - [Data Catalog](data-catalog.md) — catálogo verificado por `test_data_catalog.py` - [Frontend](frontend.md) — capa Next.js verificada por el job `frontend`