← TODOS LOS ARTÍCULOSARTÍCULO 003 / despliegues

Un deploy verde puede dejar código viejo en producción

Dos despliegues correctos pueden terminar en el orden equivocado. Cómo comprobar qué versión quedó realmente sirviendo.

El primer cambio llega a producción y pasa sus controles. Poco después termina otro deploy del mismo sitio, también en verde. No hay errores de build, el proveedor informa éxito y la página responde.

Sin embargo, producción acaba de perder parte del primer cambio.

No falló ninguno de los dos despliegues. Falló una suposición: que terminar último equivale a contener todo lo que había terminado antes.

Esa suposición aparece cuando un mismo entorno recibe entregas desde más de un camino. Por ejemplo, una automatización publica una actualización común mientras otra despliega una personalización del sitio. Cada camino puede ser correcto por separado y aun así dejar una versión vieja si construye desde una base anterior.

El verde responde una pregunta demasiado chica

Un deploy exitoso demuestra que cierto código pudo construirse y publicarse. Según la plataforma, también puede demostrar que el proceso terminó y que una URL responde. No demuestra necesariamente que la versión publicada sea la que el equipo considera vigente.

Imaginá esta secuencia:

  1. El commit B agrega una corrección sobre A.
  2. Una automatización empieza a construir B.
  3. En paralelo, otro flujo parte de A, suma un cambio visual y construye C.
  4. El deploy de B termina primero.
  5. El deploy de C termina después y pasa a atender el tráfico.

Los dos builds pueden estar verdes. El problema es que C no contiene B. El último deploy no es la continuación del anterior: es otra rama de la historia.

Mirar solamente el estado del proveedor deja el conflicto invisible. Incluso una prueba superficial puede pasar si consulta una ruta que existe en ambas versiones.

La restricción importante está en el entorno, no en el pipeline

Es tentador revisar cada automatización por separado. ¿Construyó bien? ¿Usó las variables correctas? ¿Terminó el smoke test? Todas son preguntas necesarias, pero no alcanzan cuando varias automatizaciones escriben sobre el mismo destino.

El recurso compartido es el entorno de producción. Por eso hace falta una regla que cruce los caminos de entrega: la versión que queda sirviendo debe contener el cambio mínimo que esperamos encontrar.

Hay varias formas de imponerla:

  • serializar todos los despliegues que apuntan al mismo entorno;
  • cancelar builds viejos cuando aparece una versión más nueva;
  • construir siempre desde una referencia canónica actualizada;
  • publicar artefactos inmutables y promover uno ya verificado;
  • comprobar la versión servida después de cada despliegue.

Serializar reduce carreras, pero puede volver lenta una cola y no corrige una base equivocada. Cancelar ejecuciones obsoletas ayuda si el sistema conoce el orden deseado. Un artefacto inmutable ofrece una garantía más fuerte, aunque exige adaptar el proceso.

Cuando conviven flujos que todavía no pueden unificarse, la comprobación posterior es una defensa barata y explícita.

Consultar qué quedó sirviendo

La aplicación necesita exponer una identidad de versión que no dependa de mirar el panel del proveedor. Puede ser el SHA de Git incorporado durante el build, el identificador de un artefacto o una versión de release.

Un endpoint de salud podría devolver algo así:

{
  "status": "ok",
  "revision": "c4f7a2e"
}

La respuesta permite comparar el estado deseado con el observado. Si el repositorio conserva una historia compatible, Git puede comprobar si el commit esperado está incluido en la revisión desplegada:

git merge-base --is-ancestor "$EXPECTED_SHA" "$DEPLOYED_SHA"

El código de salida cero indica que la revisión servida contiene al commit esperado en su historia. Si la comprobación falla, no conviene declarar la entrega terminada aunque el deploy figure verde. Primero hay que reconstruir desde la base correcta o volver a desplegar la versión que reúne ambos cambios.

La relación de ancestro importa más que la igualdad. Exigir que ambos SHA sean idénticos produciría falsos avisos cada vez que una personalización válida agrega un commit después de la actualización común.

Convertir la versión en una condición de cierre

La comprobación sirve cuando forma parte del recorrido normal, no cuando alguien la recuerda después de una regresión.

Un cierre mínimo puede seguir esta secuencia:

  1. Registrar la revisión que el entorno debe contener.
  2. Esperar a que terminen todos los despliegues que estaban en curso para ese destino.
  3. Leer la revisión desde el entorno, no desde el último job observado.
  4. Comprobar la relación entre la revisión esperada y la servida.
  5. Ejecutar una prueba corta sobre el comportamiento cambiado.
  6. Recién entonces marcar la entrega como verificada.

El tercer paso evita otra confusión común: el job que acaba de terminar no siempre es el que atiende el tráfico. Puede haber promociones, alias, colas o un despliegue posterior que cambió el destino mientras mirabas la ejecución anterior.

También conviene guardar ambos identificadores en la evidencia del release. Ante un problema, esa pareja permite distinguir rápidamente entre una regresión del código actual y una versión anterior que volvió a quedar activa.

Lo que esta comprobación no garantiza

La ascendencia de commits funciona bien cuando el despliegue conserva la historia de Git. Con merges squash, cherry-picks, repositorios separados o código generado, un cambio puede estar presente sin que exista esa relación. En esos casos hace falta comparar un identificador de artefacto, un manifiesto de componentes o una versión firmada durante el build.

Tampoco alcanza con conocer el commit. La aplicación puede servir el código correcto con una migración pendiente, una configuración equivocada o una caché que todavía entrega otro comportamiento. La identidad de versión responde qué código quedó publicado; el smoke test responde una parte de cómo se comporta ese entorno. Son controles complementarios.

Y un endpoint de salud mal construido puede mentir. La revisión debe quedar fijada en el artefacto durante el build, no leerse de una variable mutable que otro proceso pueda cambiar sin reemplazar el código.

La pregunta útil después del verde

Cuando hay un solo pipeline lineal, “deploy exitoso” y “versión esperada en producción” suelen coincidir. En cuanto aparecen caminos paralelos, esa coincidencia deja de ser una garantía.

La pregunta de cierre ya no es “¿terminó el deploy?”, sino otra:

¿La versión que atiende ahora contiene todo lo que decidimos publicar?

Responderla con una revisión observable y una comprobación automática convierte una carrera silenciosa en un fallo detectable. El verde sigue siendo necesario. Simplemente deja de tener la última palabra.

SEGUÍ LA PUBLICACIÓN

LA PRÓXIMA
IDEA.

Sumá Space Monkeys a tu lector RSS. Cada artículo nuevo aparece ahí, listo para leer cuando tengas un rato.

Abrir el feed