Release 5: Integración inicial
Objetivo: fusionar los módulos de todos los integrantes en un solo repositorio de grupo, con PRs (Pull Requests: solicitudes para que otro integrante revise y apruebe tus cambios antes de que entren a main) que pasan CI (Integración Continua: un pipeline automático en Jenkins que compila el proyecto y corre las pruebas en cada PR) en verde. Sin funcionalidad nueva: el módulo de cada quien debe comportarse exactamente igual que antes, ahora en el repo compartido.
Hoy cada integrante tiene su propio repo con su front y su back. La integración consiste en crear el repo del grupo, un único repo con dos carpetas, backend/ y frontend/: cada quien crea su rama, verifica, hace commit y push, y abre un PR que otro integrante revisa y aprueba. Si la estructura, los nombres o las pruebas de un módulo no están bien desde el principio, esos problemas llegan al repo del grupo y se multiplican por cada integrante. Por eso el primer paso es revisar, no integrar.
Los pasos, en orden:
- Revisión individual y cruzada de cada módulo en el repo individual, seguida de las correcciones y de las pruebas de tus Collections desde la terminal.
- Configurar el repo del grupo.
- Integrar el back.
- Integrar el front.
Paso 1: Revisión individual y cruzada
Sección titulada «Paso 1: Revisión individual y cruzada»Antes de crear cualquier rama, cada módulo se revisa en el repo individual de su propietario con la lista de chequeo de este paso. Hay dos listas, una para el back y otra para el front, y cada una repite las tablas de más abajo.
Quién revisa
Sección titulada «Quién revisa»- Revisión cruzada: un integrante del equipo sigue la lista de chequeo y revisa el módulo de otro. La asignación es del equipo, pero todos deben revisar y ser revisados (por ejemplo, A revisa a B, B revisa a C y C revisa a A).
- Si no es posible: si por alguna razón no se puede hacer la revisión cruzada, el propietario revisa su propio módulo con la misma lista.
- En cualquier caso, el propietario verifica de nuevo antes de crear su rama de integración (Paso 3). Esa segunda verificación es obligatoria, haya o no habido revisor.
Cómo se hace
Sección titulada «Cómo se hace»- Descarga las dos listas de chequeo: la del back (Markdown) y la del front (Markdown).
- Pega cada lista en una página nueva de la wiki del grupo, una por módulo y por tipo (por ejemplo, “Revisión R5 back: artistas”). Arriba se anotan el propietario, el nombre del módulo, sus tres entidades y, en una tabla aparte, el revisor.
- El revisor abre el repo individual del propietario, corre el módulo en su máquina y recorre las tablas. En cada fila escribe en la columna Comentario si cumple o, si no cumple, qué entidad y qué archivo fallan. Con un “todo bien” el propietario no sabe qué corregir.
- El propietario hace las correcciones, en su repo individual. El revisor no toca su código.
- Cuando termina, el propietario completa el cierre de la lista (ver más abajo).
Qué se revisa: convenciones
Sección titulada «Qué se revisa: convenciones»Las tablas de esta página y las listas de la wiki tienen las mismas filas y casi las mismas columnas: Criterio (qué se revisa y cómo debe ser) y Ejemplo (cómo se ve en un módulo correcto). Las listas de la wiki agregan una tercera, Comentario, donde escribe el revisor. Cada criterio se aplica a las 3 entidades.
| Criterio | Ejemplo |
|---|---|
Paquete y carpeta. Las clases del módulo están en el paquete co.edu.uniandes.<nombreproyecto>.<nombremodulo>, con el nombreproyecto acordado en grupo (igual para todos). La carpeta coincide con el paquete. |
co.edu.uniandes.musical.artistas, en src/main/java/co/edu/uniandes/musical/artistas/ |
DTO. Un archivo por entidad, llamado <Entidad>DTO.java. |
ArtistaDTO.java, AlbumDTO.java, CancionDTO.java |
Controller. <Entidad>Controller.java, anotado @RestController. |
ArtistaController.java |
Endpoint de lectura. GET /<entidades>, en un método llamado findAll(). |
GET /artistas |
Endpoint de creación. POST /<entidades>, en un método crear<Entidad>(@RequestBody <Entidad>DTO). Responde 201, imprime el body en consola y no persiste. |
POST /artistas en crearArtista(...) |
Repository (contrato). Interfaz <Entidad>Repository.java. |
ArtistaRepository.java |
Repository (fake). InMemory<Entidad>Repository.java, anotado @Repository, que carga un JSON a objetos Java con ObjectMapper. |
InMemoryArtistaRepository.java |
Datos de ejemplo. El JSON que carga el repository fake está en src/main/resources/. |
src/main/resources/datos.json |
Colecciones Postman. Una por entidad, en la carpeta collections/, con el nombre <Entidad>.postman_collection.json. |
collections/Artista.postman_collection.json |
Environment de Postman. Un único archivo para todo el módulo (no uno por entidad), con la variable baseUrl (con U mayúscula: las Collections también usan {{baseUrl}}, y el pipeline la define con ese nombre exacto). |
collections/environment.postman_environment.json |
Valor de baseUrl. El Current value es la URL local, no la de una VM. |
http://localhost:8080 |
| Criterio | Ejemplo |
|---|---|
Estructura de las fuentes. Cada componente vive en su propia carpeta dentro de src/app/. |
src/app/artist-list/, src/app/artist-detail/, src/app/artist-create/ |
Modelo TS. <entidad>.model.ts en src/app/, con la interfaz <Entidad>. |
src/app/artista.model.ts, interface Artista |
Componente listar. Carpeta <nombre>-list/, clase <Nombre>ListComponent, selector app-<nombre>-list. |
artist-list/, ArtistListComponent, app-artist-list |
Componente detalle. Carpeta <nombre>-detail/, clase <Nombre>DetailComponent, selector app-<nombre>-detail. |
artist-detail/, ArtistDetailComponent, app-artist-detail |
Componente crear. Carpeta <nombre>-create/, clase <Nombre>CreateComponent, selector app-<nombre>-create, con formulario reactivo y httpClient.post. |
artist-create/, ArtistCreateComponent, app-artist-create |
Servicio. <entidad>.service.ts en src/app/, clase <Entidad>Service, @Injectable({ providedIn: 'root' }), con httpResource para lectura y el signal seleccionado. |
src/app/artista.service.ts, ArtistaService |
Environments. Carpeta src/environments/ con environment.ts (producción, apunta a la VM del grupo) y environment.development.ts (desarrollo, apunta a localhost). |
environment.ts con la URL de la VM, environment.development.ts con http://localhost:8080 |
Qué se prueba: validación funcional
Sección titulada «Qué se prueba: validación funcional»El revisor corre el módulo en su propia máquina, sin basarse en lo que el propietario dice que funciona.
| Criterio | Ejemplo |
|---|---|
El back despliega. ./mvnw spring-boot:run arranca sin errores. |
La consola termina con un mensaje Started ...Application |
| El front del propietario funciona con este back. Con el back corriendo, el front del propietario muestra lista, detalle y formulario de crear de las 3 entidades. | Abrir http://localhost:4200 y recorrer las 3 entidades |
| Criterio | Ejemplo |
|---|---|
El front arranca. ng serve arranca sin errores. |
La consola muestra Local: http://localhost:4200/ |
| El front funciona con el back del propietario. Con el back del propietario corriendo en local, la aplicación muestra lista, detalle y formulario de crear de las 3 entidades. | Recorrer las 3 entidades en http://localhost:4200 |
Después de las correcciones: Newman y verificación final
Sección titulada «Después de las correcciones: Newman y verificación final»Cuando el propietario termina las correcciones, hace esto antes de crear su rama:
- Correr sus Collections con Newman. Newman es la herramienta que ejecuta tus Collections de Postman desde la terminal, no solo desde la aplicación, y es lo que va a correr Jenkins en cada PR. Todas las requests deben pasar, con un mínimo de 6 (un
GETy unPOSTpor cada una de las 3 entidades). Si todavía no lo has hecho, sigue el tutorial de Newman. - Volver a arrancar el back y el front (
./mvnw spring-boot:runyng serve) y comprobar que todo funciona con las 3 entidades. - Completar el cierre al final de cada lista en la wiki.
Paso 2: Configurar el repo del grupo
Sección titulada «Paso 2: Configurar el repo del grupo»Un integrante designado por el equipo realiza esta tarea antes de que cualquiera empiece a integrar, y una vez que los módulos hayan pasado el Paso 1. Los demás no tocan el repo del grupo hasta que este paso esté completo.
- Crear el repo del grupo en GitHub: un solo repo con dos carpetas en la raíz,
backend/yfrontend/, que contienen respectivamente el proyecto Spring Boot y el proyecto Angular. Git no guarda carpetas vacías, así que las dos aparecen cuando entra el primer módulo, que lleva back y front en el mismo PR (ver el Paso 3). - Proteger la rama
main: nadie puede hacergit pushdirecto, todo entra por PR. - Agregar en la raíz del repo, antes de que entre el primer módulo, el Jenkinsfile que entrega el curso, sin modificarlo. En cada PR, el pipeline compila y prueba
backend/, compila y pruebafrontend/, analiza ambos con SonarQube y corre las Collections debackend/collections/con Newman. Cómo funciona cada parte, y qué espera de tu repo, está explicado en Integración continua. El repo arranca vacío con el pipeline ya configurado: así nadie hereda ventaja por ser la base. - Verificar que todos los integrantes tienen acceso de escritura al repo del grupo.
- Escoger la VM del grupo. Cada integrante tiene su propia VM, pero el repo del grupo despliega en una sola: el equipo elige cuál y anota su URL. Esa URL es la que va en
src/environments/environment.tsdel front (el de producción), así que quien copie el proyecto base del front la pone al integrar (Paso 4), y todos los demás la dejan como está. Elenvironment.development.tsy el environment de Postman siguen apuntando alocalhost. - Cada integrante hace
git clonedel repo del grupo en su máquina. En ese clon, abierto en VS Code, vas a hacer toda la integración (Pasos 3 y 4): no en tu repo individual.
Paso 3: Integrar el back
Sección titulada «Paso 3: Integrar el back»Antes de empezar, verifica de nuevo tu módulo (ver el Paso 1): tus correcciones están hechas y ./mvnw spring-boot:run y Newman siguen en verde.
Trabajas en el clon del repo del grupo, abierto en VS Code, y en este paso solo tocas la carpeta backend/. Tu repo individual no se modifica: de allí solo copias archivos. El orden es este: crear la rama, copiar tus archivos, verificar, hacer commit y subir la rama. Mientras copias y haces commit, todo ocurre solo en tu computador. Tus archivos llegan al repo del grupo únicamente con el git push del último paso.
Preparar la rama de integración
Sección titulada «Preparar la rama de integración»Desde la carpeta del clon del grupo, trae lo último de main (otros módulos pueden haberse integrado ya) y crea tu rama con el nombre de tu módulo:
git checkout maingit pullgit checkout -b integracion/artistas-backCopiar tus archivos
Sección titulada «Copiar tus archivos»Abre tu repo individual y copia cada archivo a la misma ruta pero dentro de la carpeta backend/ del clon del grupo, con el explorador de archivos o arrastrando en VS Code. Por ejemplo, src/main/java/... de tu repo va a backend/src/main/java/...:
- La carpeta de tu módulo:
src/main/java/co/edu/uniandes/<nombreproyecto>/<nombremodulo>/. - El JSON con tus datos de ejemplo, de
src/main/resources/. Si otro módulo ya trajo un archivo con el mismo nombre, renombra el tuyo con el nombre de tu módulo (por ejemplo,datos-artistas.json) y ajusta la ruta en tu repository fake. - Las 3 Collections:
collections/<Entidad>.postman_collection.json. collections/environment.postman_environment.json, solo si todavía no está enbackend/collections/. Es uno solo para todos.
Si eres el primero en la fila, el repo del grupo solo tiene el Jenkinsfile, así que además creas la carpeta backend/ y copias dentro los archivos base del proyecto: pom.xml, mvnw, la carpeta .mvn/, la clase anotada @SpringBootApplication y application.properties. Quienes vienen después no copian estos archivos encima: si tu módulo necesita algo nuevo en ellos, lo agregas a mano (ver Coordinación del equipo).
Verificar en el repo del grupo
Sección titulada «Verificar en el repo del grupo»La copia puede romper cosas que en tu repo individual funcionaban (un archivo que olvidaste, una ruta distinta). Antes de hacer commit, entra a la carpeta backend/ del clon del grupo (cd backend) y comprueba que:
./mvnw spring-boot:rundespliega sin errores.- Tus Collections pasan en verde con Newman.
Si algo falla, corrígelo aquí. No hagas commit de algo que no funciona.
Commit y push
Sección titulada «Commit y push»git statusgit add .git commit -m "Integración módulo artistas (back)"git push -u origin integracion/artistas-backgit status te muestra qué archivos vas a subir: revisa que sean los de tu módulo y nada más. Con el push, la rama aparece en el repo del grupo en GitHub.
Abrir el PR
Sección titulada «Abrir el PR»Abre el PR desde GitHub apuntando de integracion/artistas-back a main del repo del grupo. El título del PR debe identificar el módulo y el lado: “Integración módulo artistas (back)”.
Aquí se lanza el pipeline de Jenkins. Si el pipeline falla, el PR no se aprueba. El autor corrige en su rama y vuelve a hacer push; nadie más se ve afectado.
Revisión y merge
Sección titulada «Revisión y merge»El integrante designado como revisor aprueba o rechaza antes del plazo acordado por el equipo (por ejemplo, antes de la siguiente sesión de clase). Si aprueba, cierra el PR. Solo cuando el PR se cierra el código llega a main.
Paso 4: Integrar el front
Sección titulada «Paso 4: Integrar el front»Funciona igual que el back, en el mismo clon del repo del grupo, pero ahora solo tocas la carpeta frontend/. Antes de empezar, verifica de nuevo que ng serve arranca y que tu front funciona con las 3 entidades.
Preparar la rama de integración
Sección titulada «Preparar la rama de integración»git checkout maingit pullgit checkout -b integracion/artistas-frontCopiar tus archivos
Sección titulada «Copiar tus archivos»Desde tu repo individual, copia a la misma ruta pero dentro de la carpeta frontend/ del clon del grupo (por ejemplo, src/app/... va a frontend/src/app/...):
- Las carpetas de los componentes de tus 3 entidades:
src/app/<entidad>-list/,src/app/<entidad>-detail/ysrc/app/<entidad>-create/. - Los modelos y los servicios:
src/app/<entidad>.model.tsysrc/app/<entidad>.service.ts.
Si eres el primero en la fila, además creas la carpeta frontend/ y copias dentro el proyecto base (package.json, angular.json, src/main.ts, src/app/app.component.*, src/app/app.config.ts y src/environments/). En environment.ts cambia la URL por la de la VM del grupo (la que se escogió en el Paso 2), no la de tu VM individual. Quienes vienen después no copian esos archivos encima: agregan a mano lo que su módulo necesite en app.component.html y app.config.ts, cuando les toque el turno (ver Coordinación del equipo).
Verificar, commit y push
Sección titulada «Verificar, commit y push»Entra a la carpeta frontend/ del clon del grupo (cd frontend) y comprueba que ng serve arranca y que la aplicación muestra lista, detalle y formulario de crear de tus 3 entidades. Luego:
git statusgit add .git commit -m "Integración módulo artistas (front)"git push -u origin integracion/artistas-frontAbrir el PR y revisar
Sección titulada «Abrir el PR y revisar»Mismo proceso que el back, con el título “Integración módulo artistas (front)”. El revisor verifica que la aplicación sigue funcionando con las 3 entidades del módulo después del merge.
Si Jenkins falla
Sección titulada «Si Jenkins falla»En un PR (antes de mergear): el PR no se aprueba. El autor corrige en su rama y vuelve a hacer push. Nadie más se ve afectado.
En main (después de un merge): máxima prioridad del equipo: nadie sigue integrando encima de un build roto. Se revierte el merge de inmediato para devolver main a verde:
git revert -m 1 <sha-del-merge>La causa se investiga en una rama aparte. Solo se corrige directo en main, sin revertir, si el problema es obvio y la corrección es de una línea.
Coordinación del equipo
Sección titulada «Coordinación del equipo»- Los PRs se mergean uno a la vez, no en paralelo. Quien sigue en la fila actualiza su rama con lo que ya se mergeó antes de terminar su PR:
git fetch origingit merge origin/main# resolver conflictos si los hay, luego:git push origin <tu-rama-de-integracion>Si los integrantes trabajan en paralelo sobre el mismo punto de partida, cada PR después del primero llega con conflictos garantizados.
-
Archivos compartidos con dueño claro por turno:
frontend/src/app/app.component.html,frontend/src/app/app.config.ts, elbackend/pom.xmly la clase anotada@SpringBootApplicationlos toca solo quien tiene el PR activo en ese momento. El siguiente en la fila los edita después de que el PR anterior ya se mergeó, nunca antes. -
Revisión con plazo: un PR esperando revisión varios días rompe la integración continua tanto como no integrar. El equipo acuerda un plazo máximo de revisión desde el primer día.
-
Un PR con build rojo no se aprueba, sin excepciones.
Entregable R5
Sección titulada «Entregable R5»Back:
- Los módulos de todos los integrantes en la carpeta
backend/del repo grupal, cada uno en su paqueteco.edu.uniandes.<nombreproyecto>.<nombremodulo>. mainverde: el pipeline de Jenkins corre build + Newman y pasa.- Mínimo 6 requests de Newman por módulo (un
GETy unPOSTpor entidad). - Un único
backend/collections/environment.postman_environment.jsonen el repo grupal, conbaseUrlapuntando ahttp://localhost:8080.
Front:
- Los módulos de todos los integrantes en la carpeta
frontend/del repo grupal. mainverde: el pipeline corre el build de Angular y pasa.- La aplicación integrada muestra lista, detalle y formulario de crear para todas las entidades de todos los módulos.
- Los
environmentapuntan a la VM del grupo (producción) y alocalhost(desarrollo).
Del equipo:
- Un único repo grupal con dos carpetas en la raíz:
backend/yfrontend/. Jenkinsfileversionado en la raíz del repo.mainprotegido: ningún integrante puede hacer push directo.- Revisión del módulo de cada integrante registrada en la wiki del grupo, con sus hallazgos marcados como corregidos.
- Historial de PRs en GitHub que muestra la integración módulo por módulo.