Seis lecciones, seis herramientas y el mismo pipeline de Reservalia traducido seis veces. Si has llegado hasta aquí esperando que esta lección diga cuál es la mejor, la respuesta va a decepcionar y a la vez es lo más útil que puede darte el módulo: la pregunta está mal planteada. No porque sea de mal gusto comparar —vamos a comparar en detalle—, sino porque "la mejor herramienta" no es una propiedad de la herramienta: es una propiedad de la relación entre la herramienta y un contexto concreto, con su código, su equipo, sus restricciones legales, su presupuesto y lo que ya sabe operar. Esta lección hace cuatro cosas: recapitula el pipeline de Reservalia en las herramientas vistas y fija una tabla de equivalencias de vocabulario que te servirá el resto de tu carrera; compara por dimensiones, sin ganadores globales; ordena los criterios de decisión por su peso real, que es muy distinto del peso que se les da en las discusiones de equipo; y trata lo que casi nunca se trata: cuánto cuesta cambiar de herramienta, cómo reducir ese coste antes de necesitarlo, y cómo migrar sin parar al equipo.

Contenido

  1. Por qué "¿cuál es la mejor?" está mal planteada
  2. El mismo pipeline, seis veces: recapitulación
  3. Tabla de equivalencias de vocabulario
  4. Comparativa por dimensiones
  5. Los criterios de decisión, ordenados por peso real
  6. Un árbol de decisión
  7. Coste total de propiedad, con números
  8. El coste de cambiar de herramienta y cómo reducirlo
  9. Migración entre herramientas, por fases
  10. Elegir por moda, o por lo que usaba tu antigua empresa
  11. Errores Comunes y Consejos
  12. Ejercicios
  13. Conclusión y cierre del módulo

  1. Por qué "¿cuál es la mejor?" está mal planteada

La pregunta supone que existe un orden total entre herramientas que resuelven el mismo problema. No existe, por tres razones concretas.

Primera: las herramientas convergen. Compara lo que hacen hoy las seis y verás que el 80 % coincide: pipeline definido en un fichero del repositorio, jobs con dependencias, ejecución en contenedores, caché, artefactos, matrices, secretos, aprobaciones, identidad federada. Las diferencias reales están en el 20 % restante y en cómo se sienten al usarlas. Elegir por una lista de funcionalidades produce empates constantes.

Segunda: el coste dominante no es la herramienta, es el contexto. Migrar de una a otra cuesta semanas; operar una instalación autoalojada cuesta media persona; formar al equipo cuesta meses de fluidez. Comparado con eso, que una tenga mejor sintaxis de matriz es ruido.

Tercera: la mayoría de las decisiones ya están tomadas cuando llega la pregunta. Si el código está en GitHub, la identidad del equipo está en GitHub y la protección de ramas está en GitHub, elegir otro CI significa mantener una integración adicional para siempre. Eso no lo compensa casi ninguna ventaja técnica.

Las preguntas bien planteadas son estas, y el resto de la lección las responde:

Pregunta útil Dónde se responde
¿Qué restricciones no negociables tengo? (datos, red, hardware, cumplimiento) Apartado 5, criterio 2
¿Dónde vive mi código y mi identidad? Apartado 5, criterio 1
¿Qué sabe operar mi equipo hoy, y qué está dispuesto a operar? Apartado 5, criterio 3
¿Cuál es el coste total, incluidas las personas? Apartado 7
¿Qué me costaría cambiar dentro de tres años, y cómo lo reduzco ya? Apartado 8

Y una pregunta que no es útil: "¿cuál es más potente?". Todas son suficientemente potentes para el 95 % de los pipelines. La potencia deja de ser el factor limitante muy pronto.

  1. El mismo pipeline, seis veces: recapitulación

El pipeline de Reservalia —instalar con caché → lint y test en paralelo con sharding → build de imagen → escaneo → publicar por digest → desplegar con aprobación— expresado en cada herramienta, y qué reveló cada traducción:

Herramienta Cómo quedó Qué reveló la traducción
GitHub Actions (base) needs, matrix, composite action, reusable workflow, OIDC, Environments El punto de referencia del curso
Jenkins (06-01) Jenkinsfile declarativo: stages, parallel, matrix, stash, input, post El grafo es implícito (árbol, no DAG); el input retiene ejecutor si no se cuida; el stash pasa por el controlador
GitLab CI (06-02) stages + needs, parallel, services, environment, registro integrado La distinción cache/artifacts es explícita; el registro y las credenciales vienen regalados; rules gobierna todo
CircleCI (06-03) workflows con requires, parallelism, commands, orbs, contexts Caché totalmente manual; workspace ≠ caché ≠ artefactos; reparto por tiempos históricos que las demás no traen
Travis CI (06-04) stages + jobs.include, fases fijas No cabe del todo: sin grafo, sin paso de artefactos entre jobs, sharding copiado cuatro veces, promoción por digest comprometida
Kubernetes (06-05) No es CI: es el destino. Deployment por digest, sondas, rollout undo, GitOps Cambia quién inicia el despliegue y saca las credenciales del CI

La conclusión del ejercicio es la que justifica haberlo hecho seis veces: el pipeline es el mismo problema en todas partes. Instalar de forma reproducible, verificar en paralelo, construir un artefacto inmutable, escanearlo, publicarlo identificado por su contenido y promocionarlo con una puerta. Lo que cambia es la sintaxis, el nombre de las piezas y qué te regala la herramienta. Quien entiende el problema traduce a cualquier sintaxis en días; quien solo conoce una sintaxis empieza de cero cada vez.

  1. Tabla de equivalencias de vocabulario

