← Poner el backend en producción

Sesión 7

El CI del repositorio de Servidor

Antes de empezar. La API de Servidor ya tiene DTO, validaciones y respuestas de error. Hoy le montas la compilación y las pruebas automáticas, con el Maven Wrapper que ya trae el proyecto.

Antes de empezar · sin apuntes

  1. La API se ejecuta en el entorno local. ¿Qué condiciones serían necesarias para que la consumiera una persona ajena al aula?
  2. El pipeline del portfolio comprueba HTML, enlaces, formato y accesibilidad. ¿Qué tendría que comprobar el de una API?
  3. ¿Qué directorios de un proyecto Java no deben incorporarse nunca a un repositorio de código, y por qué?

Se explica

25 minutos · explicación y demostración

Reutilizar el repositorio desde el primer día

El backend ya está en GitHub desde Servidor 1. Conservamos ese repositorio, sus ramas y su historial; no se copia a otro para Intermodular. El portfolio puede tener su propio repositorio de presentación. Si el cliente del producto vive dentro del backend, también se conserva esa estructura: un monorepo puede configurar rutas de trabajo por job.

Qué hace el CI de Java

Maven lee pom.xml, compila el código, ejecuta las pruebas y construye el JAR. GitHub Actions repetirá ese proceso en un runner limpio. El wrapper fija Maven, pero para reproducir la construcción también deben coincidir Java, dependencias y configuración.

Un artefacto es el resultado construido, en este caso el JAR. No se guarda en Git: el workflow lo genera y lo entrega al despliegue. Las pruebas se implementan en Servidor; aquí se comprueba que el proceso las ejecuta y que su fallo bloquea la fusión.

Antes de publicar

Primero se reproduce verify en local y después en CI. Un fallo local se registra y se corrige sobre la misma rama del producto. Un fallo del runner puede deberse a Java, permisos del wrapper o configuración; los logs permiten distinguirlo de un defecto de implementación.

Se trabaja

140 minutos · trabajo guiado sobre el producto compartido

Bloque A · El repositorio de la API

  1. Abre la carpeta del backend de Servidor. Ejecuta git remote -v, git status y git log -5 --oneline; comprueba que es el repositorio utilizado desde la sesión 1, con su historial. No ejecutes git init ni crees otro remoto.
  2. En main actualizada, crea una rama para la issue del CI. Ejecuta .\mvnw.cmd -B verify en PowerShell (./mvnw -B verify en Linux/macOS). Si falla, guarda el mensaje causal y corrige la configuración o enlaza la issue técnica; conserva el trabajo útil de la sesión.
  3. Abre pom.xml y anota Java 21, la versión del proyecto y la presencia del wrapper. Revisa que target y credenciales no se rastrean. git status permite ver qué subirás; el historial de Servidor se conserva completo.
  4. Comprueba las reglas configuradas en Intermodular 2 también en el backend. Si aún falta el check de Java, se añadirá después de su primera ejecución. La política de revisión debe ser la misma en ambos módulos.
  5. Continúa con el workflow del bloque B. El código que compilamos es el CRUD con DTO y errores disponible después de Servidor 12.

Bloque B · El CI que compila

Trabajo individual, por el flujo establecido: issue, rama, pull request

Crea el archivo .github/workflows/ci.yml:

name: CI

on:
  pull_request:
  push:
    branches: [main]

jobs:
  build:
    name: Compilar y probar
    runs-on: ubuntu-latest
    steps:
      - name: Descargar el repositorio
        uses: actions/checkout@v4

      - name: Preparar Java
        uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: "21"
          cache: maven

      - name: Compilar y ejecutar los tests
        run: bash ./mvnw -B verify
