El bug de las 3 a.m.: por qué tu gestor de dependencias de JavaScript rompe la build en producción y cómo blindarlo
Son las 3:07 de la mañana. Tu móvil vibra en la mesita como si tuviera convulsiones. Mientras intentas recordar tu propio nombre, ves el mensaje: "La web está caída. Build rota en producción. Todos los semáforos en rojo."
Y tú, medio dormido, piensas lo mismo que pensamos todos en ese momento: "pero si ayer funcionaba".
Bienvenido al club. Esa sensación de que tu propio proyecto te ha traicionado mientras dormías es un rito de iniciación en el mundo del desarrollo. Y en el ecosistema de JavaScript, tiene un nombre propio: el bug de las 3 a.m. o, más técnicamente, "el día que npm install decidió arruinarte la vida".
Hoy te traigo un caso real (con nombres cambiados, que nadie quiere que le señalen con el dedo) de cómo un equipo se despertó con la build hecha pedazos, cómo lo diagnosticamos a las 3 de la mañana con más cafeína que neuronas, y qué hicimos para que no volviera a pasar. Spoiler: la culpa no era de nadie y era de todos a la vez.
El caso: una build que amaneció muerta
Imagínate una startup de esas que crecen rápido. Cinco developers, un pipeline de CI/CD que parecía sólido, despliegues automatizados y una sensación generalizada de "lo tenemos controlado". Spoiler número dos: no lo tenían controlado.
El lunes por la mañana, la build de producción decidió no compilar. Sin cambios en el código. Sin commits de madrugada. Sin nadie tocando nada. El mismo código que el viernes desplegaba sin rechistar ahora escupía errores como si le hubieran insultado.
El mensaje era tan críptico como siempre: algo sobre un módulo que no encontraba, una versión que no cuadraba y una dependencia transitiva que había decidido existir en una versión que no era la que esperaban. El clásico "no es tú, es el árbol de dependencias".
Y aquí viene la parte divertida: nadie había cambiado nada.
La investigación: cuando el culpable está a tres saltos de distancia
Lo primero que hicimos fue lo que todos hacemos al principio: mirar el último commit. Nada raro. Luego, revisar si alguien había tocado el package.json. Tampoco. Después, comprobar si el entorno de CI había cambiado. Nada de nada.
Hasta que alguien tuvo la idea brillante: comparar el lockfile de la build rota con el de la última build verde. Y ahí estaba, escondido entre cientos de líneas, el culpable.
Una dependencia de una dependencia de una dependencia (sí, tres niveles) había publicado una versión nueva. Los mantenedores de esa librería habían hecho un cambio en un patch —esos que en teoría nunca rompen nada— que alteraba ligeramente cómo se resolvían ciertas importaciones. Y nuestra build, que dependía de esa librería sin saberlo, se fue al carajo.
Lo mejor de todo: la librería en cuestión ni siquiera estaba en nuestro package.json. La habíamos heredado de una herramienta de testing, que la usaba para algo completamente distinto. Es como descubrir que tu casa se ha inundado porque el vecino del quinto dejó el grifo abierto.
Los pasos que tomamos (y que deberías copiar)
Aquí es donde la historia se pone útil. Porque una cosa es reírte del desastre y otra es evitar el siguiente. Esto es lo que hicimos, en orden, y lo que recomiendo que hagas tú también:
-
Congelamos el lockfile. Lo primero fue asegurarnos de que el archivo de bloqueo estuviera versionado y que el CI lo respetara religiosamente. Si tu pipeline hace
installsin mirar el lockfile, estás jugando a la ruleta rusa con tu producción. Punto. -
Fijamos versiones exactas de las dependencias críticas. Adiós a los
^y a los~en las dependencias que tocan el núcleo del proyecto. Sí, pierdes actualizaciones automáticas. No, no te importa, porque prefieres dormir. -
Añadimos un paso de auditoría del árbol de dependencias. Antes de cada build, un script revisa qué ha cambiado en las dependencias transitivas. Si algo se movió sin que nosotros lo pidiéramos, salta la alarma. No evita el problema, pero te avisa antes de que llegue a producción.
-
Separamos los entornos de desarrollo y producción. Hasta ese momento, ambos usaban las mismas versiones flotantes. Ahora producción usa versiones fijas y desarrollo puede seguir jugando con lo último. Cada uno en su casa y Dios en la de todos.
-
Documentamos el incidente. Un post-mortem sin culpables, con lo que pasó, por qué pasó y qué cambiamos. Porque el conocimiento que no se escribe se pierde, y el próximo que llegue al equipo merece no repetir nuestra noche en vela.
La lección: las dependencias no son gratuitas
Aquí va mi opinión, y la digo bien alta: el ecosistema de JavaScript tiene un problema de confianza estructural. Instalamos paquetes como quien coge caramelos de un bol sin mirar. Confiamos en que un patch no rompa nada, en que el mantenedor de una librería que usan millones de personas tenga un mal día y no lo note, en que nuestro árbol de dependencias sea un jardín ordenado cuando en realidad es una selva amazónica.
Y no, no es culpa de los mantenedores. La mayoría son gente generosa regalando su tiempo. La culpa es nuestra, por construir castillos sobre cimientos que no controlamos y luego sorprendernos cuando tiemblan.
El bug de las 3 a.m. no es un bug. Es un síntoma. Es la factura que llega por haber ignorado durante meses que tu proyecto depende de código que no ves, escrito por gente que no conoces, actualizado cuando a ellos les apetece.
El blindaje real: cultura, no solo herramientas
Podría llenarte esto de herramientas y comandos, pero te voy a ser honesta: la herramienta es lo de menos. Lo que de verdad blinda tu build es una cultura de control de versiones explícito, auditoría periódica y desconfianza sana.
Trata tus dependencias como tratarías a un compañero nuevo: con respeto, pero revisando su trabajo antes de darle las llaves de producción. Fija lo que es crítico, audita lo que se mueve, documenta lo que aprendes y automatiza lo que puedas.
Porque a las 3 de la mañana nadie quiere estar despierto. Y tu móvil, sinceramente, también merece descansar.
Así que te pregunto: ¿sabes exactamente qué hay en tu árbol de dependencias ahora mismo? ¿O prefieres descubrirlo la próxima vez que vibre el móvil a las 3:07?
Cuéntamelo en los comentarios. Yo, mientras tanto, voy a revisar mi lockfile. Por si acaso.
Comentarios
Deja un comentario