Esta tabla es probablemente lo más reutilizable de la lección. Guárdala.

Concepto GitHub Actions GitLab CI Jenkins CircleCI Travis CI
Fichero de definición .github/workflows/*.yml .gitlab-ci.yml Jenkinsfile .circleci/config.yml .travis.yml
Ejecución completa Workflow run Pipeline Build / Run Pipeline Build
Unidad con máquina propia Job Job Stage con agent Job Job de la matriz
Agrupación lógica (no existe) Stage Stage (no existe) Stage
Comando individual Step Línea de script Step Step Fase (script, install…)
Máquina ejecutora Runner Runner (+ executor) Agent / node Executor Worker
Ranura de concurrencia (implícito) concurrent Executor (implícito) (implícito)
Dependencia entre unidades needs needs / stages Orden de stages requires Orden de stages
Ejecución paralela matrix, jobs parallel, jobs parallel parallelism, jobs Entradas de matriz
Caché de dependencias actions/cache cache: Plugin / volumen save_cache/restore_cache cache:
Paso de ficheros entre unidades Artefactos artifacts stash/unstash Workspace (no existe)
Salida descargable Artefactos artifacts archiveArtifacts store_artifacts (externo)
Salida de valores outputs reports:dotenv env / script (fichero + workspace) (no existe)
Servicio auxiliar services: services: Contenedor del pod Contenedor secundario services:
Secretos secrets Variables protegidas Credentials + withCredentials Contexts / variables secure:
Identidad federada OIDC (id-token) id_tokens Plugin / rol de instancia OIDC (no)
Reutilización de pasos Composite action extends / include Shared Library (vars/) Command (anchors YAML)
Reutilización de jobs Reusable workflow Componente / include Shared Library Orb (no)
Registro de plantillas Marketplace Catálogo de componentes Repositorio de librería Registro de orbs (no)
Entorno de despliegue environment environment (plugin) (no modelado) (no)
Aprobación manual Revisores de Environment when: manual input type: approval (no)
Cancelar obsoletos concurrency interruptible disableConcurrentBuilds Auto-cancel (no)
Filtro por rutas paths rules: changes when { changeset } (lógica propia) (no)

Dos observaciones que se leen entre líneas. Primero, la columna de Travis tiene muchos huecos, y eso no es un descuido: es la diferencia entre una herramienta de CI y una de CI/CD, y explica su declive mejor que cualquier análisis de mercado. Segundo, "job" significa cosas distintas: en Jenkins un job es lo que en las demás es un workflow, mientras que la unidad con máquina propia es el stage con agente. Es la confusión de vocabulario que más malentendidos causa en equipos mixtos.

  1. Comparativa por dimensiones

Sin ganadores globales: cada fila es una dimensión y lo relevante es cuáles te importan a ti.

Dimensión GitHub Actions GitLab CI Jenkins CircleCI Travis CI
Modelo de ejecución Grafo (needs) Etapas → grafo Árbol con paralelo anidado Grafo desde el origen Fases fijas
Alojamiento SaaS + runners propios SaaS o autoalojado completo Solo autoalojado SaaS + runners propios SaaS
Configuración Código Código Código (con herencia de UI) Código Código
Reutilización Composite + reusable + marketplace extends/include/componentes Shared Libraries Orbs con versionado inmutable Muy limitada
Secretos e identidad federada OIDC nativo, entornos OIDC nativo, variables protegidas Plugins; no nativo OIDC, contexts Cifrado en repo
Ecosistema El mayor Medio, integrado El más amplio en integraciones raras Medio Residual
Plataforma integrada Alta (repo, registro, issues) La más completa Ninguna: pieza suelta Ninguna: pieza suelta Ninguna
macOS / ARM / GPU Sí (macOS caro) Con runners propios Cualquier cosa que tengas Amplia oferta ARM y arquitecturas raras
Madurez de despliegue y aprobaciones Environments con reglas Entornos con historial y on_stop input, sin modelo de entorno type: approval, sin entorno Proveedores deploy
Observabilidad del pipeline Media (resúmenes, tiempos) Buena Depende de plugins La mejor Escasa
Modelo de coste Minutos + almacenamiento Por usuario + minutos Infraestructura + personas Créditos + usuarios Créditos
Coste de salida Medio Alto (repo + CI + registro) Medio Bajo Bajo

Cómo leer esta tabla sin equivocarse: una fila solo importa si es un requisito tuyo. "Plataforma integrada: la más completa" es una ventaja enorme si buscas plataforma y una desventaja si ya tienes un ecosistema montado y solo quieres CI. "Solo autoalojado" es descalificante para un equipo de tres y es exactamente lo que necesita una empresa con datos que no pueden salir. No hay una columna que gane más filas y por tanto gane.

  1. Los criterios de decisión, ordenados por peso real

Aquí está el contenido más valioso de la lección, y el orden importa más que la lista.

Criterio 1 — Dónde viven el código y la identidad del equipo (decide ~80 % de los casos)

Si tu código está en GitHub y tu equipo se autentica con GitHub, GitHub Actions parte con una ventaja que casi nada compensa. Si está en GitLab, lo mismo con GitLab CI. No es pereza: es que usar un CI externo implica, para siempre:

  • Una integración de permisos que mantener y que se rompe cuando alguien rota un token.
  • Sincronización de identidades: quién puede desplegar hay que definirlo dos veces, y las dos definiciones divergen.
  • Dos sitios donde mirar cuando algo falla, y un salto de contexto en cada incidente.
  • Checks que llegan desde fuera y una protección de rama que depende de una integración.

Ese coste es permanente y silencioso. La ventaja técnica que lo justifique tiene que ser grande y concreta. Este criterio no es un empate a romper: es el punto de partida, y las demás herramientas tienen que ganárselo.

Corolario incómodo: si tu código está en GitHub y estás evaluando cinco herramientas de CI, probablemente estás resolviendo el problema equivocado. Empieza por la integrada, identifica qué te falta con nombres concretos y solo entonces mira fuera.

Criterio 2 — Restricciones de cumplimiento y datos (decide, cuando aplica, sin discusión)

Si existe una restricción legal o contractual real, manda sobre todo lo demás. Las preguntas que hay que hacer antes de nada:

  • ¿El código fuente puede salir de nuestra red? ¿Y los logs, que a menudo contienen más de lo que parece?
  • ¿Los datos de prueba contienen información personal o regulada?
  • ¿Hay obligación de retención de auditoría, con quién aprobó qué y cuándo?
  • ¿Se exige separación de funciones —que quien escribe el cambio no sea quien lo aprueba—?
  • ¿Hay requisito de residencia de datos en una jurisdicción concreta?

Aviso importante y frecuente: un runner autoalojado de un SaaS no satisface una restricción estricta. El trabajo corre en tu red, sí, pero el plano de control, la orquestación, los logs y a menudo los secretos siguen en un tercero. Si la exigencia es literal, la respuesta es autoalojar la plataforma entera: Jenkins o GitLab autoalojado. Y la primera acción no es técnica: es leer el contrato o la norma, porque la mitad de las veces la restricción es menos estricta de lo que el equipo asume, y la otra mitad es más.

Criterio 3 — Qué sabe operar el equipo hoy

Una herramienta que nadie sabe operar es peor que una menos capaz que el equipo domina. Un Jenkins sin dueño se degrada solo (06-01); un clúster de Kubernetes mal operado es peor que ECS (06-05).

Preguntas concretas, con nombres y apellidos:

  • ¿Quién actualiza esto? ¿Qué deja de hacer mientras?
  • ¿Quién responde a las tres de la mañana si el CI cae durante una incidencia?
  • ¿Quién restaura la copia de seguridad, y cuándo se ensayó por última vez?
  • ¿Qué pasa cuando esa persona se va de vacaciones o de la empresa?

Si no hay respuesta a alguna, la opción autoalojada no está sobre la mesa por mucho que técnicamente convenza. Para Reservalia —Marta, Diego y Nuria— la respuesta es evidente y no requiere análisis: SaaS.

Criterio 4 — Necesidades de hardware y plataforma

macOS para compilar iOS (05-02), GPU para modelos, ARM nativo, dispositivos físicos, licencias atadas a una máquina, mucha memoria. Aquí el orden se invierte: si hay una necesidad de hardware que solo cubre una opción, esa opción entra sí o sí, aunque sea solo para esa parte del pipeline. El patrón habitual y sensato es híbrido: la herramienta principal para todo, y una pieza específica donde el hardware lo obliga.

Criterio 5 — Presupuesto y su forma

No solo cuánto, también de qué tipo:

Forma del coste Herramientas Implicaciones
Opex variable (por minuto/crédito) Actions, CircleCI, GitLab SaaS Crece con la actividad; sin inversión inicial; sorpresas si nadie vigila
Opex por usuario GitLab, en parte CircleCI Predecible; castiga a colaboradores ocasionales
Capex + opex de personas Jenkins, GitLab autoalojado Coste inicial y personas fijas; predecible; independiente de la actividad

Este criterio se cruza con el 3: el coste de las personas es real aunque no aparezca en ninguna factura, y es precisamente el que más se olvida en las hojas de cálculo que comparan "X euros al mes de SaaS" con "una máquina que ya tenemos".

Criterio 6 — Madurez del equipo en CI/CD

Un equipo que empieza se beneficia de una herramienta opinada, con valores por defecto sensatos y mucha documentación. Un equipo maduro con necesidades particulares valora el control. Adoptar Jenkins con Shared Libraries y agentes en Kubernetes siendo tres personas que nunca hicieron CI es garantía de abandono; adoptar una herramienta muy opinada teniendo requisitos raros es garantía de pelear contra ella cada semana.

El resumen del orden

1. Restricciones no negociables  → si las hay, filtran primero
2. Dónde vive el código           → decide el 80 % de lo que queda
3. Quién opera                    → descarta opciones, no las elige
4. Hardware                       → añade piezas híbridas
5. Presupuesto y su forma         → afina entre las supervivientes
6. Madurez                        → decide cuánta cuerda darse

Nótese que la calidad técnica de la herramienta no aparece en la lista. No porque dé igual, sino porque todas las supervivientes de los seis filtros son suficientemente buenas, y a esas alturas la decisión ya está tomada.

  1. Un árbol de decisión

flowchart TD
    A["Elegir herramienta de CI/CD"] --> B{"Hay restriccion legal o contractual<br/>que impida usar un SaaS?"}
    B -->|"Si"| C{"Quien opera la plataforma?"}
    C -->|"Nadie con tiempo"| D["Resolver eso primero:<br/>no hay opcion viable sin operador"]
    C -->|"Hay equipo"| E{"Se quiere plataforma completa<br/>o solo motor de automatizacion?"}
    E -->|"Plataforma"| F["GitLab autoalojado"]
    E -->|"Motor"| G["Jenkins"]

    B -->|"No"| H{"Donde vive el codigo?"}
    H -->|"GitHub"| I["GitHub Actions<br/>punto de partida"]
    H -->|"GitLab"| J["GitLab CI/CD<br/>punto de partida"]
    H -->|"Varios o Bitbucket"| K["CircleCI u otro SaaS<br/>independiente"]

    I --> L{"Falta algo concreto<br/>con nombre?"}
    J --> L
    L -->|"No"| M["Quedarse. Invertir en el pipeline,<br/>no en elegir herramienta"]
    L -->|"Velocidad de suite grande"| N["Evaluar CircleCI<br/>o mejorar lo actual primero"]
    L -->|"Hardware especial"| O["Hibrido: runners propios<br/>o Jenkins solo para esa pieza"]
    L -->|"Muchos servicios en Kubernetes"| P["Anadir GitOps: Argo CD o Flux<br/>no cambiar de CI"]

Dos ramas merecen comentario porque son las que más se equivocan en la práctica.

"Falta algo concreto con nombre": la exigencia de nombrarlo es deliberada. "Nos gustaría algo mejor" no es un requisito. "El job de e2e tarda 14 minutos por reparto desigual y no tenemos histórico de tiempos" sí lo es, y —fíjate— probablemente se arregla sin cambiar de herramienta.

"Muchos servicios en Kubernetes" lleva a añadir GitOps, no a cambiar de CI. Es un error muy común: el problema es el modelo de despliegue (06-05), no el motor de CI, y cambiar el segundo no arregla el primero.

  1. Coste total de propiedad, con números

Comparar "20 euros al mes" con "una máquina que ya tenemos" es la forma más habitual de equivocarse. El ejercicio correcto incluye las personas.

Escenario: equipo de 12 desarrolladores, 40 ejecuciones de pipeline al día, 12 minutos de cómputo por ejecución en 4 jobs paralelos ≈ 35 minutos-máquina por ejecución.

Consumo mensual = 40 ejecuciones/día × 21 días × 35 min ≈ 29.400 minutos-máquina
Concepto SaaS por minuto Autoalojado
Cómputo 29.400 min × tarifa por minuto 3 máquinas siempre encendidas
Almacenamiento (artefactos, caché) Facturado por GB Discos y copias
Licencias Incluido o por usuario × 12 Según herramienta y nivel
Operación ~0 h/mes 8-16 h/mes: actualizaciones, plugins, agentes, incidencias
Guardia 0 Parte de una rotación, o alguien de facto
Puesta en marcha Horas 2-6 semanas de una persona
Coste de indisponibilidad Del proveedor Tuyo, y el equipo parado mientras dura

La fórmula que hay que usar, y el número que casi siempre decide:

TCO_autoalojado = infraestructura + licencias
                + (horas_operación/mes × coste_hora_cargado)
                + amortización(puesta_en_marcha)
                + riesgo(indisponibilidad × frecuencia)

TCO_saas       = cómputo + almacenamiento + licencias_por_usuario
                + horas_gestión_ligera

Con un coste cargado por hora de una persona de plataforma —salario más impuestos, herramientas y espacio—, 10 horas al mes de operación suelen superar por sí solas la factura completa de un SaaS para un equipo de este tamaño. Ese es el resultado que sorprende y el que hay que llevar a la conversación con quien decide. Y el punto de equilibrio se desplaza con el tamaño: con 200 desarrolladores y un uso muy intensivo, las mismas 10-20 horas mensuales se reparten entre mucho más consumo y lo autoalojado puede ganar con claridad.

Tres avisos para que el cálculo sea honesto:

  • No inventes tarifas. Las de cada proveedor cambian por plan, región y tipo de máquina; consúltalas el día que hagas el cálculo y anota la fecha.
  • Cuenta los multiplicadores. macOS y máquinas grandes no cuestan lo mismo por minuto; un pipeline con mucho macOS (05-02) cambia el resultado por completo.
  • Incluye lo que el SaaS te ahorra en integraciones. Si la alternativa exige mantener sincronización de identidades y webhooks, eso son horas que van en la columna del autoalojado, no en ninguna.

  1. El coste de cambiar de herramienta y cómo reducirlo

Una migración de CI/CD en un repositorio real es de semanas, no de días, y el reparto del esfuerzo es sistemáticamente el mismo:

Parte del pipeline Coste de migrar Proporción típica
Lógica de build, test, despliegue Bajo si está en scripts; alto si está en el YAML 40-60 % del contenido
Orquestación (jobs, dependencias, matriz, disparadores) Reescritura mecánica 20-30 %
Integraciones (acciones/orbs/plugins de terceros) Reconstrucción 10-20 %
Secretos e identidad federada Reconfigurar y rotar 5-10 %
Aprendizaje del equipo Semanas de menor fluidez Difuso y real

La palanca que de verdad mueve ese número la anticipó la 06-04 y la merece repetir: saca la lógica del YAML y déjalo como orquestador delgado.

# Frágil: 60 líneas de lógica dentro del YAML de una herramienta concreta
- run: |
    npm ci --prefer-offline
    npx prettier --check .
    npm run lint -- --max-warnings 0
    npx tsc --noEmit
    npm test -- --coverage --shard=${{ matrix.shard }}/4
    node scripts/comprobar-cobertura.js --minimo 80
# Makefile — interfaz estable, independiente de la herramienta
.PHONY: instalar calidad test build imagen

instalar:
	npm ci --prefer-offline

calidad: instalar
	npx prettier --check .
	npm run lint -- --max-warnings 0
	npx tsc --noEmit

test: instalar
	npm test -- --coverage --shard=$(SHARD)/$(TOTAL)
	node scripts/comprobar-cobertura.js --minimo 80

imagen:
	docker buildx build --file apps/api/Dockerfile \
	  --cache-from type=registry,ref=$(ECR)/$(IMAGEN):cache \
	  --tag $(ECR)/$(IMAGEN):$(SHA) --push .
# El YAML, en cualquier herramienta, se vuelve trivial
- run: make calidad
- run: make test SHARD=${{ matrix.shard }} TOTAL=4

Beneficios, y este es el argumento importante: no dependen de que llegues a migrar.

  • El desarrollador ejecuta exactamente lo mismo en local. Desaparece la clase entera de fallos "solo pasa en CI", que es de las que más tiempo consumen.
  • La lógica es código revisable y testeable, no una cadena dentro de un YAML que nadie lee en el PR.
  • El pipeline se vuelve legible: un ci.yml con make calidad y make test se entiende de un vistazo.
  • Y sí, migrar pasa de semanas a días.

El límite honesto: no todo sale del YAML. Disparadores, matrices, permisos, entornos, aprobaciones, concurrencia y caché son propios de cada herramienta, y abstraerlos exige una capa de indirección que cuesta más de lo que ahorra. El objetivo razonable no es portabilidad total, sino que el grueso del esfuerzo de migración sea reescribir orquestación, no reconstruir lógica.

  1. Migración entre herramientas, por fases

Cuando la migración está decidida, el patrón que funciona es el mismo de la 05-04: incrementos con valor propio y sin congelar al equipo.

Fase Qué se hace Cuándo pasar a la siguiente Riesgo
1. Inventario Todos los workflows, qué hace cada uno, quién depende de él, qué secretos usa, qué integraciones tiene. Y qué está muerto Cuando esté escrito y revisado Ninguno; omitirla es el error clásico
2. Pipeline paralelo El nuevo se ejecuta junto al viejo en cada PR, sin ser obligatorio. Se comparan resultados 2-3 semanas con resultados coincidentes Coste doble de cómputo temporal
3. Cambio de la señal obligatoria El check obligatorio pasa a ser el nuevo; el viejo queda informativo Cuando nadie mire ya el viejo El más alto: aquí se descubre lo que faltaba
4. Migrar el CD Despliegue al final, y por entornos: primero staging, luego producción Cuando staging lleve semanas estable Alto: afecta a producción
5. Retirada Borrar el pipeline viejo, desactivar el servicio, revocar todos los secretos, actualizar documentación e insignias Bajo, si las fases previas se hicieron

Cuatro reglas que evitan los desastres habituales:

El CD se migra el último, siempre. El CI se puede duplicar sin consecuencias; un despliegue duplicado o a medias sí las tiene. Y dentro del CD, primero staging.

Nunca se migra todo a la vez en organizaciones con muchos repositorios. Se elige un repositorio piloto —representativo pero no crítico—, se aprende con él, se escribe una plantilla y se propaga.

Los secretos se rotan, no se copian. Es el momento natural para hacerlo y para descubrir cuáles ya no hacía falta que existieran. Y en la fase 5, revocar los del sistema viejo es parte de la migración, no un extra.

Qué no migrar, que es tan importante como qué migrar: workflows que nadie mira, jobs desactivados desde hace meses, integraciones con sistemas que ya no existen, matrices de versiones sin soporte, y la lógica que "estaba por si acaso". Una migración es la mejor ocasión que tendrás para borrar; desaprovecharla es trasladar la deuda intacta y añadirle el coste del traslado.

  1. Elegir por moda, o por lo que usaba tu antigua empresa

Dos sesgos que producen decisiones caras y que conviene nombrar en voz alta porque casi nunca se dicen.

El sesgo de la conferencia. Se ve una charla excelente sobre una herramienta en una empresa con 400 ingenieros, cinco personas de plataforma y un problema de escala que no tienes, y se concluye que es lo que hay que usar. La pregunta que lo desactiva: ¿qué problema mío, con nombre, resuelve esto que hoy no esté resuelto? Si no hay respuesta concreta, es admiración, no un requisito. Es la misma trampa que la 06-05 señalaba con Kubernetes, y la respuesta es idéntica: la complejidad se justifica con un problema, no con quién más la usa.

El sesgo del recién llegado. Alguien entra en el equipo desde una empresa donde usaban X y propone migrar a X. A veces tiene razón —trae experiencia real que el equipo no tiene—, pero el sesgo es predecible: conoce X en profundidad y la herramienta actual apenas, así que compara lo mejor de una con lo peor de la otra. La prueba que lo desactiva: pedirle que primero domine lo que hay y luego liste, con nombres, qué le falta. Si tras dos meses la lista sigue en pie y es concreta, la propuesta merece evaluación seria. La mayoría de las veces la lista se reduce a dos elementos, y ambos se resuelven configurando mejor lo que ya está.

Y una tercera trampa más sutil: cambiar de herramienta para no arreglar el pipeline. Un pipeline lento por flaky sin cuarentena, caché mal configurada y jobs sin timeout seguirá siendo lento en la herramienta nueva, con la diferencia de que ahora nadie sabe dónde mirar. Antes de evaluar alternativas, aplica lo de la 04-04: mide, separa cola de ejecución, y arregla lo tuyo. Si tras eso el problema persiste y es de la herramienta, ya tienes datos para la conversación.

Errores Comunes y Consejos

Comparar por lista de funcionalidades. Todas tienen casi todo. La decisión está en el contexto, no en la tabla.

Ignorar dónde vive el código. Es el criterio de más peso y el que más se subestima en las discusiones de equipo.

Contar solo la factura. Las horas de operación son coste real; en equipos medianos suelen superar al SaaS que se quería evitar.

Creer que un runner autoalojado satisface una restricción de cumplimiento. El plano de control sigue fuera. Lee la norma antes de diseñar.

Migrar el CD antes que el CI. El CI se duplica sin daño; un despliegue, no.

Migrar uno a uno sin aprovechar. Sin needs, sin arreglar la caché, sin borrar lo muerto: se traslada la deuda y se paga el traslado.

Copiar los secretos en vez de rotarlos. Y no revocar los del sistema viejo al terminar.

Elegir una herramienta que nadie va a operar. Un Jenkins sin dueño es peor que no tener CI, porque da una señal en la que la gente confía.

Confundir "más potente" con "mejor para nosotros". La potencia deja de ser el factor limitante muy pronto.

Consejo transversal que resume el módulo: invierte en entender el problema —artefacto inmutable, promoción por digest, puertas de calidad, feedback rápido, mínimo privilegio— y trata la herramienta como intercambiable. Quien domina el problema aprende una herramienta nueva en dos semanas; quien solo domina una sintaxis empieza de cero cada vez que cambia de trabajo.

Ejercicios

Ejercicio 1. Tres escenarios. Para cada uno, aplica los seis criterios en orden, recomienda una herramienta (o combinación) y justifica qué criterio fue decisivo y cuáles resultaron irrelevantes:

  • (a) Startup de 6 personas, código en GitHub, aplicación web Node desplegada en Vercel y una API en ECS. Sin restricciones legales. Nadie quiere operar infraestructura.
  • (b) Empresa de 300 personas en el sector sanitario. El código no puede salir de su red por contrato con sus clientes. Ya tienen Jenkins con 180 jobs freestyle. Equipo de plataforma de 4 personas. Quieren "modernizarse".
  • (c) Empresa de producto de 40 personas, código en GitLab autoalojado, 12 microservicios en Kubernetes, aplicación móvil iOS y Android, y un equipo de plataforma de 2 personas que está desbordado.

Ejercicio 2. Calcula el TCO comparado para un equipo de 25 desarrolladores con 80 ejecuciones diarias de 15 minutos en 5 jobs paralelos. Compara SaaS por minuto frente a Jenkins autoalojado en máquinas propias. Enumera todas las partidas —incluidas las que no aparecen en ninguna factura— y explica qué supuesto tendría que cambiar para invertir el resultado.

Ejercicio 3. Marta te pide un plan: reducir la dependencia de Reservalia respecto a GitHub Actions sin migrar y sin parar el desarrollo. Propón las acciones concretas, su coste, su beneficio con independencia de que la migración llegue a ocurrir, y dónde está el punto en que dejar de invertir. Estima el antes y el después del coste de una migración hipotética.

Soluciones

Solución 1.

(a) Startup de 6 personas.

Criterio Resultado
1. Restricciones Ninguna → no filtra
2. Código e identidad GitHub → decisivo
3. Quién opera Nadie → descarta todo lo autoalojado
4. Hardware Nada especial → irrelevante
5. Presupuesto Repositorio privado, poco volumen: los minutos incluidos probablemente cubren
6. Madurez Baja: conviene lo opinado y bien documentado

Recomendación: GitHub Actions, sin más análisis. Decisivos: criterios 2 y 3, que apuntan al mismo sitio. Irrelevantes: 4 y, casi, el 5. El consejo que acompaña a la recomendación es más valioso que ella: con 6 personas, el tiempo gastado en evaluar herramientas es tiempo robado al pipeline; usa lo integrado y dedica ese esfuerzo a poner puertas de calidad, despliegue automatizado y métricas DORA (01-05).

(b) Empresa sanitaria de 300 personas.

Criterio Resultado
1. Restricciones El código no sale de la red → decisivo, filtra primero: solo autoalojado
2. Código e identidad Depende de dónde esté; si es GitHub Enterprise Server o GitLab autoalojado, apunta a su CI integrado
3. Quién opera 4 personas: hay equipo. Viable
4. Hardware A verificar; en salud suele haber integraciones con sistemas antiguos
5. Presupuesto Capex + personas, ya asumido
6. Madurez Media-baja: 180 jobs freestyle indican prácticas de hace una década

Recomendación: no elegir herramienta todavía. El diagnóstico es que "modernizarse" no significa cambiar de herramienta, significa pasar de freestyle a pipeline as code (04-05, 06-01), y eso se hace dentro de Jenkins, sin migrar nada. Plan por fases: (1) inventario de los 180 jobs, con la expectativa fundada de que un tercio está muerto; (2) Jenkinsfile en los 20 más usados, con pipeline paralelo al freestyle; (3) JCasC y agentes efímeros para acabar con la deriva de configuración; (4) Shared Library para lo repetido. Al terminar, si aún hay razones, se reevalúa GitLab autoalojado con datos reales sobre qué falta.

Decisivo: criterio 1, que descarta todo el SaaS. Irrelevante: cualquier comparación con GitHub Actions o CircleCI, que quedaron fuera en el primer filtro. Y la lección de método: la mayor mejora disponible aquí no requiere cambiar de herramienta, y proponer una migración habría gastado meses sin resolver el problema real, que es que la configuración vive en formularios de un servidor.

(c) Empresa de producto de 40 personas.

Criterio Resultado
1. Restricciones Ninguna declarada
2. Código e identidad GitLab autoalojado → GitLab CI es el punto de partida
3. Quién opera 2 personas desbordadas → el dato más importante
4. Hardware macOS para iOS → requiere solución específica
5. Presupuesto Ya pagan la instancia; el margen está en no añadir operación
6. Madurez Alta: 12 microservicios en Kubernetes

Recomendación: quedarse en GitLab CI y no añadir ninguna herramienta, con tres acciones concretas. Para macOS, runners macOS gestionados por un tercero o el servicio SaaS de GitLab para esos jobs concretos: comprar máquinas Apple y operarlas con un equipo desbordado es exactamente lo que no se debe hacer (05-02). Para los 12 microservicios, include de un componente compartido anclado a versión, en vez de 12 ficheros divergentes (05-03, 04-05). Para Kubernetes, GitOps con Argo CD o Flux, que además saca las credenciales del clúster del CI (06-05).

Decisivo: criterio 3. El equipo de plataforma desbordado es la restricción que gobierna todas las decisiones, y cualquier recomendación que añada operación es incorrecta por definición, por buena que sea técnicamente. Irrelevante: comparar GitLab CI con CircleCI o Actions; ninguna ventaja compensaría añadir una integración externa a un equipo que no da abasto.

Solución 2.

Consumo: 80 × 21 × 15 × 5 = 126.000 minutos-máquina/mes ≈ 2.100 horas-máquina, que equivalen a unas 3 máquinas al 100 % de ocupación, y como la carga es en horario laboral, en la práctica hacen falta 5-6 máquinas para no tener cola en las horas punta.

Partida SaaS por minuto Jenkins autoalojado
Cómputo 126.000 min × tarifa vigente 6 máquinas (ociosas por la noche y el fin de semana)
Almacenamiento Artefactos y caché por GB Discos, copias de seguridad, su almacenamiento
Red Incluida Tráfico de salida al descargar imágenes y dependencias
Licencias Por usuario según plan Jenkins es libre; sistema operativo y monitorización sí cuestan
Puesta en marcha 1-2 días 3-6 semanas de una persona
Operación mensual 1-2 h (gestión ligera) 12-20 h: actualizaciones, plugins, CVE, agentes, disco
Guardia 0 Parte de una rotación
Indisponibilidad Del proveedor; sin control Tuya; con 25 personas paradas mientras dura
Formación Baja Media: Groovy, plugins, JCasC
Ahorro nocturno Automático (no se paga lo que no se usa) Ninguno: las máquinas están encendidas igual

Cálculo: con un coste cargado por hora de una persona de plataforma, 16 horas mensuales de operación suelen equivaler a una cifra del mismo orden que la factura entera del SaaS para este volumen, antes de contar máquinas, almacenamiento y puesta en marcha. Añadiendo la amortización de las 4-6 semanas iniciales durante el primer año, el autoalojado sale claramente por encima.

Qué supuestos invertirían el resultado:

  1. Un volumen mucho mayor. Con 500.000 minutos-máquina al mes, las horas de operación no crecen proporcionalmente y el coste por minuto propio baja mucho. Es la economía de escala que hace que las empresas muy grandes autoalojen.
  2. Hardware ya disponible y amortizado, con capacidad ociosa real y personal que ya lo opera para otras cosas.
  3. Una restricción de cumplimiento que haga irrelevante la comparación: entonces no es una decisión económica.
  4. Máquinas mucho más potentes o especializadas —GPU, mucha memoria— donde el multiplicador del SaaS es alto y una máquina propia se amortiza rápido.
  5. Jobs muy largos y continuos que mantengan las máquinas ocupadas también fuera del horario laboral, eliminando la ventaja de pagar solo por uso.

Conclusión defendible: para 25 desarrolladores y este volumen, SaaS, y el argumento decisivo no es la factura de cómputo —que puede incluso ser mayor— sino las 12-20 horas mensuales de una persona que no hay que dedicar a operar CI. Ese es el número que hay que llevar a la reunión.

Solución 3.

Objetivo bien planteado: no es "poder migrar", es reducir el acoplamiento a cambio de beneficios que rinden desde el primer día. Si una acción solo aporta valor en caso de migración, no entra en el plan.

# Acción Coste Beneficio inmediato (aunque nunca migremos) Reducción del coste de migrar
1 Mover la lógica de los run largos a scripts/*.sh y npm scripts, con un Makefile como interfaz (make calidad, make test, make imagen) 3 días Ejecutable en local: desaparecen los fallos "solo en CI"; lógica revisable y testeable; ci.yml legible Alta
2 Sustituir acciones de terceros que solo envuelven una CLI por la CLI directa; fijar por SHA las que queden y documentar por qué está cada una 2 días Menos superficie de suministro (04-03); menos roturas por cambios ajenos Media-alta
3 Documentar el contrato de despliegue: qué recibe desplegar.sh (digest, entorno), qué garantiza, cómo se verifica 1 día Cualquiera del equipo puede desplegar de emergencia sin el pipeline; es también el plan B de la 03-05 Media
4 Registro de decisiones del pipeline: por qué OIDC, por qué Environments, por qué esta caché 0,5 días Onboarding y revisiones más rápidas; evita replantear lo mismo cada trimestre Media
5 Prueba periódica: ejecutar make ci en una máquina limpia sin GitHub Actions 0,5 días Verifica que la portabilidad es real y no teórica; detecta dependencias ocultas del entorno del runner Alta
Capa de abstracción sobre disparadores, entornos y permisos Semanas Ninguno Baja

Dónde parar: después del punto 5. La última fila es la frontera, y el criterio es explícito: una capa de abstracción sobre lo específico de la herramienta cuesta más que la migración que evitaría y añade indirección permanente que empeora la legibilidad —justo lo que la 04-05 advertía sobre extraer abstracciones prematuras—.

Antes y después:

Hoy Tras el plan (7 días de trabajo)
Lógica en el YAML ~55 % ~10 %
Acciones de terceros 11 4, fijadas por SHA y justificadas
Reproducible en local Parcial Sí, verificado periódicamente
Migración hipotética 3-4 semanas 5-8 días

La frase para Marta, que es lo que hay que decir en la reunión: "Siete días de trabajo. La migración pasaría de un mes a una semana, pero eso es el efecto secundario: lo que compramos de verdad es que el equipo pueda ejecutar el pipeline en su portátil, que la lógica se revise como código y que el ci.yml se entienda de un vistazo. Si nunca migramos, sigue siendo rentable. Y no vamos más allá: construir una capa de abstracción sobre GitHub Actions costaría más que la migración que evitaría."

Conclusión y cierre del módulo

La conclusión del módulo se sostiene sobre una comprobación empírica que has hecho seis veces: el mismo pipeline de Reservalia cabe en todas las herramientas, porque el problema es el mismo en todas partes. Instalar de forma reproducible, verificar en paralelo con feedback rápido, construir un artefacto inmutable, escanearlo, publicarlo identificado por su contenido, promocionarlo por digest a través de una puerta y poder volver atrás. Lo que cambia es la sintaxis, el nombre de las piezas y qué te regala la plataforma. Por eso la tabla de equivalencias del apartado 3 vale más que cualquier tutorial de una herramienta concreta: te permite leer un .gitlab-ci.yml o un Jenkinsfile el primer día de un trabajo nuevo.

Lo que cada herramienta enseñó, y que se lleva uno aunque no vuelva a tocarla: Jenkins, que el control total se paga con operación real y que un motor de propósito general integra cualquier cosa a cambio de no traer nada resuelto. GitLab, que una plataforma integrada regala trazabilidad, credenciales y entornos, y cobra en acoplamiento. CircleCI, que la velocidad de un pipeline es un problema de ingeniería con soluciones concretas —reparto por tiempos, caché explícita, clases de recurso— y que la separación entre workspace, caché y artefactos aclara una confusión que dura años. Travis, que el modelo de fases fijas basta para CI y no para CD, que el negocio de tu proveedor puede cambiar bajo tus pies, y que un secreto confiado a un tercero es un secreto cuya seguridad no controlas. Docker y Kubernetes, que el sustrato importa tanto como el orquestador, que el digest manda sobre el tag, y que la complejidad se justifica con un problema y no con quién más la usa. Y GitHub Actions, que la herramienta que usas todos los días también tiene límites, asimetrías peligrosas y una superficie de suministro que hay que vigilar.

Los criterios, en el orden que importa: las restricciones no negociables filtran primero; dónde viven el código y la identidad deciden el 80 % de lo que queda; quién va a operar descarta opciones; el hardware añade piezas híbridas; el presupuesto y su forma afinan; y la madurez del equipo decide cuánta cuerda darse. La calidad técnica no aparece, porque a esas alturas ya está decidido. Y el coste que casi nadie calcula —las horas de personas— es el que suele invertir el resultado de la hoja de cálculo.

Con esto se cierra el módulo 6 y, con él, la parte conceptual del curso. Has recorrido los principios (módulos 1 a 4), cuatro contextos reales (módulo 5) y la maquinaria (módulo 6). Lo que queda es hacerlo tú. El módulo 7 es enteramente práctico: cinco ejercicios guiados que construyen, paso a paso, un pipeline de extremo a extremo —el pipeline básico, las pruebas automatizadas, el despliegue en producción, el monitoreo y la retroalimentación, y el endurecimiento con seguridad y secretos— y un proyecto final donde montas el tuyo completo, con las puertas, el artefacto inmutable, el despliegue con rollback y las métricas para saber si está funcionando. Ahí es donde todo lo anterior deja de ser lectura. Empieza por el Ejercicio 1: Pipeline Básico, que arranca justo donde arrancó la 02-02, pero esta vez lo escribes tú.

Curso de CI/CD: Integración y Despliegue Continuo

Módulo 1: Introducción a CI/CD

Módulo 2: Integración Continua (CI)

Módulo 3: Despliegue Continuo (CD)

Módulo 4: Prácticas Avanzadas de CI/CD

Módulo 5: Implementación de CI/CD en Proyectos Reales

Módulo 6: Herramientas y Tecnologías

Módulo 7: Ejercicios Prácticos

Módulo 8: Recursos Adicionales

© Copyright 2026. Todos los derechos reservados