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 12:55] – Fases en inglés: Start, Specification, Implementation, Testing, Review & Finish, Publish 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 gramática de los comandos y la lista de comprobación. La figura del ciclo 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). Cada fase, en una conversación nueva:+===== El servidor =====
  
-  - **Start.** Crearlo en GitHub y ponerlo en el tablero. ''/git-flow start N'': rama, worktree y ''.env'' con sus puertos. ''cd'' al worktree y ''./app.sh start''. +Un VPS compartido por toda la clase, con tres cosas montadas por el profesor:
-  - **Specification.** ''/sdd spec create''. Leer y corregir ''requirements.md'' (criterios comprobables, casos de error), ''design.md'' (igual que el CRUD de referencia) y ''tasks.md''. Si se cambia algo, volver a generar. +
-  - **Implementation.** ''/sdd spec impl''. Si ha cambiado el backend, ''./app.sh start'' para reconstruirlo. Probar en la URL del worktree. +
-  - **Testing.** ''/test unit create <Servicio>'', ''/test api create <Entidad>'' y ''/test e2e create''. Después, uno a uno, ''/test unit run'', ''/test api run'' y ''/test e2e run''. Si un cambio posterior rompe tests, ''/test <tipo> repair''. +
-  - **Review & Finish.** ''/code review''. Leer ''review.md'', cerrar a mano los mejorables que no se hacen, y ''/code impl review.md''. Después ''/git-flow commit'' y ''/git-flow finish'': comprueba tareas, revisión y tests; fusiona en ''develop'' y GitHub cierra el issue. CI en ''develop'' pasa lo mismo que acaba de pasar ''finish''.+
  
-**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.
  
-  - **Publish.** ''/git-flow publish'': ''develop'' → ''main'', CI, despliegue en el servidor, smoke test. Si sale en rojo, copiar el log del paso fallido y preguntárselo al agente.+<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>
  
-===== La gramática =====+===== Los mismos scripts =====
  
-Siempre **familia, sustantivo y verbo**, como ''docker container ls'' o ''gh issue create''; el sustantivo se omite cuando es el issue en el que se está (''/git-flow start'', ''/code review''), como en ''docker login''. Lo que empieza por ''/'' es una skill; lo que acaba en ''.sh'', un script.+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:
  
-^ Familia ^ Subcomando ^ Qué hace ^ +<sxh bash> 
-| ''/git-flow'' | ''start N'' | Rama ''<alumno>-N-<slug>'', worktree hermano y ''.env'' con puertos libres. No levanta la aplicación | +COMPOSE_FILE=compose.yaml 
-| | ''commit'' | Agrupa los cambios por intención en commits ''type(#N): título'' y los propone antes de hacerlos | +</sxh>
-| | ''update'' | Trae ''develop'' a la rama; si hay conflicto, se para y dice qué hacer | +
-| | ''finish'' | Comprueba tareas, revisión y tests; ''--squash'' en ''develop'' con ''Closes #N'', push, ''./app.sh stop -v'', borra el worktree | +
-| | ''publish'' | ''develop'' → ''main'' con ''--ff-only'' y push: despliega | +
-| ''./app.sh'' | ''start'' | Levanta la aplicación del worktree reconstruyendo lo que ha cambiado y dice su URL. En el servidor, lo mismo con ''COMPOSE_FILE=compose.yaml'' | +
-| | ''stop [-v]'' | La para conservando los datos; con ''-v'' borra la base de datos | +
-| | ''status'' | Estado de sus contenedores | +
-| | ''logs'' | Últimas líneas de log de sus contenedores | +
-| ''/sdd'' | ''spec create'' | Lee el issue de la rama y genera requisitos, diseño y tareas en ''.kiro/specs/N-slug/'' con cc-sdd. Se puede relanzar | +
-| | ''spec impl'' | Implementa las tareas pendientes de ''tasks.md'', tests unitarios y de arquitectura tras cada una | +
-| ''/test'' | ''arch create'' / ''unit create <Clase>'' / ''api create <Entidad>'' / ''e2e create'' | Genera los tests de ese tipo y los deja pasando. ''arch'', una vez por proyecto | +
-| | ''arch run'' / ''unit run'' / ''api run'' / ''e2e run'' | Los ejecuta, siempre un tipo cada vez, y explica el rojo | +
-| | ''arch repair'' / ''unit repair'' / ''api repair'' / ''e2e repair'' | Por cada test roto decide si está mal el test o el código y arregla lo que toca; si no lo sabe, pregunta | +
-| ''/code'' | ''review'' | El código contra la spec, las convenciones y ''calidad-codigo''; los tests contra los criterios de aceptación y ''tests.md''. Cada hallazgo, una tarea en ''review.md''. No bloquea | +
-| | ''impl <plan>'' | Hace las tareas pendientes de un fichero markdown que no es la spec: ''review.md'' o un plan escrito a mano. ''/test unit run'' tras cada una |+
  
-Fuera de la gramática, por ser de cc-sdd y usarse una vez: ''/kiro-steering'' y ''/kiro-steering-custom'' (tema 4). Y las skills de conocimiento, que no se invocan: ''convenciones-backend'', ''convenciones-frontend'' y ''calidad-codigo''.+  * 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.
  
-===== Los comandos de tests, sin skill =====+===== Secretos =====
  
-Son los que ejecutan ''/test <tipo> run'' por dentro y CI sin ninguna IA:+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.
  
-^ Comando ^ Dónde ^ Qué pasa ^ +===== Los workflows =====
-| ''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 |+
  
-===== 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 ''finish''. +on: 
-  * Dos worktrees con la aplicación levantada a la vez, cada uno con sus datos. +  push: 
-  * Dos CRUD hechos con ''/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: 
-  * Tests ArchUnit con su descripción y unitarios pasando en ''mvn test''. + 
-  * Tests de API y E2E generados pasando en ''npm run test:api'' y ''npm run test:e2e''. +jobs: 
-  * ''/test <tipo> repair'' ha actualizado un test por un cambio intencionado y ha arreglado el código por una regresión. +  ci: 
-  * ''/code review'' ha dejado hallazgos en ''review.md'', ''/git-flow finish'' se ha parado por uno abierto y ''/code impl'' lo ha corregido. +    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'', ''.kiro/specs/'' 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.1791975303.txt.gz · Última modificación: por claude