Herramientas de usuario

Herramientas del sitio


clase:daw:daw-proyecto:tema06

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:tema06 [2026/10/14 00:39] – CI con mvn verify y npm run e2e claudeclase:daw:daw-proyecto:tema06 [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:
-====== 6. Despliegue en el proyecto ======+====== 6. Automatizando el proyecto con IA ======
  
-Objetivo del tema: ''/git-flow publicar'' = 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.+Objetivo del tema: que la calidad la vigilen **tests que genera la IA** en los cuatro niveles (arquitectura, unitarios, API y E2E) y **revisiones que hace la IA** antes de cerrar un issue. Al acabar, ''/git-flow finish'' no cierra nada que no tenga los tests en verde y la revisión limpia, y todo lo demás ocurre solo.
  
-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**.+Una skill nueva, ''/test'', y un verbo nuevo para ''/code'', con la gramática del tema 1:
  
-===== El servidor =====+^ Skill ^ Sustantivos ^ Verbos ^ 
 +| ''/test'' | ''unit'', ''arch <reglas>'', ''api <escenarios>'', ''e2e <escenarios>'' | ''create'', ''run'', ''repair''. Siempre con el tipo delante: no hay un «todos» | 
 +| ''/code'' | el issue, implícito | ''review'' (nuevo) e ''impl <plan>'' (tema 5) |
  
-Un VPS compartido por toda la clase, con tres cosas montadas por el profesor:+===== Los cuatro tipos de tests =====
  
-  * **Docker.** +^ Tipo ^ Qué prueba ^ Con qué ^ Necesita ^ Lo ejecuta ^ 
-  * **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 3. +| ''arch'' | Que cada clase está en su capa y depende de lo que debe | ArchUnit | Nada | ''mvn test'', dentro del build | 
-  * **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.+| ''unit'' | La lógica del dominio, servicio a servicio | JUnit 5 y Mockito, sin Spring | Nada | ''mvn test'', dentro del build | 
 +| ''api'' | Cada endpoint de verdad: HTTP, código de estado y JSON | Playwright (fixture ''request'') | La aplicación del worktree levantada y la base de datos reseteada | ''npm run test:api'', fuera del build | 
 +| ''e2e'' | La aplicación completa desde el navegador, criterio a criterio | Playwright con Chromium | Lo mismo | ''npm run test:e2e'', fuera del build |
  
-<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>+Los dos primeros forman parte del build de Maven: corren en cada compilación y no necesitan nada levantado. Los dos últimos **no forman parte del build**: son lentos, necesitan la aplicación y se lanzan cuando se quiere. Los comandos son los mismos para el alumno, para el agente y para CI (tema 7); lo que añade ''/test'' es no tener que recordarlos y, cuando algo sale en rojo, que el agente lo explique.
  
-===== manage.sh =====+===== Crear los tests: /test <tipo> create =====
  
-Una única entrada para operar la aplicación en el servidor, en el repositorio:+==== arch: tests de arquitectura con ArchUnit ====
  
-<sxh bash;title:manage.sh> +Las reglas de arquitectura (las de Programación y DWS: capas, nombres, sin ciclos, ''domain'' sin Spring) las hace cumplir ArchUnit con tests que fallan cuando una clase está donde no debe. Lo nuevo es que **los escribe la IA** a partir de las reglas en castellano, que son el argumento. Se lanza al empezar el proyecto y cuando cambia una regla, no por issue:
-#!/bin/bash +
-set -e +
-cd "$(dirname "$0")" +
-compose="docker compose -f compose.yaml"+
  
-case "$1" in +<code> 
-  deploy) $compose down; $compose build; $compose up -d ;; +/test arch create 
-  status) $compose ps ;; +- Las clases de controller solo dependen de domain. 
-  logs)   $compose logs --tail=200 ;; +- Las de persistence solo dependen de domain. 
-  *) echo "uso: $0 deploy|status|logs"; exit 1 ;; +- Nada en domain importa org.springframework ni jakarta.persistence. 
-esac+- Los controladores acaban en Controller y están en ..controller.. 
 +- Los repositorios de persistence acaban en RepositoryImpl e implementan una interfaz de domain. 
 +- Sin ciclos entre paquetes. 
 +</code> 
 + 
 +Cada test lleva en su ''@DisplayName'' y en un comentario **qué comprueba, por qué y las excepciones**: 
 + 
 +<sxh java> 
 +@Test 
 +@DisplayName("domain no depende de Spring: el dominio tiene que compilar y probarse sin el framework") 
 +void domainSinSpring() { 
 +    noClasses().that().resideInAPackage("..domain..") 
 +        .should().dependOnClassesThat().resideInAPackage("org.springframework..") 
 +        .check(clases); 
 +}
 </sxh> </sxh>
  
