~/blog $ git show 2026-09-08
I Shipped Two Days Early and Skipped the Test Plan
· 5 min read · Victor Benavides
--ops--craftLa semana pasada publiqué aquí un post sobre disciplina de releases. Un congelamiento unos días antes. Un plan de pruebas escrito. Un sábado entero recorriéndolo con dispositivos reales y cuentas reales. Una lista de unas treinta y cinco casillas la noche del release.
Lo que ese post no mencionó — porque todavía no había terminado de asimilarlo — es que el release inmediatamente anterior salió dos días antes, sin el recorrido humano. Cuarenta y ocho casos escritos. Ninguno ejecutado por una persona.
Así que antes que nada: el post decía la verdad sobre el proceso y se quedó callado sobre la excepción, y la excepción era mía.
Qué cambié por qué
El release era grande — veintitrés repositorios, cuatro servicios llegando a producción por primera vez, siete migraciones de base de datos. Estaba listo el sábado, las suites automáticas estaban en verde, y lo saqué en vez de sentarme encima hasta el lunes.
Los cuarenta y ocho casos se movieron al siguiente release. Están registrados, asignados, y se van a recorrer. Pero "se van a recorrer" es una promesa sobre el futuro, y mientras tanto hay flujos en producción que ningún humano completó nunca de punta a punta.
Quiero ser exacto con el razonamiento, porque "andábamos apurados" no es el motivo. Esa plataforma todavía no tiene clientes en producción. El costo de un defecto ahora mismo es mi noche y un redespliegue — no el negocio de alguien más. Esa es una razón real y defendible para aceptar el intercambio, y la registré como un intercambio en lugar de fingir que el release estaba completamente probado.
También es una razón con fecha de vencimiento, y yo podía ver la fecha desde donde estaba parado.
Lo que la suite automática no me puede decir
Escribí hace unas semanas que las pruebas corren en un mundo sin cuerpos, sin tiempo y sin otras personas. Saltarme el recorrido humano es el argumento de ese ensayo apuntado directo a mi propio pie.
Las suites demostraron que el código hace lo que yo creo que hace. No me pueden decir si una persona puede completar una tarea — si el flujo tiene sentido, si la pantalla después de la pantalla es la correcta, si un dispositivo en una mano hace lo que hace un dispositivo en un runner de CI. Nada en un pipeline verde me ha dicho eso jamás.
Después el release me enseñó seis cosas
Aquí está la parte que hizo que esto valiera la pena escribirlo y no solo confesarlo.
Ejecutar el release encontró seis defectos en mi propio runbook — el documento que existe justamente para que la noche sea aburrida. Todos eran invisibles leyéndolo.
Uno. La herramienta de infraestructura se aplica automáticamente al hacer merge. Mi runbook lo documentaba como un disparo manual que yo activaría deliberadamente. Hacer merge de la promoción arrancó un apply en producción que nadie pidió. Falló únicamente porque otro plan todavía tenía tomado el lock del estado — es decir, lo detuvo la suerte, no el diseño.
Dos. La lista de repositorios que necesitaban actualizar una dependencia decía diez. Eran trece. Un pin desactualizado compila en verde y despacha un contrato viejo, que es la forma más silenciosa de estar mal.
Tres. El comando documentado para actualizar esos pines era un push directo a una rama protegida. No puede funcionar. Nunca funcionó. Ahí estaba en el documento, con toda autoridad.
Cuatro. Seis repositorios necesitaban un back-merge antes de poder promoverse siquiera — sus solicitudes de promoción abrían en conflicto por los pines de dependencias. Nada de eso estaba en el plan.
Cinco. Un servicio que se desplegaba por primera vez falló sin más señal que un timeout, porque un secreto de configuración existía en el vault de un entorno y no en el del otro. El despliegue después se revirtió limpiamente solo, lo que borró la evidencia antes de que yo pudiera mirarla. Una falla prolija que destruye su propia escena del crimen es peor que una desprolija.
Seis. Otro servicio primerizo necesitaba un registro DNS que no existía. Eso bloquea lo obvio, y además bloquea silenciosamente la emisión del certificado, así que te quedan dos fallas que parecen no tener relación y una sola causa.
Qué creo que significa esto
Un runbook que no ejecutaste no es un runbook. Es una hipótesis sobre lo que va a pasar, escrita por alguien que todavía no estuvo ahí.
El mío estaba escrito con cuidado, por mí, sobre sistemas que yo construí — y estaba equivocado en seis lugares, cuatro de los cuales habrían frenado el release en seco. No equivocado por descuido. Equivocado porque escribir lo que crees que pasa y averiguar lo que pasa son actividades distintas, y solo una está disponible desde un escritorio.
Los seis ya están corregidos en el documento. Ese es el retorno real de una noche difícil: no que salió bien, sino que la próxima arranca desde un documento con seis mentiras menos.
Qué haría distinto
No salir antes de tiempo. O más precisamente: no dejar que "listo" y "probado" se colapsen entre sí como lo hacen "integrado" y "desplegado", cosa sobre la que ya escribí y aparentemente todavía necesito aprender.
El release estaba listo en el sentido de que el código estaba terminado y las máquinas estaban de acuerdo. No estaba probado en el sentido de que una persona hubiera confirmado que alguien puede usarlo. Son estados distintos y yo tenía nombres para ellos, lo que lo empeora en vez de mejorarlo.
Escribir sobre disciplina es fácil y barato. La prueba de fuego es la semana en que quieres saltártela — y el mes pasado, me la salté.