Files
localesp/docs/07-cicd.md
T
edgar.friendly 27166eb3f4
deploy-branch / deploy (push) Failing after 1m38s
deploy-branch / teardown (push) Skipped
ci: despliegue por rama en <rama>.localesp.es (Gitea Actions + host runner)
2026-07-24 08:54:52 +02:00

4.3 KiB

CI/CD — despliegue por rama

Cada rama se despliega automáticamente en https://<rama>.localesp.es.

Cómo funciona

push a rama X
   │  Gitea Actions  (workflow: .gitea/workflows/deploy.yml)
   ▼
runner self-hosted (host executor, en el propio VPS)
   │  npm ci  →  vite build  →  scripts/deploy.sh <rama>
   ▼
/opt/localesp-<slug>/            código + dist/ + node_modules (prod)
systemd  localesp-<slug>.service node server/index.js  (PORT=80xx)
nginx    <slug>.localesp.es      proxy_pass → localhost:80xx
certbot  *.localesp.es           Let's Encrypt (si el DNS ya apunta)

El slug se deriva del nombre de rama (Feature/Foofeature-foo), válido como hostname DNS. Un entorno = un directorio, un servicio, un vhost y un puerto. La base de datos localesp.db de cada entorno se conserva entre despliegues (no se sobreescribe).

Puertos: 8080/8081 son entornos legacy (localesp.service, localesp-master.service); los nuevos empiezan en 8082. Si la rama ya tiene su localesp-<slug>.service, se reutiliza su puerto (adopta el entorno existente).

Precondición manual: el registro DNS

El registro A de <rama>.localesp.es se crea a mano (no está automatizado).

  1. En el proveedor DNS de localesp.es, añade un registro A: <rama>.localesp.es A <IP-pública-del-VPS>
  2. Espera a que propague (dig +short <rama>.localesp.es).
  3. Lanza el workflow (push a la rama, o Actions → Run workflow en Gitea).

Mientras el DNS no apunte al VPS, deploy.sh despliega la app igualmente y la sirve por HTTP; emite el cert Let's Encrypt en cuanto detecta que el DNS ya resuelve. No hay que tocar nada más.

Añadir una rama nueva

git checkout -b mi-feature
# ... cambios ...
git push -u origin mi-feature

El workflow corre solo. Si quieres URL pública: crea el registro A (arriba). Si no, el entorno existe pero no es alcanzable por hostname (útil para tests internos si añades el host a /etc/hosts).

Borrar una rama

Al borrar la rama en Gitea, el job teardown limpia el entorno (unit systemd, vhost, cert y /opt/localesp-<slug>). También manual:

ssh localesp.jumpingcrab.com 'bash /opt/localesp-master/scripts/teardown.sh mi-feature'

Notas sobre los entornos existentes (migración)

Al primer despliegue vía CI de cada rama legacy:

  • master/opt/localesp-master, reutiliza el puerto 8081 y el vhost existente (master.localesp.es y el apex localesp.es, que proxyan a 8081). Transparente, no hay corte.
  • prototipo-yb01 → pasa a un entorno dedicado /opt/localesp-prototipo-yb01 en un puerto nuevo (8082) y el vhost prototipo.conf se repunta a ese puerto. El antiguo /opt/localesp + localesp.service (8080) queda huérfano; puedes retirarlo con systemctl disable --now localesp.service cuando confirmes que el nuevo funciona.

Seguridad

El runner (gitea-runner) se ejecuta como root en el VPS de producción y en modo host (sin contenedor): cualquier workflow que se ejecute corresponde a código del repo corriendo con privilegios de root en la caja. Esto es aceptable mientras el repo sea propio / de baja colaboración. Si entran colaboradores externos, conviene migrar a:

  • runner en contenedor + despliegue por SSH (clave como secret de Gitea), o
  • ephemeral runners (gitea-runner register --ephemeral).

Evolución: estrategia B (wildcard)

Para eliminar la precondición manual del DNS y el cert por rama, más adelante:

  1. Registro wildcard *.localesp.es (DNS).
  2. Wildcard cert *.localesp.es vía challenge DNS-01 (una sola vez).
  3. Un único vhost *.localesp.es que enruta por Host con un map rama→puerto.

deploy.sh apenas cambia: se caen los pasos de creación de vhost y certbot. Nada de lo hecho aquí se pierde.

Infra del runner (referencia)

Instalado en el VPS (localesp.jumpingcrab.com):

  • Binario: /usr/local/bin/gitea-runner (v2.2.0), host executor.
  • Config: /etc/gitea-runner/config.yaml — etiquetas self-hosted:host, linux:host.
  • Registro: /var/lib/gitea-runner/.runner (instance-level, https://git.localesp.es).
  • Servicio: gitea-runner.service (systemd, User=root, WorkingDirectory=/var/lib/gitea-runner).

Comprobar estado: systemctl status gitea-runner · journalctl -u gitea-runner -f. Ver runners en Gitea: Site administration → Actions → Runners.