Volver al blog
El bot de GitHub anunciando el preview listo con su URL y los cinco checks en verde, junto al árbol de ArgoCD con los recursos que ese pull request ha levantado

Un entorno entero por cada pull request, y que se borre solo

LaboratorioGitOpsKubernetesDevOps

Revisar un pull request leyendo el diff funciona para la lógica y no funciona para casi nada más. Si el cambio toca una migración, una plantilla de Helm o el comportamiento de una pantalla, aprobarlo es un acto de fe.

La alternativa es que cada pull request levante su propio entorno completo, y que se borre solo cuando se cierre.

Qué levanta exactamente

En el homelab, cuando un PR lleva la etiqueta de preview, el Pull Request Generator de ArgoCD lo detecta en menos de un minuto y crea el entorno entero.

RecursoQué recibe el PR
NamespaceEl suyo, con el número del PR
Base de datosPostgreSQL propio, vía CNPG
BúsquedaSu instancia de Typesense
SecretosLos suyos, desde Infisical
DominioUn subdominio propio
Todo con nombre propio: nada se comparte con staging.

Lo importante no es la lista, sino que no comparte nada con staging. Una migración destructiva en un preview rompe ese preview y nada más.

Las dos mitades se encuentran en el SHA

El montaje son dos piezas que no se hablan entre sí: GitHub Actions construye las imágenes y ArgoCD despliega los manifiestos. Nadie llama a nadie. Lo que las mantiene alineadas es que ambas usan el commit del pull request como identificador.

Del lado de GitHub, el workflow escucha los eventos del PR —abierto, actualizado, reabierto, etiquetado y cerrado— y solo actúa si lleva la etiqueta de preview. Construye los cuatro servicios en paralelo y etiqueta cada imagen con el número del PR y el SHA de su cabecera:

tags: ${{ env.REGISTRY }}/${{ matrix.image }}:pr-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}

La matriz corre sin cancelar hermanas cuando una falla. No es despiste: el almacenamiento del registro público devuelve errores de certificado intermitentes, y con la cancelación activada un fallo transitorio en un servicio tiraba la construcción de los otros tres.

Del lado de ArgoCD no hay ningún webhook. Un generador de pull requests pregunta a GitHub cada sesenta segundos por los PR que lleven esa etiqueta:

generators:
  - pullRequest:
      github:
        owner: Zetesis-Labs
        repo: ZetesisPortal
        labels:
          - preview
      requeueAfterSeconds: 60

Por cada PR que encuentra, materializa tres aplicaciones en dos oleadas. Y cada una apunta al commit exacto del pull request, no a su rama:

OleadaAplicaciónQué crea
0pr-secretsExternalSecrets desde Infisical
0pr-infraPostgreSQL con CNPG y Typesense
1pr-appEl chart de Helm con sus dominios y sus tags
Tres ApplicationSets, dos oleadas. La aplicación no arranca hasta que sus secretos y su base de datos existen.

El ApplicationSet de la aplicación es donde se cierra el círculo: sobrescribe los parámetros del chart con el mismo esquema que usó el workflow al etiquetar.

targetRevision: "{{ .head_sha }}"
- name: web.image.tag
  value: "pr-{{ .number }}-{{ .head_sha }}"
- name: web.domain
  value: "pr-{{ .number }}.staging.zetesis.xyz"

Manifiesto e imagen salen del mismo commit sin que ninguna de las dos partes conozca a la otra. Empujar otro commit al PR cambia el SHA, y con él cambian a la vez el tag que construye el workflow y la revisión que despliega ArgoCD.

Al cerrar el pull request se desmonta por los dos lados: ArgoCD borra las aplicaciones —y con ellas el namespace entero, con su base de datos y sus secretos— porque el generador deja de verlo, y un último trabajo del workflow borra de Harbor las imágenes de ese PR. Ni entornos huérfanos ni un registro creciendo con imágenes que nadie va a descargar nunca más.

Y con los datos de verdad

En Konect el preview arranca copiando los datos de staging. Esa diferencia cambia qué puedes probar: las migraciones se ejecutan contra el esquema real, con su volumen y sus casos raros, no contra una base vacía donde todo pasa.

Es donde aparecen las migraciones que tardan veinte minutos, o las que fallan porque hay una fila con un nulo que nadie esperaba.

Se borra solo

Un entorno efímero que no se limpia deja de ser efímero y pasa a ser un clúster lleno de basura. La limpieza va automática al cerrar el PR, y en el portal además hay un tope de veinticuatro horas.

La etiqueta también importa: solo se levanta preview si el PR la lleva. Sin eso, cada cambio de documentación arrastra una base de datos.

Cuándo no compensa

El coste no es el CPU: es que necesitas la plataforma debajo. Sin GitOps, sin secretos externos y sin una base de datos que sepa provisionarse sola, montar previews por PR es construir esas tres cosas primero.

Si ya las tienes, es de lo más barato que puedes añadir. Si no, el orden correcto es el inverso.

Seguir leyendo