Ir al contenido

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:

  1. 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.
  2. Configurar el repo del grupo.
  3. Integrar el back.
  4. Integrar el front.

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.

  • 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.
  1. Descarga las dos listas de chequeo: la del back (Markdown) y la del front (Markdown).
  2. 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.
  3. 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.
  4. El propietario hace las correcciones, en su repo individual. El revisor no toca su código.
  5. Cuando termina, el propietario completa el cierre de la lista (ver más abajo).

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

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:

  1. 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 GET y un POST por cada una de las 3 entidades). Si todavía no lo has hecho, sigue el tutorial de Newman.
  2. Volver a arrancar el back y el front (./mvnw spring-boot:run y ng serve) y comprobar que todo funciona con las 3 entidades.
  3. Completar el cierre al final de cada lista en la wiki.

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.

  1. Crear el repo del grupo en GitHub: un solo repo con dos carpetas en la raíz, backend/ y frontend/, 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).
  2. Proteger la rama main: nadie puede hacer git push directo, todo entra por PR.
  3. 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 prueba frontend/, analiza ambos con SonarQube y corre las Collections de backend/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.
  4. Verificar que todos los integrantes tienen acceso de escritura al repo del grupo.
  5. 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.ts del 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á. El environment.development.ts y el environment de Postman siguen apuntando a localhost.
  6. Cada integrante hace git clone del 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.

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.

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:

Ventana de terminal
git checkout main
git pull
git checkout -b integracion/artistas-back

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á en backend/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).

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:

  1. ./mvnw spring-boot:run despliega sin errores.
  2. Tus Collections pasan en verde con Newman.

Si algo falla, corrígelo aquí. No hagas commit de algo que no funciona.

Ventana de terminal
git status
git add .
git commit -m "Integración módulo artistas (back)"
git push -u origin integracion/artistas-back

git 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.

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.

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.


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.

Ventana de terminal
git checkout main
git pull
git checkout -b integracion/artistas-front

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/ y src/app/<entidad>-create/.
  • Los modelos y los servicios: src/app/<entidad>.model.ts y src/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).

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:

Ventana de terminal
git status
git add .
git commit -m "Integración módulo artistas (front)"
git push -u origin integracion/artistas-front

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.


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:

Ventana de terminal
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.


  • 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:
Ventana de terminal
git fetch origin
git 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, el backend/pom.xml y la clase anotada @SpringBootApplication los 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.


Back:

  • Los módulos de todos los integrantes en la carpeta backend/ del repo grupal, cada uno en su paquete co.edu.uniandes.<nombreproyecto>.<nombremodulo>.
  • main verde: el pipeline de Jenkins corre build + Newman y pasa.
  • Mínimo 6 requests de Newman por módulo (un GET y un POST por entidad).
  • Un único backend/collections/environment.postman_environment.json en el repo grupal, con baseUrl apuntando a http://localhost:8080.

Front:

  • Los módulos de todos los integrantes en la carpeta frontend/ del repo grupal.
  • main verde: 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 environment apuntan a la VM del grupo (producción) y a localhost (desarrollo).

Del equipo:

  • Un único repo grupal con dos carpetas en la raíz: backend/ y frontend/.
  • Jenkinsfile versionado en la raíz del repo.
  • main protegido: 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.