-  * ''-f compose.yaml'': solo producción, sin el override de desarrollo. +**No hay un documento aparte con la arquitectura.** Mantener un Markdown sincronizado con los tests es un trabajo que nadie hace, así que la fuente de verdad son los tests con su descripción. Para cambiar una regla se le pide a la skill que cambie el test. Cuando se añade una regla que el código actual aún no cumple, ''FreezingArchRule.freeze(regla)'' congela las violaciones existentes y solo falla con las nuevas.
-  * ''down'' **sin ''-v''**: se paran los contenedores pero el volumen ''db-data'' se queda. Un despliegue **nunca borra la base de datos**; Flyway aplica las migraciones nuevas al arrancar. +
-  * Los workflows solo llaman a ''manage.sh'', así que lo mismo que hace GitHub se puede lanzar a mano desde el servidor si un día hace falta.+
  
-===== Secretos =====+==== unit: tests unitarios con JUnit ====
  
-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 ''manage.sh'' y Compose la lee en ''${DB_PASSWORD}''. En desarrollo esa misma variable viene del ''.env'' del worktree.+Los tests unitarios prueban la lógica del dominio **sin Spring y sin base de datos**: un servicio con sus repositorios sustituidos por mocks de Mockito. Son los más rápidos y los que mejor localizan un error.
  
-===== Los workflows =====+<code> 
 +/test unit create 
 +</code>
  
-Un solo fichero para CI y CD:+Sin argumento genera los de todas las clases que no los tienen; con una clase o un paquete (''/test unit create PedidoService''), solo esos.
  
-<sxh yaml;title:.github/workflows/ci-cd.yml> +Lo que hace: lee la clase, identifica cada comportamiento (lo que devuelve, lo que valida, lo que lanza) y escribe un test por comportamiento en ''backend/src/test/java'', con el mismo paquete, ''@DisplayName'' en castellano que diga el caso y Mockito para las dependencias. Los ejecuta y se para si alguno falla por un error del código, en vez de retocar el test para que pase.
-name: CI/CD+
  
-on: +Qué no prueban: controladores ni repositorios. Eso es de los tests de API.
-  push: +
-    branches: [develop, main] +
-  workflow_dispatch:+
  
-jobs: +==== api: tests de API con Playwright ====
-  ci: +
-    runs-on: ubuntu-latest +
-    steps: +
-      - uses: actions/checkout@v4 +
-      - 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 +Los tests de API prueban cada endpoint **de verdad**: peticiones HTTP contra el backend del worktree, comprobando el código de estado y el JSON. Se escriben con Playwright, igual que los E2E (mismo lenguaje, misma configuración, misma carpeta): Playwright trae para esto el fixture ''request'', que hace peticiones sin abrir ningún navegador.
-        env: { DB_PASSWORD: ci } +
-        run: | +
-          docker network create nginx-proxy-network +
-          docker compose up -d --build --wait+
  