distribution y java-version
Debe declararse la versión registrada en el paso 2, no el valor 21 del ejemplo. El runner no aprovisiona ningún JDK por defecto: la distribución y la versión se declaran de forma explícita. Si el valor declarado no coincide con el que especifica el pom.xml, la compilación falla con un mensaje que no menciona ninguna de las dos versiones.
cache: maven
Conserva entre ejecuciones el repositorio local de dependencias. Sin esta directiva, cada pull request vuelve a descargar el árbol completo de dependencias, con el consiguiente incremento de la duración del job.
./mvnw
El Maven Wrapper incluido en el proyecto. Utiliza la versión de Maven declarada por el propio proyecto y no la instalada en la máquina anfitriona, lo que garantiza una construcción equivalente en el runner y en cualquier entorno local.
-B
Modo por lotes (batch): suprime el coloreado y los indicadores de progreso, que en un registro no interactivo generan ruido y dificultan el diagnóstico.
verify
Fase del ciclo de vida de Maven que compila el código, ejecuta las pruebas y construye el artefacto empaquetado. El fallo de cualquiera de las tres etapas determina el fallo del job.
Si el job falla con «permission denied» al ejecutar ./mvnw

Es la incidencia más frecuente de esta sesión y no guarda relación con el código de la aplicación. El runner ejecuta Linux, donde un archivo requiere el bit de permiso de ejecución; el sistema de archivos de Windows no conserva ese atributo, de modo que el wrapper se incorporó al repositorio sin él. Se corrige registrando el permiso en el índice de Git y publicando el cambio:

git update-index --chmod=+x mvnw, después commit y push.

Conviene retener la causa: es la primera manifestación práctica de que el entorno de construcción no coincide con el entorno de desarrollo, diferencia que reaparecerá en otros contextos.

Si el proyecto no incorpora mvnw

Utiliza mvn -B verify, sin el prefijo ./: los runners incorporan Maven preinstalado. La construcción se completa, pero la solución es inferior, dado que la versión de la herramienta la determina la máquina y no el proyecto. Restaura los archivos del wrapper desde el historial o desde la plantilla de Servidor, conservando el código y el repositorio actuales.

Provocación controlada de fallos. Introduce las dos alteraciones siguientes en una rama de diagnóstico, sin fusionarlas, y restaura su estado antes de aprobar la pull request:

Alteración introducida Propiedad que demuestra
Supresión de un punto y coma en una clase El pipeline impide la integración de código que no compila
Inversión temporal de una aserción de prueba El pipeline impide la integración de código que compila pero incumple su especificación

El segundo caso constituye la diferencia sustancial entre este pipeline y el del portfolio: la validación no se limita a la corrección sintáctica del artefacto, sino que verifica su comportamiento.

Bloque C · Comprobación obligatoria y primer recorrido del flujo

Trabajo individual

  1. Fusiona la pull request que incorpora el CI.
  2. Accede a Settings → Rules → Rulesets → main protegida → Edit → Require status checks e incorpora Compilar y probar.
  3. Abre tres issues correspondientes a los siguientes incrementos previstos de la API y recorre al menos una de forma completa por el flujo de integración.

Lista de verificación de la sesión 7

  • El repositorio de la API existe, es público y no contiene la carpeta de construcción.
  • Cada pull request muestra el check «Compilar y probar».
  • La comprobación es obligatoria y se ha verificado una pull request bloqueada por una prueba fallida.
  • Una issue de la API recorrida entera.

Cierre

15 minutos · comprobación del resultado

Antes de cerrar · sin mirar

  1. ¿Por qué el directorio de construcción no se incorpora al repositorio?
  2. ¿Qué hace verify que no haría solo compilar?
  3. ¿Para qué sirve cache: maven?
  4. ¿Por qué el wrapper produce una construcción equivalente en el runner y en el entorno local?
Ver respuestas

1 · Porque se regenera con un comando, pesa, cambia entera en cada compilación y provoca conflictos. Al repositorio va lo que escribe una persona.

2 · Ejecuta los tests y construye el artefacto, además de compilar.

3 · Para reutilizar las dependencias ya descargadas y no bajarlas en cada ejecución.

4 · Porque fija la versión de Maven en el propio proyecto, en lugar de usar la que tenga instalada cada máquina.

Antes de la sesión 8

  • La API se ejecuta en el entorno local y responde a una petición efectuada desde el navegador.
  • Es posible identificar el puerto en el que escucha —el proceso lo indica al arrancar— y la ruta que devuelve la colección de datos.
  • El check de compilación está en verde en main.