Saltar a contenido

CI/CD: del commit a producción

Qué significan las siglas, qué problema resuelven y cómo se ven en el pipeline del curso.

El problema que resuelve

Entre «el código está listo» y «los usuarios lo están usando» hay una serie de pasos repetitivos: compilar, probar, empaquetar, subir el artefacto, actualizar el servidor y comprobar que quedó arriba. Hacerlos a mano tiene un costo conocido:

Sin pipeline Con pipeline
«En mi máquina funciona» La misma imagen en todos los entornos
Un documento de 12 pasos que alguien sigue de memoria Los pasos son un archivo YAML versionado
Se despliega los viernes, con miedo Se despliega cualquier día, varias veces
Nadie sabe con certeza qué versión está arriba Cada versión tiene su commit y su tag
Volver atrás es un trabajo manual Volver atrás es desplegar el tag anterior

CI/CD es automatizar ese camino para que un cambio pueda llegar a producción en minutos, de forma repetible y sin intervención manual.

Las tres siglas

flowchart LR
    A["Commit<br/>push a main"] --> B["Build<br/>compilar"]
    B --> C["Pruebas<br/>unitarias y análisis"]
    C --> D["Imagen<br/>docker build y push"]
    D --> E["Despliegue<br/>al servidor"]

CI · Integración continua

Cada cambio que llega al repositorio se compila y se prueba automáticamente. Si algo rompe, se sabe en minutos y no cuando ya hay veinte cambios encima.

Lo que normalmente corre en esta etapa: compilación, pruebas unitarias, análisis estático (SonarQube) y, a veces, pruebas funcionales.

CD · Entrega continua (continuous delivery)

El resultado de la integración queda siempre listo para publicar: una imagen versionada en un registro. El despliegue existe como un botón, pero una persona decide cuándo se aprieta.

CD · Despliegue continuo (continuous deployment)

Nadie aprieta nada: si el pipeline pasa, el cambio llega solo al servidor. Es lo que hace el workflow del curso sobre la rama main.

La diferencia entre las dos CD es un botón

Entrega continua deja el artefacto listo y espera una aprobación. Despliegue continuo publica automáticamente. La decisión depende del riesgo del proyecto, no de la herramienta.

Qué se necesita para que funcione

Un pipeline no es solo el archivo YAML. Descansa sobre cuatro cosas que ya vimos en el curso:

Pieza Para qué Dónde está en el curso
Control de versiones Todo cambio pasa por el repositorio Git y GitHub
Pruebas automáticas Si no hay pruebas, el pipeline automatiza publicar errores más rápido Pruebas unitarias
Un artefacto inmutable La misma imagen que se probó es la que se despliega Docker
Un destino reproducible El servidor se describe en archivos, no se configura a mano Kubernetes o Docker Compose

El pipeline del curso, paso a paso

El proyecto cowork tiene un único archivo .github/workflows/build.yml con dos jobs. El flujo completo después de un git push a main:

flowchart LR
    P["1 · git push<br/>a main"] --> A["2 · Runner de GitHub<br/>descarga el código"]
    A --> B["3 · docker build<br/>y push a ghcr.io"]
    B --> C["4 · Nuestro runner<br/>en el servidor"]
    C --> D["5 · kubectl apply<br/>y rollout restart"]
    D --> E["6 · Pod nuevo<br/>corriendo"]

Job 1 · construir y publicar la imagen

Corre en un runner de GitHub (ubuntu-latest): compilar y empaquetar no necesita acceso a nuestra red.

.github/workflows/build.yml
jobs:
  build-and-publish:
    name: Build and Push Image to GHCR
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write          # para publicar en GHCR
    steps:
      - uses: actions/checkout@v4
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}   # credencial temporal del job
      - run: docker build -t ghcr.io/${OWNER_LC}/${IMAGE_NAME}:${IMAGE_TAG} .
      - run: docker push ghcr.io/${OWNER_LC}/${IMAGE_NAME}:${IMAGE_TAG}

Job 2 · desplegar en el servidor

Corre en el runner self-hosted (runs-on: main), el único que alcanza el clúster MicroK8s on-premise.

.github/workflows/build.yml
  deploy-onpremise:
    name: Deploy on MicroK8s On-Premise
    runs-on: main                 # nuestro runner self-hosted
    needs: build-and-publish      # solo si el job anterior terminó bien
    steps:
      - uses: actions/checkout@v4
      - run: sudo microk8s kubectl apply -f k8s/deployment.yaml
      - run: sudo microk8s kubectl rollout restart deployment/cowork-api -n docsjaveriana
      - run: sudo microk8s kubectl rollout status  deployment/cowork-api -n docsjaveriana --timeout=300s

Tres decisiones que vale la pena entender de este archivo:

  • needs: si la imagen no se publicó, no se despliega nada.
  • rollout restart: con el tag :latest el apply no cambia el YAML, así que hay que forzar que el clúster baje la imagen nueva.
  • rollout status: el workflow queda en rojo si el pod nuevo no llega a estar listo. Sin esta línea, un despliegue roto se reportaría como exitoso.

El detalle de cada paso está en GitHub Actions; quién lo ejecuta, en Action Runners.

El mismo pipeline, otro destino

Si el proyecto se despliega con Docker Compose en lugar de Kubernetes, solo cambian los últimos pasos: docker compose pull y docker compose up -d. Todo lo anterior —el Dockerfile, la imagen y el primer job— es idéntico.

Buenas prácticas

Siete reglas que evitan problemas

  1. Ramas cortas y commits pequeños. Un cambio pequeño que falla es fácil de encontrar y de revertir.
  2. El pipeline rojo se arregla primero. Un main roto bloquea a todo el equipo.
  3. Nada de secretos en el YAML. Van en los secrets del repositorio o en variables de entorno.
  4. La imagen se construye una sola vez. La misma que pasó las pruebas es la que se despliega; no se reconstruye por entorno.
  5. Tags con versión, no solo :latest. Con :latest nunca se sabe qué está corriendo ni cómo volver atrás.
  6. El pipeline debe fallar cuando algo falla. Un paso que ignora errores da una falsa sensación de seguridad.
  7. Rápido. Si el pipeline tarda media hora, la gente deja de esperarlo y empieza a saltárselo.

Preguntas frecuentes

¿CI/CD es lo mismo que DevOps?

No. CI/CD es una práctica técnica concreta; DevOps es la forma de trabajo que la hace posible. Ver DevOps.

¿Necesito Kubernetes para hacer CI/CD?

No. El destino puede ser un servidor con Docker Compose, un servicio administrado o incluso un scp a una máquina. Lo que define CI/CD es la automatización del camino, no la tecnología del final.

¿Y si no tengo pruebas automáticas?

El pipeline sigue sirviendo para construir y desplegar de forma repetible, pero sin pruebas solo garantiza que el error llegue antes a producción. Las pruebas son lo que convierte la velocidad en seguridad.

Referencias