-      - name: Tests del backend (unitarios, ArchUnit y API) +<code> 
-        working-directory: backend +/test api create Pedido: alta válida, sin cliente, cliente que no existe, borrar uno con líneas 
-        env: { DB_PORT: 3306, DB_PASSWORD: ci } +</code>
-        run: mvn -B verify+
  
-      - name: Tests E2E +El argumento son los **escenarios**: qué hay que probar, en texto. Por cada uno, en ''frontend/tests/api/pedidos.spec.ts'', un test que hace la petición y comprueba el código de estado y el JSON; lo normal es el caso bueno de cada endpoint y cada error que la spec o las validaciones prevén: ''400'' con un campo obligatorio vacío, ''404'' con un id que no existe, ''409'' con un valor único repetido. Los datos de partida son los del ''%%R__%%'' de la entidad; los tests que escriben se limpian a sí mismos (borran lo que crean) para que se puedan pasar dos veces seguidas.
-        working-directory: frontend +
-        run: | +
-          npm ci +
-          npx playwright install --with-deps chromium +
-          npm run e2e+
  
-  deploy: +<sxh typescript> 
-    needs: ci +test('POST /api/pedidos sin número devuelve 400 y el nombre del campo', async ({ request }) => { 
-    if: github.ref == 'refs/heads/main' +  const res = await request.post('/api/pedidos', { data: { fecha: '2026-10-14', clienteId: 1 } }); 
-    runs-on: self-hosted +  expect(res.status()).toBe(400); 
-    steps: +  expect((await res.json()).errores.numero).toBeDefined(); 
-      - uses: actions/checkout@v4 +});
-      - name: Desplegar +
-        env: +
-          DB_PASSWORD: ${{ secrets.DB_PASSWORD }} +
-        run: ./manage.sh deploy +
-      - name: Smoke test +
-        run: curl -fsS http://lorenzo.proyectosdaw.cip.fpmislata.com/api/clientes > /dev/null+
 </sxh> </sxh>
  
-Lo que hay que entender:+Los de API y los E2E son dos **proyectos** del mismo ''playwright.config.ts'', separados por carpeta; el de API no necesita navegador:
  
-  * **''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 verify'' y ''npm run e2e''. ''--wait'' espera a los ''healthcheck''. +<sxh typescript;title:frontend/playwright.config.ts> 
-  * **''deploy'' corre en el runner del servidor** (''self-hosted''), solo en ''main'' y solo si ''ci'' ha pasado (''needs''). Hace ''checkout'' del commit y ''manage.sh deploy'': la imagen se construye en el servidor con ese código. +export default defineConfig({ 
-  * **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. +  use: { baseURL: process.env.BASE_URL ?? 'http://localhost:4200' }, 
-  * ''workflow_dispatch'' permite relanzarlo a mano desde la pestaña //Actions// (siempre sobre ''main'').+  projects: [ 
 +    { name: 'api', testDir: 'tests/api' }, 
 +    { name: 'e2e', testDir: 'tests/e2e', use: { browserName: 'chromium' } }, 
 +  ], 
 +}); 
 +</sxh>
  
-Y dos workflows pequeños de operación, ''status.yml'' y ''logs.yml'', solo con ''workflow_dispatch'' y un paso ''./manage.sh status'' o ''./manage.sh logs'' 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.+==== e2e: tests E2E con Playwright ====
  
-===== La IA y los workflows =====+Los tests E2E prueban la aplicación completa desde el navegador, como lo haría el usuario. Los criterios de aceptación de ''requirements.md'' son frases comprobables; ''e2e'' las convierte en tests de Playwright en TypeScript, ''frontend/tests/e2e/<entidad>.spec.ts'', y los deja pasando. El argumento son los escenarios; lo normal es pasarle los criterios de la spec:
  
-El YAML lo escribe el agente a partir de lo de arriba. Donde de verdad ayuda es cuando algo falla: un workflow rojo tiene un log largo y la causa está en tres líneas. La skill ''/ci-revisar'' sigue la ejecución y, si falla, la lee y propone el arreglo:+<code> 
 +/test e2e create los criterios de aceptación de requirements.md 
 +</code>
  
