Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 37 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -211,7 +224,11 @@ complejidad recomendada para equipos pequeños — el caso de este TP.

**Protección de `main`:**

<!-- branch-protection.png: captura pendiente de agregar (Settings > Branches para 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
Expand Down Expand Up @@ -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)

<!-- dockerhub-tag-detalle.png: captura pendiente de agregar (detalle del tag v0.3.0: linux/amd64, tamaño) -->
_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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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.
37 changes: 21 additions & 16 deletions docs/estado-del-proyecto.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -80,16 +81,20 @@ 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.

## Antes de la demo y la defensa

- [ ] **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.
Expand All @@ -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 |
Binary file added docs/images/branch-protection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/dockerhub-tag-detalle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/dockerhub-tags.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/pipeline-release.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/render-deploy-hook.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/render-servicio.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading