Mil compilaciones al mes, y ninguna nos cuesta nada ⚙️
Primero, una corrección. La primera versión de este artículo afirmaba que se nos habían agotado los minutos de compilación de GitHub y que eso nos obligaba a pasar a una cuenta Pro. Era falso, y de una forma que un solo vistazo a la documentación habría aclarado: para los repositorios públicos, los minutos de compilación de GitHub son gratis. Los artefactos y las cachés, también. Nuestro repositorio es público desde finales de mayo, así que nunca hemos pagado un solo minuto ni lo haremos. En lugar de corregir el texto en silencio, preferimos reescribirlo y contarte lo que mostraron de verdad las mediciones. Y resulta que es mucho más interesante que la versión equivocada.
Primero adivinar, después mirar. Todo empezó una noche en la que un pull request terminado esperaba en el navegador y no se lanzaba ni una sola comprobación. Ninguna marca verde, solo silencio. Fuimos a por la explicación obvia («se acabó la cuota») y contratamos una cuenta Pro. Después todo volvió a funcionar, lo que parecía confirmar la teoría. Pero no: el silencio tenía otra causa (un pull request que GitHub no puede fusionar limpiamente con la rama principal en ese momento no inicia ninguna comprobación). Desde entonces hemos consultado los datos de facturación de cada ejecución. La respuesta, para cada ejecución y cada sistema operativo: tiempo facturable = 0 milisegundos. Apoyar una plataforma con una suscripción está perfectamente bien, pero como explicación para este repositorio no se sostiene.
Lo que sí es cierto: la maquinaria ha crecido. Cada pull request pone en marcha una pequeña fábrica: se compila todo el servidor y se ejecuta su batería de pruebas, el linter y el análisis de código le echan un vistazo, CodeQL busca agujeros de seguridad y se generan imágenes Docker para el servidor del juego, el portal, el WorldHost y el backend de IA. Una versión añade compilaciones del cliente para Windows, Linux y macOS, además de la versión WebGL para el juego en el navegador. Desde finales de mayo, eso suma 1723 ejecuciones de compilación, 1092 solo en julio, con 131 pull requests fusionados en cuatro semanas. Y sí, el aumento reciente tiene que ver de verdad con la IA 😉: el proyecto se desarrolla al 100 % con ayuda de IA, y con la suscripción más grande simplemente pasan más cosas en paralelo. Solo que la moneda no es el dinero, sino el tiempo de espera.
Adónde se va el tiempo de espera. Medido durante ocho días: la comprobación normal (CI), 379 minutos; el análisis de seguridad de CodeQL, 230; las compilaciones de versiones, 126; el resto son minucias. Una sola versión cuesta unos 110 minutos de cómputo, repartidos entre WebGL (31,6), la imagen Docker (19,4), macOS (13,7), Linux (13,7), la gran puerta de pruebas (12,1), Windows (10,9) y el empaquetado (7,2). Ese es el tiempo que pasa entre «terminado» y «listo para que lo instales».
Y ahora, lo que de verdad escasea: la caché. Para que una compilación no empiece de cero cada vez, GitHub guarda resultados intermedios, y para eso tienes 10 GB por repositorio, da igual lo público que seas. Ahora mismo, la nuestra ocupa 5,3 GB en 63 entradas. El problema es el reparto: más o menos dos tercios son capas intermedias de Docker que se vuelven a subir en cada ejecución, y desplazan justo lo que más ayudaría. Ese es el verdadero cuello de botella, y no hay suscripción en el mundo que te libre de él.
El hallazgo más bonito fue un bug de verdad. Al compilar, Unity crea una carpeta intermedia enorme (Library) cuya reutilización ahorra minutos. Al medir descubrimos que, para Windows, Linux y macOS, esa carpeta nunca se guardaba: las compilaciones intentaban restaurarla obedientemente, pero nadie la escribía nunca. Y la compilación de Windows era la única con una clave de caché sin marca de plataforma. Resultado: descargaba 1,7 GB de estado intermedio de WebGL, que Unity luego desechaba diligentemente antes de volver a importarlo todo. El registro lo muestra negro sobre blanco: 257 segundos de importación de assets en lugar de 85 en caliente. Son casi nueve minutos perdidos por versión, porque a una clave le faltaba una palabra.
Qué más apareció. Nuestra batería de pruebas se ejecuta tres veces por cada commit publicado (en el pull request, después de fusionar y otra vez en la versión). CodeQL revisa tres lenguajes en cada pull request, aunque ni siquiera es una comprobación obligatoria. Falta por completo una caché para los paquetes de .NET. Se configura un emulador para arquitecturas de procesador ajenas, aunque solo compilamos para una. Y 7,4 GB de artefactos de compilación antiguos siguen ahí con la retención estándar de 90 días. Nada de esto es dramático, pero todo junto suma un buen pedazo de vida.
La lección es la misma que nos enseñó nuestro servidor. Aquella vez medimos que la mitad de la memoria ocupada no iba al juego, sino a Docker y a la monitorización. Esta vez fue aún más vergonzoso: supusimos una factura que nunca existió y pagamos antes de mirar. Medir, no adivinar: por lo visto, esa frase sigue valiendo hasta que la interiorizas de verdad. La limpieza está planificada, pero todavía no está hecha; cuando esté en marcha, te contaremos qué nos ha aportado. 🚀
Comentarios