-<sxh bash> +Cómo trabaja: lee los criterios, abre la aplicación del worktree con el Playwright MCP para ver qué hay en pantalla, escribe el test y lo ejecuta; si falla por un selector o un texto, lo arregla y lo vuelve a pasar. La IA interviene **al generar**, no al ejecutar: lo que queda en el repositorio es un ''.spec.ts'' normal, determinista, que CI ejecuta sin ninguna IA. 
-gh run list --limit 5 + 
-gh run watch                       # sigue la última ejecución +Reglas que la skill tiene que respetar (están en ''convenciones-frontend''): 
-gh run view <id> --log-failed      # solo los pasos que han fallado + 
-</sxh>+  * Selectores por ''data-testid'' y por rol (''getByRole'', ''getByLabel''), nunca por clase CSS. Un test que depende del CSS se rompe al primer cambio de estilo. 
 +  * Un test por criterio de aceptación, con el criterio como nombre del test. 
 +  * Los tests cuentan con los datos de prueba del tema 4 y **se pasan sobre la base de datos recién reseteada**. 
 + 
 +===== Ejecutarlos: /test <tipo> run ===== 
 + 
 +Ejecuta los tests de un tipo y, si algo sale en rojo, lo explica: qué test, qué esperaba, qué ha pasado y dónde mirar. Por dentro son los comandos del tema 4, que es lo que ejecuta CI sin ninguna skill: 
 + 
 +^ Verbo ^ Comando ^ 
 +| ''/test arch run'' | ''mvn test -Dtest='*ArchTest''' desde ''backend/'' | 
 +| ''/test unit run'' | ''mvn test -Dtest='!*ArchTest''' desde ''backend/'' | 
 +| ''/test api run'' | ''npm run test:api'' desde ''frontend/'' (resetea la base de datos y levanta la aplicación antes) | 
 +| ''/test e2e run'' | ''npm run test:e2e'' desde ''frontend/'' (igual) | 
 + 
 +No hay un «todos» a propósito: los tipos se lanzan **uno a uno**, en ese orden, para saber en cada momento qué se está probando y contra qué. Para que ''arch'' y ''unit'' se puedan separar, los tests de ArchUnit acaban en ''ArchTest'' y los unitarios en ''Test''. En ''/sdd spec impl'' es ''/test unit run'' lo que pasa después de cada tarea. 
 + 
 +===== Repararlos: /test <tipo> repair ===== 
 + 
 +Pasa mucho: se cambia algo del código, se refactoriza, y se rompen tests, sobre todo los E2E. ''repair'' pasa los tests de un tipo y, por cada uno que falla, decide **qué está mal, el test o el código**, y arregla lo que corresponda: 
 + 
 +<code> 
 +/test e2e repair 
 +</code> 
 + 
 +El criterio es la **intención**: 
 + 
 +  * Un test está desactualizado solo si un cambio **intencionado** del código (un commit, o un cambio sin commitear que el alumno ha hecho a propósito) modificó o eliminó lo que el test comprueba: el texto de un mensaje, un campo, un flujo. Entonces se actualiza el test. 
 +  * Sin un cambio intencionado que lo justifique, el fallo es una **regresión**: se arregla el código y el test no se toca. 
 +  * Si no se sabe, **no se toca nada** y se pregunta. 
 + 
 +Y tres reglas que no se negocian, porque sin ellas «reparar» acaba siendo «hacer que pase»: 
 + 
 +  * Nunca quita, comenta ni relaja una aserción, salvo que el cambio intencionado lo obligue. Nunca crea tests nuevos: para eso está ''create''. 
 +  * Borra un test solo si lo que comprobaba ya no existe en la aplicación, y entero, no vaciado ni comentado. 
 +  * Un test cada vez, sin commits, y al final una tabla: test, diagnóstico (desactualizado / regresión / sin determinar) y qué se ha cambiado. El alumno la lee y decide si está de acuerdo. 
 + 
 +''repair'' deja un fichero de estado junto a la spec, ''repair.md'', con una línea ''- [x]'' / ''- [ ]'' por test; si se interrumpe, al relanzarlo sigue por donde iba. 
 + 
 +===== La revisión: /code review ===== 
 + 
 +Sin pull request nadie mira el código antes de que llegue a ''develop''. Lo mira la IA: 
 + 
 +<code> 
 +/code review 
 +</code> 
 + 
 +Una sola revisión que mira dos cosas, el código y los tests, y que **no toca nada y no bloquea**: deja cada hallazgo como una tarea ''- [ ]'' en ''review.md'', junto a la spec. Después, el alumno lee, decide, y las correcciones las hace ''/code impl review.md'' (abajo). Se puede relanzar las veces que haga falta: marca como resueltos los hallazgos que ya no aparecen y añade los nuevos. 
 + 
 +==== El código: contra la spec y las reglas ==== 
 + 
 +Compara el diff de la rama contra ''develop'' con tres cosas: 
 + 
 +  * **La spec del issue**: ¿hace lo que se pidió, y como se pidió? ¿Falta algún criterio de aceptación? ¿Ha hecho cosas que no estaban en la spec? 
 +  * **Las convenciones** (''convenciones-backend'', ''convenciones-frontend'', que remiten al steering): ¿está en las capas correctas, con los nombres correctos, con migración y datos de prueba, con ''data-testid''? 
 +  * **Las reglas de calidad** de ''calidad-codigo'' (abajo): ¿es código bueno, además de correcto? 
 + 
 +Cada hallazgo lleva la **regla** incumplida, el **sitio** (''fichero:línea'') y el **coste** del código tal como está (qué se duplica, qué no se puede probar, qué se rompe al cambiarlo). **Sin coste no hay hallazgo**: eso separa un defecto de una preferencia. Antes de proponer cambiar la **forma** de algo sin cambiar lo que hace (extraer, mover, renombrar), mira cómo lo resuelven tres clases hermanas; si lo hacen igual, es una convención del proyecto y no se reporta. Y clasifica en **grave** (no cumple la spec, rompe una convención, falta un test, o una regla con coste claro) y **mejorable**. 
 + 
 +Un hallazgo bien hecho y dos mal hechos: 
 + 
 +<code> 
 +GRAVE  PedidoService.java:48  metodos.md «cálculo puro y efectos secundarios» 
 +       calcularTotal() lee los pedidos de la base de datos y los suma en el mismo método. 
 +       Coste: no se puede probar la suma sin base de datos; el test unitario actual la monta entera. 
 + 
 +MAL    "extraer las líneas 20-24 a un método privado para mejorar la legibilidad" 
 +       (no mira las clases hermanas: todos los servicios lo escriben así; y no dice qué cuesta) 
 +MAL    "el método es demasiado largo" 
 +       (sin regla ni coste: es una opinión) 
 +</code> 
 + 
 +Los graves se corrigen. Los mejorables los decide el alumno: o se dejan abiertos para que se corrijan con los graves, o se cierran a mano con un «no se hace, es así a propósito». Un hallazgo cerrado así no bloquea nada. 
 + 
 +<note important>El alumno lee la revisión. El código lo ha escrito la IA, pero el commit lo firma él y es responsable de lo que hay en ''develop''. La revisión es una ayuda para leer, no una excusa para no leer.</note> 
 + 
 +==== calidad-codigo: las reglas ==== 
 + 
 +''review'' sabe si el código es **bueno** porque carga una skill de **conocimiento** con las reglas de calidad: métodos que hacen tres cosas, clases que se conocen demasiado, comentarios que repiten el código, tests que copian los valores que prueban. Se escribe una vez y se va completando cuando una revisión saca algo que no estaba. ''SKILL.md'' lleva la máxima y el índice; cada grupo de reglas, en su fichero: 
 + 
 +<code> 
 +.claude/skills/calidad-codigo/ 
 +├── SKILL.md          <- la máxima, el orden de prioridades y la tabla de ficheros 
 +├── metodos.md 
 +├── clases.md 
 +├── comentarios.md 
 +└── tests.md 
 +</code> 
 + 
 +**La máxima**: el código se escribe para que **una persona lo entienda al leerlo** y para que **un agente lo pueda modificar sin equivocarse**. Consecuencia que lo cambia todo: una repetición pequeña y visible es aceptable; una indirección para ahorrar dos líneas (un método que solo reenvía, un genérico) no lo es, porque el agente no olvida los dos sitios que hay que tocar y la persona sí pierde el hilo. 
 + 
 +Cuando dos reglas chocan, gana la primera de esta lista: mantenibilidad, testabilidad, determinismo, separación de responsabilidades. 
 + 
 +^ Fichero ^ Reglas (las que entran; se amplía con lo que salga en las revisiones) ^ 
 +| ''metodos.md'' | El método público cuenta la historia entera y se lee de arriba abajo. Se trocea por **cosa** que hace, no por fase. Con pocos casos (hasta 4), un método lineal por caso en vez de un genérico. El nombre dice qué hace, no cómo. Cabe en una pantalla y tiene como mucho tres parámetros. El cálculo puro se separa de la entrada/salida (base de datos, HTTP) para poder probarlo sin montar nada | 
 +| ''clases.md'' | Una clase, una responsabilidad. Composición antes que herencia. Un DTO o record agrupa solo lo homogéneo y sus campos se nombran por lo que son, no por quién los usa. Nada estático con estado. La interfaz del ''Repository'' en ''domain'' dice lo que el dominio necesita, no lo que la base de datos ofrece | 
 +| ''comentarios.md'' | El código se explica solo: si hace falta un comentario para entender qué hace, el nombre está mal. El único comentario que se escribe es el **porqué** que leer el código no revela (una decisión, una restricción externa). Nada de comentarios que repiten la línea de debajo ni de código comentado | 
 +| ''tests.md'' | Un test por comportamiento, con el caso en el nombre. El test **no copia los valores del código que prueba** (si el IVA es una constante, el test la lee de producción y comprueba la relación, no escribe 21 otra vez). Sin lógica en el test: ni ''if'' ni bucles. Lo que se prepara se ve en el propio test | 
 + 
 +Y en ''SKILL.md'', cuatro olores de **diseño** que vienen antes del código y que el agente tiene que buscar aunque no haya regla concreta: una decisión que se toma en dos sitios; un método que vive en una clase que no es la dueña del concepto; un ''if'' que no cubre todos los casos; un retorno defensivo (''return null'', lista vacía) que tapa un error en vez de fallar. 
 + 
 +La ''description'' de la skill dice cuándo cargarla: «Reglas de calidad del código del proyecto. Cargar al escribir o revisar cualquier clase Java o TypeScript, y siempre desde ''/code review''». 
 + 
 +==== Los tests: contra los criterios ==== 
 + 
 +La misma revisión mira después los tests del issue: que **cada criterio de aceptación** de ''requirements.md'' tiene su test E2E y cada caso de error su test de API; que no hay tests que no comprueban nada (sin aserciones, o con aserciones que siempre pasan); que cumplen ''tests.md'' de ''calidad-codigo'' (no copian los valores del código, sin lógica dentro). Lo que falta es un hallazgo grave más en ''review.md'' («falta el test E2E del criterio 3»). 
 + 
 +==== Las correcciones: /code impl <plan> ==== 
 + 
 +<code> 
 +/code impl .kiro/specs/12-alta-clientes/review.md 
 +</code> 
 + 
 +El mismo ''/code impl'' del tema 5: ''review.md'' es una lista de tareas como ''plan_<algo>.md'', así que lo hace igual, una detrás de otra, marcándolas, con los tests unitarios y de arquitectura después de cada una y parándose si uno falla por el código. 
 + 
 +===== Lo que comprueba /git-flow finish ===== 
 + 
 +Con los tests y la revisión, ''finish'' deja de ser solo git. Antes de fusionar comprueba, y si algo falla lo dice y **no hace nada**: 
 + 
 +  - ''tasks.md'' o ''plan_<algo>.md'' sin tareas pendientes. 
 +  - ''review.md'' sin hallazgos abiertos (los graves corregidos; los mejorables, corregidos o cerrados por el alumno). 
 +  - Los cuatro tipos de tests en verde: ''finish'' ejecuta por dentro los comandos de ''/test run'', uno a uno, y se para en el primero que falla.
  
