Herramientas de usuario

Herramientas del sitio


clase:daw:daw-proyecto:tema07

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
clase:daw:daw-proyecto:tema07 [2026/10/14 09:55] – Coherencia del flujo: /revisar-ci, npm run test:api|test:e2e, scripts arrancar/parar/estado/logs también en el servidor (sin manage.sh), tests y revisión de calidad en su fase claudeclase:daw:daw-proyecto:tema07 [2026/10/14 14:08] (actual) – Tema nuevo «2. IA y agentes»: los temas 2 a 7 pasan a ser 3 a 8, con sus referencias cruzadas renumeradas claude
Línea 1: Línea 1:
-====== 7. Resumen ======+====== 7. Despliegue en el proyecto ======
  
-La fábrica está montada. Esta página es la que se tiene abierta mientras se trabaja en la 2ª evaluación: el flujo en pasos, la chuleta de las skills y la lista de comprobación. El diagrama del flujo con quién hace cada cosa está en el [[.:tema01#el_ciclo_de_vida_de_un_cambio|tema 1]].+Objetivo del tema: ''/git-flow publish'' = producción actualizada, **sin entrar nunca al servidor**. Y en cada push, GitHub compila y pasa todos los tests. ''develop'' no se despliega en ningún sitio: es local.
  
-===== El flujo, en pasos =====+Lo que ya sabéis: qué es GitHub Actions y un primer workflow con VPN y SSH, en [[clase:daw:daw:1eval:tema05#github_actions|Despliegue 5]]; cómo funciona nginx-proxy con ''VIRTUAL_HOST'', en [[clase:daw:daw:1eval:tema04.c#proxy_con_nginx|Despliegue 4.c]]. Lo nuevo aquí es sustituir la VPN y el SSH por un **runner dentro del servidor**.
  
-**Por cada issue** (varios a la vez, cada uno en su worktree):+===== El servidor =====
  
-  - Crear el issue en GitHub y ponerlo en el tablero. +Un VPS compartido por toda la clase, con tres cosas montadas por el profesor:
-  - ''/git-flow iniciar N'': rama, worktree y ''.env'' con sus puertos. ''cd'' al worktree y ''./arrancar.sh''. +
-  - Modo plan: decir qué se quiere, pedir que pregunte, revisar el plan. Sale ''planes/N-slug.md''. +
-  - ''/clear'' y ''Ejecuta @planes/N-slug.md''. Si el issue es un CRUD, en vez del plan: ''/kiro-spec-init'', ''requirements'', ''design -y'', ''tasks -y'' e ''impl''. +
-  - Los tests: ''/crear-test-unitarios'' para el dominio que haya cambiado, ''/crear-test-api'' para los endpoints nuevos y ''/crear-test-e2e planes/N-slug.md''. Y ''/crear-test-arquitectura'' si hay reglas nuevas. Si el issue era un CRUD, a partir de su ''requirements.md''. +
-  - Pasar los tests: ''mvn test'', ''npm run test:api'' y ''npm run test:e2e''. Probar en la URL del worktree; si ha cambiado el backend, ''./arrancar.sh'' antes. +
-  - ''/revisar-calidad'' sobre el paquete del issue; corregir los graves. +
-  - ''/git-flow commit''. +
-  - ''/git-flow finalizar'': pasa ''/revisar''; si no hay nada grave, fusiona en ''develop'' y GitHub cierra el issue. CI en ''develop''; si sale en rojo, ''/revisar-ci''.+
  
-**Cuando hay algo que sacar:**+  * **Docker.** 
 +  * **nginx-proxy** en la red ''nginx-proxy-network'', escuchando en el 80. Cada aplicación se publica sola por su ''VIRTUAL_HOST'': ''<alumno>.proyectosdaw.cip.fpmislata.com'', que ya está en ''compose.yaml'' desde el tema 4. 
 +  * **Un runner autoalojado de GitHub por alumno**, registrado contra su repositorio. Un runner es un proceso que espera trabajos de GitHub Actions y los ejecuta **en la máquina donde está instalado**. Como está en el servidor, un workflow que se ejecute en él puede hacer ''docker compose'' directamente: ni SSH, ni VPN, ni registro de imágenes. El profesor lo registra con el token que da GitHub en //Settings → Actions → Runners → New self-hosted runner//; es la única vez que alguien entra al servidor.
  
-  - ''/revisar-calidad'' sobre todo el backend; corregir los graves. +<note>Todos los runners comparten el Docker del servidor, así que con ''docker ps'' cada uno ve los contenedores de los demás. Es un servidor de clase y se asume. Lo que separa a cada alumno es el nombre de proyecto de Compose (el del repositorio) y su subdominio.</note>
-  - ''/git-flow publicar'': ''develop'' → ''main'', CI, despliegue en el servidor, smoke test. Si sale en rojo, ''/revisar-ci''.+
  
-===== Scripts y comandos =====+===== Los mismos scripts =====
  
-^ Comando ^ Dónde ^ Qué hace ^ +En el servidor no hay nada nuevo que aprender: la aplicación se opera con el **mismo script** del tema 4, ''app.sh'', con sus cuatro subcomandos. Lo único que cambia es una variable de entorno que fija el workflow:
-| ''./arrancar.sh'' | raíz del worktree | Levanta la aplicación del worktree (reconstruyendo lo que ha cambiado) y dice su URL | +
-| ''./parar.sh'' | raíz del worktree | La para conservando los datos; con ''-v'' borra la base de datos | +
-| ''./estado.sh'' | raíz del worktree | Estado de sus contenedores | +
-| ''./logs.sh'' | raíz del worktree | Últimas líneas de log de sus contenedores |+
  
-Los mismos cuatro operan la aplicación en el servidor, lanzados desde GitHub (tema 6).+<sxh bash> 
 +COMPOSE_FILE=compose.yaml 
 +</sxh>
  
-===== Los tres comandos de tests =====+  * Con ''COMPOSE_FILE=compose.yaml'' Compose carga solo producción: el ''compose.override.yaml'' de desarrollo no se aplica, así que ni ''ng serve'', ni puertos publicados, ni datos de prueba. 
 +  * ''app.sh start'' hace ''up -d --build --wait'': construye la imagen con el código del commit, sustituye los contenedores que han cambiado y espera a los ''healthcheck''. Nunca hace ''down -v'': el volumen ''db-data'' se queda y un despliegue **nunca borra la base de datos**; Flyway aplica las migraciones nuevas al arrancar. 
 +  * Los workflows solo llaman a ''app.sh'', así que lo mismo que hace GitHub se puede lanzar a mano desde el servidor si un día hace falta.
  
-^ Comando ^ Dónde ^ Qué pasa ^ +===== Secretos =====
-| ''mvn test'' | ''backend/'' | Unitarios y ArchUnit. No necesita nada levantado | +
-| ''npm run test:api'' | ''frontend/'' | Resetea la base de datos y pasa los de API contra la aplicación del worktree. No forman parte del build | +
-| ''npm run test:e2e'' | ''frontend/'' | Lo mismo con los E2E |+
  
-===== Chuleta de skills =====+La contraseña de la base de datos de producción no está en ningún fichero: está en //Settings → Secrets and variables → Actions// del repositorio como ''DB_PASSWORD''. El workflow la pasa como variable de entorno a ''app.sh'' y Compose la lee en ''${DB_PASSWORD}''. En desarrollo esa misma variable viene del ''.env'' del worktree.
  
-^ Skill ^ Para qué ^ +===== Los workflows =====
-| ''/git-flow iniciar N'' | Empezar un issue: rama, worktree y ''.env'' con puertos | +
-| ''/git-flow commit'' | Agrupar los cambios en commits con sentido, ''type(#N):título'' | +
-| ''/git-flow actualizar'' | Traer ''develop'' a la rama | +
-| ''/git-flow finalizar'' | Revisar, fusionar en ''develop'' con ''Closes #N'', push, parar contenedores y borrar el worktree | +
-| ''/git-flow publicar'' | ''develop'' → ''main'': despliega | +
-| ''/crear-test-arquitectura'' | Reglas en castellano → tests ArchUnit con descripción | +
-| ''/crear-test-unitarios <clase>'' | Un test JUnit por comportamiento del dominio, con Mockito | +
-| ''/crear-test-api <Entidad>'' | Un test Playwright por endpoint y por error previsto | +
-| ''/crear-test-e2e <plan>'' | Criterios de aceptación → tests Playwright pasando | +
-| ''/revisar'' | Diff contra el plan y las convenciones, grave / mejorable | +
-| ''/revisar-calidad <ruta>'' | Informe de calidad del código con las reglas de ''calidad-codigo''; no toca nada | +
-| ''/kiro-spec-init'' … ''/kiro-impl'' | Un CRUD con cc-sdd, igual que el de referencia gracias al steering | +
-| ''/revisar-ci'' | Seguir el workflow y diagnosticar si falla | +
-| ''convenciones-backend'', ''convenciones-frontend'', ''calidad-codigo'' | No se invocan: el agente las carga al tocar código |+
  
-===== Listo para la 2ª evaluación =====+Un solo fichero para CI y CD:
  
-Antes de empezar el proyecto, todo esto tiene que estar hecho y comprobado:+<sxh yaml;title:.github/workflows/ci-cd.yml> 
 +name: CI/CD
  
-  * Tablero creado y un issue de prueba cerrado solo por el commit de ''finalizar''. +on: 
-  * Dos worktrees con la aplicación levantada a la vez, cada uno con sus datos. +  push: 
-  * Un CRUD hecho con el flujo de plan y un segundo con cc-sdd, iguales. +    branches: [develop, main] 
-  * Steering de cc-sdd con ''backend.md'' y ''frontend.md'' condicionales, y las skills de convenciones apuntando a ellos. +  workflow_dispatch: 
-  * ''convenciones-backend'' y ''convenciones-frontend'' escritas a partir del primer CRUD. + 
-  * Tests ArchUnit con su descripción y unitarios pasando en ''mvn test''. +jobs: 
-  * Tests de API y E2E generados pasando en ''npm run test:api'' y ''npm run test:e2e''. +  ci: 
-  * ''/git-flow finalizar'' se para ante una revisión con algo grave. +    runs-on: ubuntu-latest 
-  * CI en verde en ''develop''. +    steps: 
-  * Una publicación en ''main'' desplegada sola en ''%%http://<alumno>.proyectosdaw.cip.fpmislata.com%%''. +      - uses: actions/checkout@v4 
-  * ''AGENTS.md'' con: comandos, dónde corren los tests, git solo con ''/git-flow'', ''planes/'' es histórico.+      - uses: actions/setup-java@v4 
 +        with: { distribution: temurin, java-version: 25 } 
 +      - uses: actions/setup-node@v4 
 +        with: { node-version: 22 } 
 + 
 +      - name: Levantar la aplicación 
 +        env: { DB_PASSWORD: ci } 
 +        run: | 
 +          docker network create nginx-proxy-network 
 +          docker compose up -d --build --wait 
 + 
 +      - name: Tests del backend (unitarios y ArchUnit) 
 +        working-directory: backend 
 +        run: mvn -B test 
 + 
 +      - name: Tests de API y E2E 
 +        working-directory: frontend 
 +        run: | 
 +          npm ci 
 +          npx playwright install --with-deps chromium 
 +          npm run test:api 
 +          npm run test:e2e 
 + 
 +  deploy: 
 +    needs: ci 
 +    if: github.ref == 'refs/heads/main' 
 +    runs-on: self-hosted 
 +    steps: 
 +      - uses: actions/checkout@v4 
 +      - name: Desplegar 
 +        env: 
 +          COMPOSE_FILE: compose.yaml 
 +          DB_PASSWORD: ${{ secrets.DB_PASSWORD }} 
 +        run: ./app.sh start 
 +      - name: Smoke test 
 +        run: curl -fsS http://<alumno>.proyectosdaw.cip.fpmislata.com/api/clientes > /dev/null 
 +</sxh> 
 + 
 +Lo que hay que entender: 
 + 
 +  * **''ci'' corre en un runner de GitHub** (''ubuntu-latest''), en cada push a ''develop'' y a ''main''. Levanta la aplicación con el mismo ''compose.yaml'' + ''compose.override.yaml'' del portátil (sin ''.env'': valen los puertos por defecto y el perfil ''datos-prueba''), y pasa los tests con los mismos comandos que en el worktree: ''mvn test'', ''npm run test:api'' y ''npm run test:e2e''. ''--wait'' espera a los ''healthcheck''. 
 +  * **''deploy'' corre en el runner del servidor** (''self-hosted''), solo en ''main'' y solo si ''ci'' ha pasado (''needs''). Hace ''checkout'' del commit y ''./app.sh start'' con ''COMPOSE_FILE=compose.yaml'': la imagen se construye en el servidor con ese código. 
 +  * **El smoke test** es el último paso: una petición a la URL de producción que tiene que responder 200. Si el despliegue ha dejado la aplicación caída, el workflow sale en rojo y se ve en el acto. 
 +  * ''workflow_dispatch'' permite relanzarlo a mano desde la pestaña //Actions// (siempre sobre ''main''). 
 + 
 +Y dos workflows pequeños de operación, ''status.yml'' y ''logs.yml'', solo con ''workflow_dispatch'' y un paso ''./app.sh status'' o ''./app.sh logs'' (con el mismo ''COMPOSE_FILE'') en ''self-hosted''. Son la forma de ver qué pasa en producción sin acceso al servidor: se lanzan desde //Actions// y la salida queda en el log del workflow. 
 + 
 +===== La IA y los workflows ===== 
 + 
 +El YAML lo escribe el agente a partir de lo de arriba. Y no hay skill para cuando CI sale en rojo, porque **no debería salir en rojo**: pasa los mismos comandos que ''/git-flow finish'' acaba de pasar en el worktree. Si sale, es que algo distingue el runner del portátil (un fichero que no está en git, una variable, un puerto) o que ha fallado el despliegue o el smoke test. Un workflow rojo tiene un log largo y la causa está en tres líneas: se abre el paso fallido en //Actions//, se copia su log y se le pregunta al agente en una conversación nueva. Desde la terminal, ''gh run view --log-failed'' da solo los pasos que han fallado, que es lo que hay que pegarle (tema 5: no pegarle logs enteros). 
 + 
 +===== Ejercicios ===== 
 + 
 +==== Ejercicio 1 ==== 
 +  * Crea un issue «CI» e inícialo. 
 +  * Comprueba que ''app.sh'' funciona como lo va a ejecutar el servidor, sin ''.env'' y solo con producción: ''COMPOSE_FILE=compose.yaml ./app.sh start'' desde el repositorio principal, ''./app.sh status'' y luego ''./app.sh stop''. 
 +  * Añade el secreto ''DB_PASSWORD'' en //Settings → Secrets and variables → Actions//. 
 +  * Escribe ''.github/workflows/ci-cd.yml'' solo con el job ''ci''. Finaliza el issue y mira en //Actions// cómo se ejecuta en el push a ''develop''. Si sale en rojo, arréglalo hasta que esté en verde. 
 + 
 +==== Ejercicio 2 ==== 
 +  * Pide al profesor que registre tu runner en el servidor. Comprueba en //Settings → Actions → Runners// que aparece como //Idle//. 
 +  * Crea un issue «Despliegue» e inícialo. Añade el job ''deploy'' al workflow con el ''needs: ci'', el ''if'' sobre ''main'' y el smoke test contra tu URL. 
 +  * Finaliza el issue y ''/git-flow publish''. Sigue la ejecución en //Actions// y comprueba que la aplicación responde en ''%%http://<alumno>.proyectosdaw.cip.fpmislata.com%%''. 
 + 
 +==== Ejercicio 3 ==== 
 +  * Añade ''status.yml'' y ''logs.yml'' con ''workflow_dispatch'' sobre ''self-hosted''. 
 +  * Lánzalos desde //Actions// y lee la salida de ''app.sh status'' en el log. 
 + 
 +==== Ejercicio 4 ==== 
 +  * Cambia a propósito la URL del smoke test por una que no existe, finaliza el issue y publica. CI pasa y ''deploy'' sale en rojo. Copia el log del paso fallido, pregúntaselo al agente y comprueba que señala la URL. Arréglala y vuelve a publicar. 
 +  * Haz un cambio visible en la aplicación, finaliza y publica. Comprueba en producción que el cambio está y que los datos que había siguen estando. 
 + 
 +Fuera de este tema, por ser de un sistema real y no de un proyecto de clase: entornos de ''dev'' y ''pre'', copias de seguridad, copiar datos de producción, tareas programadas y HTTPS (el proxy sirve HTTP).
  
clase/daw/daw-proyecto/tema07.1791964551.txt.gz · Última modificación: por claude