Herramientas de usuario

Herramientas del sitio


clase:daw:daw-proyecto:tema06

¡Esta es una revisión vieja del documento!


6. Despliegue en el proyecto

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.

Lo que ya sabéis: qué es GitHub Actions y un primer workflow con VPN y SSH, en Despliegue 5; cómo funciona nginx-proxy con VIRTUAL_HOST, en Despliegue 4.c. Lo nuevo aquí es sustituir la VPN y el SSH por un runner dentro del servidor.

El servidor

Un VPS compartido por toda la clase, con tres cosas montadas por el profesor:

  • 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 3.
  • 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.
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.

manage.sh

Una única entrada para operar la aplicación en el servidor, en el repositorio:

#!/bin/bash
set -e
cd "$(dirname "$0")"
compose="docker compose -f compose.yaml"

case "$1" in
  deploy) $compose down; $compose build; $compose up -d ;;
  status) $compose ps ;;
  logs)   $compose logs --tail=200 ;;
  *) echo "uso: $0 deploy|status|logs"; exit 1 ;;
esac

  • -f compose.yaml: solo producción, sin el override de desarrollo.
  • 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

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 workflows

Un solo fichero para CI y CD:

name: CI/CD

on:
  push:
    branches: [develop, main]
  workflow_dispatch:

jobs:
  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
        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
        env: { DB_PORT: 3306, DB_PASSWORD: ci }
        run: mvn -B test

      - name: Tests E2E
        working-directory: frontend
        run: |
          npm ci
          npx playwright install --with-deps chromium
          npx playwright test

  deploy:
    needs: ci
    if: github.ref == 'refs/heads/main'
    runs-on: self-hosted
    steps:
      - 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

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 exactamente igual que en el worktree. –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 manage.sh deploy: 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 ./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.

La IA y los workflows

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:

gh run list --limit 5
gh run watch                       # sigue la última ejecución
gh run view <id> --log-failed      # solo los pasos que han fallado

Con –log-failed el agente recibe solo lo que importa, no el log entero (tema 4: no pegarle logs enteros).

Ejercicios

Ejercicio 1

  • Crea un issue «CI» e inícialo.
  • Escribe manage.sh con deploy, status y logs y dale permisos de ejecución.
  • 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 publicar. 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 manage.sh status en el log. ==== 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. * 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. * 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/tema06.1791929215.txt.gz · Última modificación: por claude