-Con ''--log-failed'' el agente recibe solo lo que importa, no el log entero (tema 4: no pegarle logs enteros).+Si está todo, hace lo del tema 3: ''update'', ''--squash'' en ''develop'' con ''Closes #N'', push, ''./app.sh stop -v'' y borrar el worktree. Es la regla del tema 1: ningún comando espera al alumno; los que generan trabajo lo dejan en ficheros, y el que hace algo irreversible solo comprueba que esos ficheros están como tienen que estar.
  
 ===== Ejercicios ===== ===== Ejercicios =====
  
 ==== Ejercicio 1 ==== ==== Ejercicio 1 ====
-  * Crea un issue «CI» e inícialo. +  * Crea un issue «Skill /test: create» e inícialo. 
-  * Escribe ''manage.sh'' con ''deploy'', ''status'' y ''logs'' y dale permisos de ejecución. +  * Instala Playwright en ''frontend/'' (''npm init playwright@latest'') con los proyectos ''api'' y ''e2e'' y los scripts ''test:api'' y ''test:e2e'' del tema 4. 
-  * Añade el secreto ''DB_PASSWORD'' en //Settings → Secrets and variables → Actions//. +  * Escribe la skill ''/test'' con los cuatro sustantivos y el verbo ''create'': ''arch'' (reglas en castellano → tests ArchUnit en ''backend/src/test'' acabados en ''ArchTest'', con ''@DisplayName'' y comentario), ''unit'' (sin argumento, todas las clases sin tests; o una clase o paquete → un test JUnit 5 por comportamiento, con Mockito y sin Spring), ''api'' (escenarios → ''tests/api/<entidad>.spec.ts'' con un test por escenario) y ''e2e'' (escenarios, normalmente los criterios de ''requirements.md'' → un ''.spec.ts'' por criterio, usando el MCP de Playwright). 
-  * 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.+  * ''/test arch create'' con las seis reglas del tema. Mueve a mano el servicio del CRUD al paquete ''controller'' y comprueba que ''mvn test'' falla con el mensaje del test. Deshazlo. 
 +  * ''/test unit create'' con el servicio del CRUD del tema 5, ''/test api create'' con los escenarios de su entidad y ''/test e2e create'' con los criterios de la spec. Comprueba que ''mvn test'' no ejecuta los de Playwright y que ''npm run test:api'' y ''npm run test:e2e'' pasan dos veces seguidas. 
 +  * Finaliza el issue.
  
 ==== Ejercicio 2 ==== ==== Ejercicio 2 ====
