diff --git a/README.md b/README.md index d5b7930..b165060 100644 --- a/README.md +++ b/README.md @@ -87,9 +87,20 @@ y el servicio quedó corriendo esa imagen en producción, exportando telemetría ![Corrida del workflow Release: jobs ci, docker y deploy](docs/images/pipeline-release.png) -_Esa captura corresponde a la primera corrida (release `v0.1.0`), con el job `Deploy to Render` en rojo — es la falla -descrita en Fase 4. Las releases `v0.2.0` y `v0.3.0` corrieron el pipeline completo sin ese error; falta reemplazar la -captura por una corrida en verde._ +_Corrida de la release `v0.3.0`: los tres jobs de `ci.yml` (`Lint`, `Unit tests`, `E2E tests`) alimentan al build y push +de la imagen, que a su vez habilita el deploy a Render. El resumen muestra los 34 tests unitarios y los 16 e2e en verde +y el tag con el que se publicó la imagen (`v0.3.0`)._ + +![Servicio en Render con el deploy v0.3.0 activo](docs/images/render-servicio.png) + +_Servicio `curso-devops-api` en Render: el deploy `e02efcb` (`v0.3.0`) figura como `Live` con trigger `Deploy Hook`. Su +digest coincide con el manifest `sha256:e02efcb5...` de Docker Hub, es decir que corre exactamente la imagen publicada._ + +![Eventos de Render: deploy lanzado por el deploy hook](docs/images/render-deploy-hook.png) + +_Historial de eventos: cada release aparece como `Triggered via Deploy Hook`. La excepción es el deploy de `v0.1.0` del +28 de septiembre, `Triggered by you via API`, que fue un redeploy manual durante el diagnóstico descrito en +[Observabilidad](#observabilidad-opentelemetry--grafana-cloud)._ ![Pull Request con los tres checks de CI requeridos en verde](docs/images/pr-checks.png) @@ -118,10 +129,12 @@ _PR #21: `Lint`, `Unit tests` y `E2E tests` aparecen como `Required` y en verde en el código. **Notas sobre Render.** El servicio tiene `autoDeploy` apagado: los deploys salen únicamente por el deploy hook, que -pasa `imgURL` con el tag exacto de la release. Por eso el campo de imagen en Settings puede mostrar un tag viejo -(`v0.1.0`), ya que cada deploy por hook lo sobreescribe; la fuente de verdad es la lista de deploys, donde el activo -es `v0.3.0`. Al ser el plan Free, el servicio se duerme por inactividad y el primer request posterior tarda unos 40 s -(cold start). +pasa `imgURL` con el tag exacto de la release. Ese `imgURL` vale solo para ese deploy: **no modifica la imagen +configurada en el servicio**, que durante las primeras releases siguió en `v0.1.0` y se actualizó a mano a `v0.3.0` para +que la cabecera del dashboard y un eventual deploy manual o rollback coincidan con lo que corre. Aun así, el despliegue +correcto sale siempre del pipeline y la fuente de verdad de lo que corre es la lista de deploys, donde el activo es +`v0.3.0` (`e02efcb`). Al ser el plan Free, el servicio se duerme por inactividad y el primer request posterior tarda +unos 40 s (cold start). ### 2. Justificación Técnica y Decisiones de Diseño @@ -211,7 +224,11 @@ complejidad recomendada para equipos pequeños — el caso de este TP. **Protección de `main`:** - +![Regla de protección de la rama main](docs/images/branch-protection.png) + +_Settings > Branches: la regla para `main` exige Pull Request y los tres status checks (`Lint`, `Unit tests`, +`E2E tests`, todos de GitHub Actions), y tiene activado "Do not allow bypassing the above settings", por lo que aplica +también al administrador del repositorio._ `main` exige PR (no admite push directo) y tiene "Require status checks to pass" activo para `Lint`, `Unit tests` y `E2E tests` (verificado con `gh api repos/adrianberriel/curso-devops-api/branches/main/protection`) — un PR con @@ -280,12 +297,16 @@ llegan a la imagen final. `docker-compose.yaml`, que le pide a Docker que envuelva el proceso con su init liviano incorporado. -**Evidencia:** las imágenes publicadas son `linux/amd64`. `v0.1.0` pesa 61.32 MiB, `v0.2.0` 70.12 MiB y `v0.3.0` (la -que corre en producción) 79.61 MiB comprimida (Docker Hub las muestra en MB decimales: 64.3, 73.5 y 83.5) — el -crecimiento viene de las dependencias de OpenTelemetry -agregadas entre releases. +**Evidencia:** las imágenes publicadas son `linux/amd64`. Según Docker Hub, `v0.1.0` pesa 61.32 MB, `v0.2.0` 70.12 MB y +`v0.3.0` (la que corre en producción) 79.61 MB comprimida — el crecimiento viene de las dependencias de OpenTelemetry +agregadas entre releases. (La API de Docker Hub devuelve esos mismos tamaños en bytes decimales, 64.3, 73.5 y 83.5 MB; +la interfaz web divide por 1024² pero conserva la etiqueta "MB". El informe usa los valores de la interfaz.) + +![Detalle del tag v0.3.0 en Docker Hub](docs/images/dockerhub-tag-detalle.png) - +_Las capas confirman las decisiones del Dockerfile: base `alpine 3.24` con `NODE_VERSION=24.20.0` pineada, `COPY +--chown=node:node` de `dist/` y `node_modules` de producción (el resto del código fuente no llega a la imagen final) y +`USER node` antes del `CMD`._ #### Orquestación Local @@ -440,8 +461,8 @@ Primera release publicada: `adrianberriel/curso-devops-api:v0.1.0`. Release actu ![Tags del repositorio en Docker Hub](docs/images/dockerhub-tags.png) -_Esa captura es de cuando solo existía el tag `v0.1.0`; falta actualizarla para que muestre también `v0.2.0` y -`v0.3.0`._ +_Los tres tags SemVer publicados (`v0.1.0`, `v0.2.0`, `v0.3.0`), todos `linux/amd64`, sin tag `latest`, en un +repositorio público (la página se ve sin iniciar sesión)._ ### 3. Aplicación de la Filosofía DevOps @@ -511,6 +532,6 @@ _Borrador — a revisar y completar con la evidencia final._ 2. **Defectos detectados tarde.** `ci.yml` corre lint y tests en cada Pull Request, y el mismo CI se vuelve a ejecutar sobre el tag antes de publicar (`needs: ci`), de modo que un defecto se frena antes de llegar al registro. 3. **Retrabajo por diferencias de entorno.** Un `Dockerfile` multi-stage con base pineada, usado igual en local y en - CI, evita el "en mi máquina funciona"; además la imagen final es liviana (61.32 MiB comprimida en `v0.1.0`), lo que + CI, evita el "en mi máquina funciona"; además la imagen final es liviana (61.32 MB comprimida en `v0.1.0`), lo que reduce la transferencia en cada publicación y despliegue. \ No newline at end of file diff --git a/docs/estado-del-proyecto.md b/docs/estado-del-proyecto.md index ef78cf3..4524ed4 100644 --- a/docs/estado-del-proyecto.md +++ b/docs/estado-del-proyecto.md @@ -64,8 +64,9 @@ las capturas van al final porque dependen de que lo demás exista. hoy no hay ningún dashboard propio, solo los de la plataforma. 2. [ ] **Experimento de falla controlada** (Tercera Forma). Genera además la evidencia `falla-controlada-1.png`. 3. [ ] **Principios Lean** y cierre de la Segunda/Tercera Forma con la evidencia real. -4. [ ] **Capturas** de la tabla de abajo. -5. [ ] **Cierre:** PR de la captura `pr-checks.png` y limpieza de ramas (ver Housekeeping). +4. [ ] **Capturas pendientes:** solo `monitoreo-dashboard.png` y `falla-controlada-1.png` (dependen de los puntos 1 y + 2). +5. [ ] **Cierre:** PR de las 6 capturas de evidencia y limpieza de ramas (ver Housekeeping). ## Decisiones tuyas pendientes @@ -80,6 +81,9 @@ Cada una trae una recomendación; ninguna bloquea el plan de arriba. *Recomendación:* dejarlo manual y declararlo como limitación; la consigna no exige automatizarlo. - [ ] **Actualizar dependencias antes de entregar.** Hay versiones menores nuevas (NestJS 12.0.1 → 12.2.0, oxlint, vitest, prettier). *Recomendación:* no tocarlas ahora; cada cambio exige una release nueva y revalidar el pipeline. +- [x] **Imagen configurada en Render.** Cambiada de `v0.1.0` a `v0.3.0` el 2026-10-21 (Update Source, sin deploy + nuevo). Consecuencia: cada release futura deja la configuración un tag atrás hasta que se actualice a mano; el + despliegue correcto sigue saliendo del pipeline. Las capturas de Render ya reflejan el cambio. - [ ] **Renombrar el workspace de Render** ("My Workspace" es el nombre por defecto). Cosmético; solo importa si aparece en una captura del informe. @@ -87,9 +91,10 @@ Cada una trae una recomendación; ninguna bloquea el plan de arriba. - [ ] **Despertar Render unos minutos antes.** El plan Free duerme el servicio; el primer request tardó ~42 s. - [ ] **Generar tráfico sobre la API** para que el dashboard tenga datos recientes (incluyendo algunos 404 y 400). -- [ ] **Saber explicar el `imagePath` de Render.** En Settings el servicio muestra `v0.1.0`, pero cada deploy por hook - sobreescribe la imagen con el tag exacto de la release. La fuente de verdad es la lista de deploys (Events), donde - el activo es `v0.3.0`. +- [ ] **Saber explicar que el deploy hook no actualiza la imagen configurada en Render.** Pasa `imgURL` solo para ese + deploy; por eso la cabecera mostraba `v0.1.0` hasta que se cambió a mano. Tras la próxima release volverá a quedar un + tag atrás. La fuente de verdad es la lista de deploys, donde el activo es `v0.3.0` (`e02efcb`, mismo digest que + Docker Hub). - [ ] **Saber explicar los 3 commits que no siguen Conventional Commits** (ver README, "Excepciones conocidas"). - [ ] **No citar el tamaño de una imagen construida en local.** Pesa ~449 MB descomprimida y es `arm64`; las publicadas son `linux/amd64` y pesan ~80 MB comprimidas. @@ -105,14 +110,14 @@ Cada una trae una recomendación; ninguna bloquea el plan de arriba. Van en `docs/images/`; los nombres deben coincidir con las referencias del informe. -| Archivo | Estado | Qué debe mostrar | -|-----------------------------|-------------------|---------------------------------------------------------------------------------------------------------------------------------------------------| -| `pipeline-release.png` | ⚠️ desactualizada | Muestra la corrida fallida de `v0.1.0` (Deploy to Render en rojo). Reemplazar por una corrida `Release` completa en verde (ideal: la de `v0.3.0`) | -| `dockerhub-tags.png` | ⚠️ desactualizada | Solo muestra `v0.1.0`. Reemplazar por una que incluya `v0.2.0` y `v0.3.0` | -| `pr-checks.png` | ✅ lista | PR #21 con los checks de CI (Lint, Unit tests y E2E tests) en verde; ya referenciada en el README | -| `branch-protection.png` | ❌ falta | Settings > Branches: protección de `main` con los status checks requeridos | -| `dockerhub-tag-detalle.png` | ❌ falta | Detalle de `v0.3.0` (linux/amd64, tamaño) | -| `render-servicio.png` | ❌ falta | Servicio en Render corriendo la imagen `v0.3.0` | -| `render-deploy-hook.png` | ❌ falta | Deploy disparado por el hook (eventos / log) | -| `monitoreo-dashboard.png` | ❌ falta | Dashboard propio con las Golden Signals | -| `falla-controlada-1.png` | ❌ falta | Evidencia del experimento de falla controlada | +| Archivo | Estado | Qué debe mostrar | +|-----------------------------|----------|-----------------------------------------------------------------------------------------------------------------------| +| `pipeline-release.png` | ✅ lista | Corrida `Release` de `v0.3.0` completa en verde (ci, docker, deploy); referenciada en el README | +| `dockerhub-tags.png` | ✅ lista | Tags `v0.1.0`, `v0.2.0` y `v0.3.0`, sin `latest`; referenciada en el README | +| `pr-checks.png` | ✅ lista | PR #21 con los checks de CI (Lint, Unit tests y E2E tests) en verde; referenciada en el README | +| `branch-protection.png` | ✅ lista | Protección de `main` con PR y los tres status checks; referenciada en el README | +| `dockerhub-tag-detalle.png` | ✅ lista | Detalle de `v0.3.0`: linux/amd64, 79.61 MB, capas con `USER node`; referenciada en el README | +| `render-servicio.png` | ✅ lista | Deploy `v0.3.0` (`e02efcb`) en `Live` vía Deploy Hook, con `v0.3.0` también en la cabecera; referenciada en el README | +| `render-deploy-hook.png` | ✅ lista | Eventos de Render con los deploys por hook y cabecera en `v0.3.0`; referenciada en el README | +| `monitoreo-dashboard.png` | ❌ falta | Dashboard propio con las Golden Signals | +| `falla-controlada-1.png` | ❌ falta | Evidencia del experimento de falla controlada | diff --git a/docs/images/branch-protection.png b/docs/images/branch-protection.png new file mode 100644 index 0000000..e357246 Binary files /dev/null and b/docs/images/branch-protection.png differ diff --git a/docs/images/dockerhub-tag-detalle.png b/docs/images/dockerhub-tag-detalle.png new file mode 100644 index 0000000..38c84ad Binary files /dev/null and b/docs/images/dockerhub-tag-detalle.png differ diff --git a/docs/images/dockerhub-tags.png b/docs/images/dockerhub-tags.png index 41b7888..d17cde5 100644 Binary files a/docs/images/dockerhub-tags.png and b/docs/images/dockerhub-tags.png differ diff --git a/docs/images/pipeline-release.png b/docs/images/pipeline-release.png index 876e02d..d6f39f5 100644 Binary files a/docs/images/pipeline-release.png and b/docs/images/pipeline-release.png differ diff --git a/docs/images/render-deploy-hook.png b/docs/images/render-deploy-hook.png new file mode 100644 index 0000000..6e3d8a2 Binary files /dev/null and b/docs/images/render-deploy-hook.png differ diff --git a/docs/images/render-servicio.png b/docs/images/render-servicio.png new file mode 100644 index 0000000..cfa6cd6 Binary files /dev/null and b/docs/images/render-servicio.png differ