-  * Pide al profesor que registre tu runner en el servidor. Comprueba en //Settings → Actions → Runners// que aparece como //Idle//. +  * Crea un issue «Skill /test: run y repair» e inícialo. 
-  * 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. +  * Añade el verbo ''run'' con la tabla de comandos del tema: en rojo, explica qué test, qué esperaba y qué ha pasado. 
-  * Finaliza el issue y ''/git-flow publicar''. Sigue la ejecución en //Actions// y comprueba que la aplicación responde en ''%%http://<alumno>.proyectosdaw.cip.fpmislata.com%%''.+  * Introduce un error a mano en una validación del servicio, reconstruye el backend y lanza ''/test unit run'' y ''/test api run'': tiene que caer al menos un unitario y uno de API, y la explicación tiene que señalar la validación. Deshazlo. 
 +  * Añade el verbo ''repair'' con el criterio de la intención, las tres reglas y el fichero ''repair.md''. 
 +  * Cambia a propósito el texto de un mensaje de error del formulario y lanza ''/test e2e repair'': tiene que actualizar el test y decir que era un cambio intencionado. Después rompe una validación del servicio sin tocar ningún test y lanza ''/test api repair'': tiene que arreglar el código y dejar el test como estaba. 
 +  * Finaliza el issue.
  
 ==== Ejercicio 3 ==== ==== Ejercicio 3 ====
-  * Añade ''status.yml'' y ''logs.yml'' con ''workflow_dispatch'' sobre ''self-hosted''. +  * Crea un issue «Skill /code» e inícialo. 
-  * Lánzalos desde //Actions// y lee la salida de ''manage.sh status'' en el log.+  * Escribe la skill de conocimiento ''calidad-codigo'' con los cuatro ficheros de la tabla y los olores de diseño en ''SKILL.md''. Pide al agente un primer borrador a partir de la tabla y corrígelo: cada regla con una frase de ejemplo de código que la cumple y otra que no. 
 +  * Añade a la skill ''/code'' el verbo ''review'', que revisa primero el código y luego los tests: solo lectura más escribir ''review.md'', el formato de hallazgo del ejemplo y la regla de las clases hermanas. 
 +  * ''/code review'' sobre el CRUD del tema 5. Lee ''review.md'': para cada hallazgo, decide si es un defecto o una preferencia y por qué. Cierra a mano uno mejorable. 
 +  * ''/code impl'' con ''review.md'' y vuelve a pasar ''/code review'': no deben salir los graves. 
 +  * Finaliza el issue.
  
 ==== Ejercicio 4 ==== ==== Ejercicio 4 ====
-  * Escribe la skill ''/ci-revisar'': ''gh run watch'' de la última ejecución y, si falla, ''gh run view --log-failed'', diagnóstico y propuesta de arreglo. ''allowed-tools'' solo con ''gh run''. +  * Crea un issue «finish comprueba» e inícialo. 
-  * Rompe un test E2E a propósito, finaliza el issue y lanza ''/ci-revisar''. Tiene que decirte qué test ha fallado y por qué. Arregla el test y vuelve a finalizar. +  * Amplía ''/git-flow finish'' con las tres comprobaciones del tema (las tareas, en ''tasks.md'' o en ''plan_<algo>.md'', según el issue). Si alguna falla, tiene que decir cuál y no tocar nada. 
-  * 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.+  * Deja una tarea sin marcar en ''tasks.md'' y lanza ''finish'': se tiene que parar. Márcala, deja un hallazgo grave abierto en ''review.md'' y vuelve a lanzar: se tiene que parar. Ciérralo y finaliza.
  
-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).+==== Ejercicio 5 ==== 
 +  * Crea un issue para la segunda entidad de tu proyecto e inícialo. Es el primer issue que se hace con el arnés entero. 
 +  * ''/sdd spec create''. En ''design.md'' compáralo con el CRUD del tema 5: cada diferencia es una línea que falta en el steering. Corrígela y vuelve a generar hasta que salga igual. 
 +  * ''/clear'', ''/sdd spec impl'', ''/test unit create'', ''/test api create'' y ''/test e2e create''. Los cuatro tipos en verde, uno a uno. 
 +  * ''/code review''. Quita a mano de ''requirements.md'' un caso de error sin quitar su código y vuelve a pasarla: tiene que marcarlo como grave. Restaura el fichero y ''/code impl'' con ''review.md''. 
 +  * ''/git-flow commit'' y ''/git-flow finish''.
  
clase/daw/daw-proyecto/tema06.1791931187.txt.gz · Última modificación: por claude