Poner fin al dolor: Repensando CI para Monorepos Grandes

Rate this content
Bookmark

Escalar bases de código grandes, especialmente monorepos, puede ser una pesadilla en los sistemas de Integración Continua (CI). El panorama actual de las herramientas de CI tiende a ser orientado a máquinas, de bajo nivel y exigente en términos de mantenimiento. Lo peor es que a menudo están desconectadas de las necesidades y el flujo de trabajo real del desarrollador.

¿Por qué es un obstáculo el CI? Porque los sistemas de CI actuales son comodines, sin una comprensión específica de tu base de código. No pueden aprovechar el contexto en el que operan para ofrecer optimizaciones.

En esta charla, exploraremos el futuro del CI, diseñado específicamente para bases de código grandes y monorepos. Imagina un sistema de CI que comprenda la estructura de tu espacio de trabajo, paralelice dinámicamente las tareas en máquinas utilizando datos históricos, y haga todo esto con una configuración mínima y de alto nivel. Repensemos el CI, haciéndolo más inteligente, eficiente y alineado con las necesidades del desarrollador.

25 min
15 Nov, 2023

Comments

Sign in or register to post your comment.

Video Summary and Transcription

La charla de hoy analiza la reevaluación del CI en monorepos, con un enfoque en aprovechar el gráfico implícito de dependencias de proyectos para optimizar los tiempos de compilación y gestionar la complejidad. Se destaca el uso de NX Replay y NX Agents como una forma de mejorar la eficiencia del CI mediante el almacenamiento en caché de cálculos anteriores y la distribución de tareas en múltiples máquinas. Se discuten la distribución detallada y la detección de fallas como métodos para mejorar la eficiencia de la distribución y garantizar una configuración limpia. Habilitar la distribución con NX Agents simplifica el proceso de configuración, y NX Cloud ofrece escalabilidad dinámica y reducción de costos. En general, la charla explora estrategias para mejorar la escalabilidad y eficiencia de los flujos de CI en monorepos.

Available in English

1. Introducción a Repensar CI en Monorepos

Short description:

Hoy, me gustaría hablar sobre cómo podríamos repensar cómo funciona CI en monorepos. Mi nombre es Joris Sturmfloner y he estado utilizando monorepos durante seis años. También soy miembro del equipo principal de NX y un experto desarrollador de Google en tecnologías web y Angular.

[♪ música tocando ♪ Muy bien. Hoy me gustaría hablar un poco sobre cómo podríamos repensar cómo funciona CI en comparación con la situación actual de CI que tenemos, con un enfoque particular en monorepos y monorepos grandes potencialmente. Cómo podríamos optimizar eso. Antes de continuar, mi nombre es Joris Sturmfloner. He estado utilizando monorepos durante probablemente seis años. Desde hace unos cuatro años, también soy miembro del equipo principal de NX, que es una herramienta de gestión de monorepos. Y también soy un experto desarrollador de Google en tecnologías web y Angular y también soy instructor en AgHead, donde publico cursos sobre desarrollo web y herramientas para desarrolladores.

2. Consideraciones para CI en Monorepos

Short description:

Al trabajar con monorepos, debemos considerar la experiencia local del desarrollador, la automatización y las reglas, y los pipelines de tareas. Las soluciones de CI actuales no están optimizadas para monorepos y requieren un mantenimiento manual a nivel bajo. Los desarrolladores desean una forma de definir su estructura de CI a alto nivel y necesitan estrategias para garantizar la escalabilidad y la velocidad y el rendimiento manejables.

Entonces, cuando nos adentramos en la dirección de un monorepo, no es gratuito, ¿verdad? Hay algunas consideraciones que deben tenerse en cuenta. Una de las más importantes es, obviamente, la experiencia local del desarrollador. ¿Cómo estructuramos un proyecto en un monorepo? ¿Cómo nos aseguramos de tener consistencia en cómo se configuran estos productos? ¿Qué versión utilizan? ¿Cómo se configuran de manera que también podamos tener cierta movilidad entre proyectos, potencialmente, y también nos ayude a mantenerlos? La automatización y las reglas en torno a esos proyectos también son una parte muy importante, especialmente en lo que respecta al mantenimiento y la longevidad de dicho monorepo.

También cosas como características de los pipelines de tareas, poder ejecutar cosas en paralelo. Porque claramente en un monorepo, ya no ejecutamos solo un proyecto, sino potencialmente una serie de proyectos donde también hay dependencias. Y por lo tanto, necesitamos poder construir productos dependientes primero antes de ejecutar nuestro proyecto. Y esas son cosas que no queremos hacer manualmente, sino que queremos tener soporte de herramientas. Pero hoy me gustaría centrarme específicamente en el elefante en la habitación cuando hablamos de monorepos, que a menudo no se le presta atención de inmediato, lo cual es un error, que es CI. Porque claramente hay algo: la situación actual de CI no está optimizada para monorepos porque está muy orientada a la máquina, por lo que debemos centrarnos en instrucciones exactas que queremos procesar. Necesitamos tener un enfoque muy instructivo. También es muy detallado en ese sentido. Requiere mucho mantenimiento porque, como mencioné, ya no ejecutamos solo un proyecto y ya está. Ejecutamos una serie de proyectos. Ejecutamos múltiples proyectos. Y por lo tanto, necesitamos tener estrategias para ajustar el CI para asegurarnos de que incluso cuando cambia la estructura de nuestro monorepo, cuando se agregan más productos al monorepo, siga funcionando. También diría que está un poco alejado de lo que los desarrolladores desean, porque como desarrollador, me gustaría tener una forma más a alto nivel de definir mi estructura de CI, mi ejecución de CI, mi pipeline de CI, en el sentido de decir, hey, quiero ejecutar todos estos proyectos que se han modificado, por ejemplo, en ese PR, en lugar de tener que ajustar cada aspecto de ese proyecto. Y como dije antes, realmente no funcionan para monorepos, están diseñados para ser mucho más generales y para espacios de trabajo de proyectos individuales en general. Así que hoy me gustaría adentrarme en algunos de estos aspectos, específicamente en lo que respecta a la velocidad y el rendimiento, porque eso es algo importante en lo que debemos prestar atención, porque de lo contrario nuestro monorepo sería un problema. Porque si tenemos una buena colaboración local dentro de los equipos, pero nuestro pipeline tarda más de una hora en cada PR, eso será un problema.

3. Gestión de la Complejidad y Mantenibilidad en CI

Short description:

Para mantener una CI compleja y mantenible en monorepos, es clave aprovechar el grafo implícito de las dependencias del proyecto. Al paralelizar las ejecuciones y utilizar un pipeline de tareas, podemos optimizar los tiempos de construcción y tener en cuenta las dependencias entre proyectos. Además, al ejecutar nodos afectados, podemos probar y construir selectivamente proyectos ascendentes. Estas consideraciones son cruciales para una configuración de CI eficiente y escalable.

Y también, al analizar el aspecto de la complejidad y mantenibilidad, porque claramente, como mencioné antes, no queremos tener que hacer todas las ejecuciones en paralelo, iniciar manualmente máquinas, cosas así. Así que quiero explorar un enfoque potencialmente diferente que podría ayudar con esa complejidad y mantenibilidad. Esto es bastante obvio, ¿verdad? Si tenemos más proyectos en un solo repositorio, este tiempo de CI se sumará, porque ahora no solo necesitamos construir, probar, hacer linting y ejecutar pruebas de extremo a extremo para un proyecto, sino que ahora tenemos cinco, diez, cien, que fácilmente pueden ser un número considerable. He estado trabajando con clientes que tienen más de 600 productos en un solo monorepo. Y por lo tanto, estamos hablando potencialmente de tamaños como esos.

Como mencioné antes, si no prestamos atención al aspecto de CI en un monorepo, podríamos encontrarnos con congestión básicamente. Y obtenemos resultados como estos, que básicamente no son manejables porque los desarrolladores encontrarán soluciones alternativas. Como necesitan enviar, tienen un sprint en marcha donde necesitan entregar ciertas características. Y si cada ejecución de PR lleva más de una hora, comienzan a agrupar PR en uno solo, agrupando características en un solo PR. Y luego tenemos esos cambios masivos de más de 200 archivos, que son imposibles de revisar. Y, por lo tanto, la calidad obviamente se ve afectada en gran medida.

Entonces, lo que queremos tener es algo como esto, obviamente. Queremos mantener eso lo más bajo posible y mantenerlo casi plano, idealmente, y no algo que crezca exponencialmente con más y más productos que tenemos en nuestro monorepo. ¿Cómo lo hacemos? Una de las cosas fundamentales que tiene cada monorepo de alguna manera implícita detrás de escena es un grafo. Los proyectos en un monorepo se referencian entre sí. Eso puede ser a través de un mecanismo de resolución de dependencias, dependiendo de la herramienta que estés utilizando, pero también puede ser simplemente la referencia en un package JSON, donde se referencia la fuente del otro paquete en el que dependes. Por lo tanto, hay un grafo que se construye en un monorepo, que refleja las dependencias.

Y podemos aprovechar esa información del grafo, diciendo cosas como si ejecutas la construcción para este producto, o sirves este producto si es una aplicación, por ejemplo, podemos mirar la configuración de tu monorepo y decir, potencialmente también necesitamos construir primero sus hijos dependientes, porque eso podría ser una dependencia y una entrada para que ese otro producto se ejecute realmente, porque esos deben construirse primero. Y esas son cosas que podemos especificar, generalmente para las cuales necesitamos una herramienta para no tener que configurar manualmente eso y cambiarlo a medida que cambia la estructura. Y por lo tanto, claramente no queremos tener cosas como estas, sino que queremos tener una ejecución paralela tanto como sea posible para ahorrar tiempo. Y nuevamente, como puedes ver aquí, tener en cuenta estas dependencias potenciales que existen entre proyectos, donde esto puede depender de la salida del anterior, como acabas de ver. Y por lo tanto, necesitamos tener un mecanismo lo suficientemente inteligente que, cuando realiza tal paralelización, también tenga en cuenta esas cosas, que generalmente se refiere como un pipeline de tareas, donde podemos definir de manera bastante sencilla cómo se ven estas dependencias, aprovechando también el grafo detrás de escena. Y esto es algo que, por ejemplo, hacemos en NX, porque es algo básico que necesitas tener en un monorepo.

Otra cosa es poder ejecutar solo nodos afectados en CI, pero también localmente. Con nodos afectados, me refiero básicamente a que si cambias un producto aquí en el medio, podemos inferir que potencialmente necesitamos ejecutar las pruebas, construir y ejecutar pruebas de tendencia, también de estos proyectos ascendentes, porque dependen de ese producto que hemos cambiado. Y potencialmente podríamos necesitar volver a ejecutar porque tal vez introducimos algún cambio que rompe y ya no se construyen o las pruebas ya no pasan. Por lo tanto, necesitamos ajustar eso. Y con un mecanismo así, que llamamos afectado, porque es literalmente un comando que puedes ejecutar, NX afectado, y luego le das un objetivo para el cual quieres calcular esos nodos afectados. Eso nos da la capacidad de crear o ejecutar solo un subconjunto de la cantidad total de proyectos que podríamos tener en un monorepo en nuestro sistema de CI. Y por lo tanto, ya puedes ver que estas son consideraciones que deberían tenerse en cuenta en nuestra configuración de CI para asegurarnos de que esa curva que hemos visto antes se mantenga lo más baja posible.

4. Optimización de CI con NX Replay y NX Agents

Short description:

NX Replay es un mecanismo de almacenamiento en caché distribuido y remoto que optimiza los cálculos almacenando y reproduciendo los resultados de cálculos anteriores. Esta función, junto con NX Agents, mejora la eficiencia de los pipelines de CI en monorepos. Al aprovechar los resultados de caché y volver a calcular selectivamente los nodos afectados, podemos acelerar significativamente el proceso de CI. Además, al cambiar un nodo con muchos proyectos dependientes, como un sistema de diseño o bibliotecas de autenticación, el cálculo puede optimizarse aún más.

En general, lo que hemos descubierto, al trabajar mucho con empresas y grandes monorepos, son estos tres aspectos. Como los que acabamos de ver como la paralelización y los afectados. Esos son requisitos previos, pero los que realmente marcan la diferencia son estos tres aproximadamente. Ahora, estos también son términos de marketing. Así que no te distraigas con eso, pero básicamente son esas tres características mientras que NX workflows es algo que vendrá más adelante. Así que nos estamos centrando en NX Replay y NX Agents.

Entonces, lo que es NX Replay, es básicamente una caché de cálculos. Ahora lo llamamos Replay. Dije, como, es un término de marketing si quieres, pero básicamente es un almacenamiento en caché remoto distribuido que puedes agregar a tus proyectos. Y Replay, por lo tanto, porque literalmente reemplaza el cálculo. Es decir, si tienes un proyecto, calculará una clave hash a partir de varias fuentes. Eso incluye el código fuente en sí, variables de entorno, cosas como variablesruntime que también puedes incluir en esa clave. Y luego calcula una clave y almacena el resultado junto con esa clave. Y así, si ejecutamos otro cálculo nuevamente y tenemos una clave coincidente, restauraremos y reproduciremos tanto la salida en la terminal como los artefactos. Porque claramente algunos de los comandos, algunas de las tareas pueden producir archivos JavaScript compilados o archivos CSS u otro tipo de procesamiento que estés realizando. Y esos también se reproducen. Y por eso se llama NX Replay. Y esto es muy valioso porque si volvemos a mirar nuestra situación de afectados, donde cambiamos el nodo en el medio, lo enviamos como PR a nuestro repositorio, nuestro pipeline se ejecuta, identifica estos son los nodos afectados. Pero ¿qué sucede durante el procesamiento, ahora uno de los proyectos ascendentes falla las pruebas porque como dijimos antes, hemos cambiado algo, las pruebas ya no pasan. Necesitamos arreglarlo. Entonces, lo que hacemos nuevamente, descargamos ese PR, lo arreglamos, lo enviamos nuevamente. Ahora, si solo tuviéramos afectados, tendríamos que volver a ejecutar todos estos nodos. Pero si lo piensas, no tiene sentido calcular algunos de ellos porque literalmente no han cambiado. Por lo tanto, eso forma parte del grafo ahora más pequeño, el grafo de los afectados no se ve afectado porque se extraerá de la caché ya que tenemos una clave de caché coincidente que podemos reproducir ahora. Y solo nos quedan otros dos proyectos que están aquí, como puedes ver aquí con el reloj de arena, que deben volver a calcularse. Como puedes ver, podemos limitar aún más ese camino y hacerlo aún más rápido. Y obviamente, a medida que más miembros del equipo trabajen en nuestros proyectos, obtendremos más resultados de caché naturalmente. Y por lo tanto, nuestras PRs podrían ser más rápidas. Ahora, otro punto es, ¿qué sucede si ocurren esos escenarios más extremos, donde cambiamos un nodo que simplemente, tiene muchos proyectos dependientes, porque es una parte central.

5. Distribución de tareas con NX Agents

Short description:

Cuando se trata de proyectos que tienen muchos proyectos dependientes, como sistemas de diseño o bibliotecas de autenticación, distribuir tareas en múltiples máquinas puede mejorar la eficiencia. Sin embargo, la distribución manual puede ser desafiante debido a las diferentes duraciones de las tareas y la necesidad de ajustar el número de máquinas. Los scripts personalizados pueden ayudar a distribuir tareas, pero requieren mantenimiento y no se adaptan bien a las estructuras de proyectos cambiantes. Para abordar estas dificultades, se han desarrollado los NX agents para distribuir tareas de forma dinámica en función de los datos históricos y el grafo del proyecto. Con los NX agents, describes qué tareas ejecutar sin especificar cómo se distribuyen. Además, los NX agents ofrecen escalado dinámico, distribución detallada y rerun automático de tareas inestables. Al activar la distribución con un comando sencillo, las tareas se pueden distribuir en múltiples máquinas, mejorando la eficiencia de los pipelines de CI.

Podría ser, por ejemplo, un design system, que es uno común, pero también algunas bibliotecas de lógica de authentication o cosas así, donde muchos de nuestros proyectos dependen de ello. Y si lo cambiamos, a menudo nos encontramos con un escenario de peor caso donde los proyectos defectuosos son casi todo el grafo, porque todo el proyecto depende de eso. Por lo tanto, lo que se hace generalmente es distribuir. En lugar de simplemente paralelizar las cosas tanto como sea posible en la misma máquina, lo que intentamos hacer es distribuirlos en diferentes máquinas.

Entonces aquí puedes ver, distribuirlos en la máquina uno, máquina dos, máquina tres. Lo que puedes ver aquí, sin embargo, es que es una distribución muy uniforme, ¿verdad? Y eso es lo que generalmente sucede si lo configuras manualmente. Porque la distribución es difícil, porque necesitas codificarla de alguna manera. Y una forma muy directa, potencialmente ingenua de hacerlo es simplemente dividirlo por las diferentes tareas que tienes y luego ejecutarlo en diferentes máquinas.

Entonces aquí puedes ver, los diferentes tiempos de ejecución pueden llevar potencialmente a una baja eficiencia, porque algunas tareas pueden llevar mucho tiempo, y por lo tanto, la ejecución completa lleva más tiempo, pero otras máquinas ya están inactivas, porque su tarea, digamos el linting, fue más rápido, y ya han terminado. También el número de máquinas es estático. Por lo general, defines el número de máquinas, y eso es básicamente el número que está fijo allí. Y necesitas ajustarlo con el tiempo a medida que la estructura de tu monorepo obviamente se vuelve más grande y crece. Y también hay complejidad potencialmente en la puesta en marcha de esas máquinas, dependiendo de tu proyecto o proveedor de CI que estés utilizando.

Muy a menudo veo scripts que se hacen en CI. Por ejemplo, NX tiene una API programática, por lo que puedes calcular esos nodos afectados programáticamente, y luego intentar mezclarlos de alguna forma inteligente, donde los distribuyes en diferentes máquinas e incluso generas pipelines dinámicamente. Este es un ejemplo para GitLab, que te permite crear nodos dinámicamente, y así tener algún tipo de distribución. Pero es algo muy estático como puedes ver, porque está codificado en tu código, y no puede adaptarse realmente a una estructura de monorepo cambiante. Por lo tanto, esto requiere mucho mantenimiento.

Después de ver algunas de estas dificultades que enfrentan los equipos al crear estos scripts personalizados, hemos estado investigando lo que llamamos NX agents, básicamente para ayudar con esa distribución, específicamente para configurar las máquinas, pero también con la dinamicidad de la distribución en sí, para que no necesites ajustarlo continuamente a medida que tu estructura de monorepo crece, sino que la distribución se produciría dinámicamente en función del número de tareas que se ejecutan, pero también en función del tiempo de ejecución de estas tareas basado en datos históricos básicamente.

Por lo tanto, los NX agents intentan aprovechar el grafo del proyecto, porque tienen acceso al grafo NX en segundo plano, y por lo tanto, saben cómo se estructuran los proyectos, qué dependencias hay, lo cual es un punto importante cuando se distribuye, como distribuirlos de manera eficiente. Y describes qué quieres ejecutar, no cómo quieres ejecutarlos, sino que simplemente dices, quiero ejecutar la tarea afectada de construcción y linting, y las tareas de extremo a extremo de una cierta manera, pero no defines cómo se distribuyen.

Y una gran parte que viene con la primera versión de los NX agents es todo el aspecto de escalado dinámico, por lo que se generan más máquinas según el PR, pero también la distribución detallada y también la rerun automática de tareas inestables. Ahora, nos hemos centrado específicamente en las pruebas y las pruebas de extremo a extremo en este momento, pero en teoría, podemos detectar tareas inestables y volver a ejecutarlas automáticamente en CI. Así que echemos un vistazo. ¿Cómo se ve la descripción de lo que se ejecuta? Bueno, todo lo que necesitas hacer básicamente para activar la distribución es esta línea. Específicamente el dash-dash distributes on, donde proporcionas la información, quiero distribuir mis tareas que se ejecutan justo después en 15 máquinas, en este caso, de la nota Linux Medium plus JS. Y esos son nombres de máquinas basados en ciertas características, que obviamente puedes definir según las necesidades que tengas. Es algo así como una configuración de Docker casi. Y luego ejecutas los comandos reales. Y aquí puedes ver cómo describes qué ejecutar y no cómo.

6. Habilitando la distribución con NX Agents

Short description:

Habilitar la distribución con NX Agents aprovecha la información del grafo del proyecto para dividir las tareas en tareas más detalladas, que luego se distribuyen en las máquinas especificadas. La máquina coordinadora en la infraestructura de NX Cloud se encarga de la distribución, permitiendo un equilibrio y escalabilidad automáticos. Esta infraestructura también se puede alojar en las instalaciones. En tu CI, defines la distribución, mientras que la infraestructura en la nube se encarga de la gestión.

Simplemente habilitamos la distribución, tantas máquinas, estos son los comandos. Eso es todo, ¿verdad? Y lo que sucede es que se aprovecha la información del grafo del proyecto, que está disponible en CI. Activas ese script, como acabamos de ver, donde ejecutas la construcción afectada con la distribución activada. Eso se pasa a una máquina coordinadora, que se encuentra en la infraestructura de NX Cloud, y luego divide esas tareas y las distribuye en tareas más detalladas, que luego se distribuyen en el número de máquinas que especificaste.

Y la parte interesante es que si vemos que necesitamos más máquinas, podemos agregar algunas o incluso expandirlas dinámicamente, pero no tenemos que cambiar la configuración real subyacente. Y eso ayuda mucho con la sobrecarga de configuración o la complejidad que mencionamos inicialmente, porque ahora esto se puede equilibrar automáticamente. Es como si el coordinador ahora tuviera cuatro máquinas, mientras que toda la distribución ahora puede ocurrir en un enfoque diferente, en un enfoque potencialmente más eficiente. Y como dije, esto se aloja en la infraestructura de NX Cloud, que también puede estar en las instalaciones. Entonces, si necesitas tenerlo en las instalaciones, obviamente también funciona. Pero la parte principal aquí es que en tu CI, solo defines la distribución y la inicias, pero en la parte de la nube, básicamente se gestiona toda la infraestructura.

7. Distribución Detallada y Detección de Inestabilidad

Short description:

La distribución detallada permite dividir las pruebas de extremo a extremo en ejecuciones de prueba individuales a nivel de archivo, mejorando la eficiencia de la distribución y equilibrando las máquinas. NX puede crear automáticamente objetivos para cada archivo, lo que permite ejecutar pruebas a nivel de archivo. Un ejemplo concreto muestra cómo NX distribuye las pruebas de extremo a extremo en diferentes agentes, reduciendo el tiempo de ejecución de 90 minutos a 10 minutos. La detección de inestabilidad detecta y vuelve a ejecutar tareas inestables en diferentes máquinas para garantizar una configuración limpia.

Entonces, ¿cómo se ve la distribución detallada? Bueno, básicamente una de las grandes preocupaciones que a menudo tenemos es esa máquina en el medio. Así es, esa prueba de extremo a extremo, el bloque rojo que puedes ver, porque muy a menudo lo que sucede, es que tienes esas enormes pruebas de Cypress o Playwright que se ejecutan para una aplicación determinada, y son muy difíciles de dividir porque es solo un gran bloque, y ocupan una máquina completa, lo que puede llevar a que toda la distribución no sea eficiente.

Entonces, investigamos esto con una función que se implementará en NX 18, que nos permite dividir dinámicamente, crear dinámicamente tareas para objetivos, básicamente para una prueba de extremo a extremo a nivel de archivo, porque tanto Cypress como Playwright te permiten ejecutar archivos individuales con un filtro. Y así, NX puede hacerlo automáticamente con el resultado de que podemos dividirlos en ejecuciones de prueba a nivel de archivo individuales. Y así podemos agruparlos de manera inteligente, y ahora tenemos piezas mucho más detalladas que podemos distribuir, y así podemos equilibrar mejor las máquinas, y por lo tanto obtener mejores resultados.

Si observamos un ejemplo concreto, aquí hay un espacio de trabajo, un espacio de trabajo NX, con un par de aplicaciones Next.js con pruebas de extremo a extremo de Cypress, y aquí tengo algunas pruebas que son muy similares, que tienen algunas esperas aquí, algunas esperas para aumentar artificialmente o aumentar su tiempo de ejecución. También tengo instalado NX Console, y eso me permite ver qué objetivos se están definiendo para un proyecto así. Y así, si hago clic en ese enlace aquí, podemos ver que tenemos una prueba de extremo a extremo, pero NX detecta automáticamente que esta es una prueba de extremo a extremo de Cypress, y por archivo nos da básicamente un objetivo que se crea dinámicamente.

Y eso significa que ahora podemos no solo ejecutar toda la prueba de extremo a extremo, sino que también podemos ejecutar cada archivo individual automáticamente. Y esto es lo que NX hará a nivel de CI. Entonces, si hago aquí algunos cambios en esas páginas de la tripulación aquí, digamos que decimos aquí, HideArea3, y hagamos lo mismo aquí para el simulador de vuelo, solo para tener algunos cambios que están sucediendo aquí para que nuestras pruebas cambien. Y ahora, si agrego eso y lo subo a CI nuevamente, una vez que se haya subido, lo que sucederá es que CI ejecutará mi script aquí.

Y si observamos el script, esto ha sido generado automáticamente por NX. Hemos habilitado la distribución aquí con la distribución en cinco máquinas Linux por ahora. Entonces, este es un número estático de máquinas en las que estoy ejecutando la distribución. Y lo que quiero ejecutar es, en primer lugar, todas las pruebas y construcciones, y luego el extremo a extremo-CI, que son las piezas de CI distribuidas de manera detallada que puedo ejecutar en CI. Ahora aquí tengo solo el runMany, así que quiero ejecutar todos ellos. Entonces, si voy a mi repositorio aquí, puedes ver aquí la ejecución que se está iniciando. Así que ahora se está ejecutando la prueba de extremo a extremo.

Y si voy a la página de CI para NX Cloud, vemos que hay una ejecución de pipeline en progreso, que ahora ya distribuye esas pruebas de extremo a extremo en diferentes agentes. Entonces, puedes ver que ahora se está ejecutando una prueba por agente. Y esto depende en gran medida de cuántos agentes tenemos disponibles y cómo se está realizando la distribución aquí. También puedes ver que algunas cosas ya se han completado, y aquí puedes ver cómo se apilaron y cómo se está realizando esa distribución. Pero la parte importante aquí es que con un simple indicador, ahora distribuimos todas estas tareas en estas diferentes máquinas disponibles. Y hemos visto algunos ejemplos donde hemos pasado de una ejecución de extremo a extremo de 90 minutos en CI a 10 minutos solo con una distribución más detallada mediante los agentes de NX. De manera similar, podemos realizar la detección de inestabilidad porque podemos comprender según la caché si hay algunas tareas inestables que tienen, básicamente, si tienes una prueba ejecutándose en CI que se ha ejecutado antes con una determinada clave hash, y encontramos esa clave hash nuevamente en algún momento, pero ahora da un resultado diferente. Sabemos que podemos detectar esto y saber con certeza que son inestables. Y así podemos básicamente iniciarlos y moverlos a una máquina diferente solo para asegurarnos de tener una configuración limpia, una fase de inicio limpia y volver a ejecutarlos nuevamente. Entonces aquí puedes ver, por ejemplo, que hubo un intento en el lado izquierdo donde una prueba falló y sabíamos que era potencialmente una prueba inestable. Y así automáticamente se inició un nuevo intento y el segundo resultó en una ejecución correcta.

8. Repensando CI para Monorepos y NX Cloud

Short description:

Superficiar información y reintentar pipelines fallidos. La escalabilidad dinámica optimiza el uso de las máquinas y reduce los costos. NX Cloud simplifica la configuración de distribución con una sola bandera. La división de tareas y la detección de inestabilidad mejoran la eficiencia. Conéctate con NX Connect y explora nuestros recursos para obtener más información.

Y eso fue marcado. Y así podemos, en primer lugar, superficiar esa información, pero como puedes ver también, podemos reintentar automáticamente. Y así, básicamente, se ejecuta nuevamente todo el pipeline, tiene éxito en lugar de fallar. Como puedes ver aquí, esa ejecución está sucediendo.

Otra parte aquí también es la escalabilidad dinámica, porque claramente algunas de las PR pueden verse muy diferentes. Entonces tienes algunas PR que están ejecutando todas esas pruebas de extremo a extremo porque algunas partes se vieron afectadas y necesitamos ejecutarlas. Algunas como PR2 o PR4 son muy rápidas porque solo cambiamos un proyecto. Solo necesitamos ejecutar una prueba para eso, eso es todo. Y así, si tenemos un número estático de máquinas, eso podría ser subóptimo porque algunas de ellas podrían estar inactivas o la distribución terminará siendo una tarea por máquina lo cual es realmente ineficiente también en términos de costos.

Y así también permitimos no solo dar las máquinas, sino también dar un conjunto de cambios, un archivo de conjunto de cambios dinámico donde puedes definir máquinas para conjuntos de cambios pequeños, medianos y grandes. Entonces, ahora mismo damos este tipo de distribución y automáticamente distribuiremos según las notas afectadas en comparación con el conjunto completo de notas en un gráfico de proyecto, y lanzaremos cuatro, ocho o doce máquinas. Pero en el futuro, podemos comenzar a hacer un enfoque mucho más detallado donde potencialmente puedes definir un porcentaje del gráfico que clasificará para ti como pequeño, mediano o grande. Entonces te brinda aún más flexibilidad allí. Así que esto ha sido solo algunas de las cosas que quería mostrarte de cómo queremos comenzar a repensar cómo funciona CI, especialmente para los monorepos. Lo que realmente intentamos hacer en NX es brindarte la experiencia de extremo a extremo, ¿verdad? Así que tenemos el lado inteligente de los monorepos en la experiencia del desarrollador local donde venimos con herramientas que te ayudan a estructurar los monorepos, facilidades para permitirte automatizar fácilmente dichos monorepos. Pero también queremos asegurarnos de que no te quedes solo en CI con configuraciones complejas y scripts complejos en CI para asegurarnos de que también tengas éxito allí. Porque si CI no funciona, puedes tener la mejor experiencia de desarrollador local, pero eso simplemente será un problema y volverás a alejarte de los monorepos solo por esa razón. Y eso es lo que intentamos cubrir.

Lo hacemos con NX Cloud, que es nuestro producto allí. Puedes conectarte simplemente con NX Connect y eso te guiará a través de la configuración de toda la distribución. Y nuevamente, la parte importante aquí es la simplicidad de definir dicha distribución con una sola bandera. Y así, esa única bandera te brinda la distribución en estas máquinas, la escalabilidad dinámica potencial de estas máquinas, según el tamaño de la PR. Así que ahorras costos en realidad, y no ejecutas máquinas innecesariamente. La división de tareas, que es una combinación de NX que puede dividirlas dinámicamente, pero también ayuda en el lado de CI donde los agentes de NX pueden recoger esas tareas más detalladas y distribuirlas de manera mucho más eficiente. Y finalmente, también la detección de inestabilidad de tareas. Entonces, eso puede ser una tarea de extremo a extremo, pero potencialmente también puede ser cualquier otra tarea que pueda ser inestable. Y definitivamente revisa nuestro canal de YouTube. Hay muchos videos informativos y análisis más profundos que publicamos allí. Y de lo contrario, ponte en contacto, comunícate. Si tienes preguntas, mis mensajes directos también están abiertos en X, o tenemos un Discord, un Discord de comunidad, que es bastante activo. O, obviamente, puedes ir a nx.dev/docs. Tenemos todos los detalles allí. Gracias.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

DevOps.js Conf 2022DevOps.js Conf 2022
27 min
Why is CI so Damn Slow?
We've all asked ourselves this while waiting an eternity for our CI job to finish. Slow CI not only wrecks developer productivity breaking our focus, it costs money in cloud computing fees, and wastes enormous amounts of electricity. Let’s take a dive into why this is the case and how we can solve it with better, faster tools.
DevOps.js Conf 2024DevOps.js Conf 2024
25 min
Atomic Deployment for JS Hipsters
Deploying an app is all but an easy process. You will encounter a lot of glitches and pain points to solve to have it working properly. The worst is: that now that you can deploy your app in production, how can't you also deploy all branches in the project to get access to live previews? And be able to do a fast-revert on-demand?Fortunately, the classic DevOps toolkit has all you need to achieve it without compromising your mental health. By expertly mixing Git, Unix tools, and API calls, and orchestrating all of them with JavaScript, you'll master the secret of safe atomic deployments.No more need to rely on commercial services: become the perfect tool master and netlifize your app right at home!
DevOps.js Conf 2021DevOps.js Conf 2021
33 min
How to Build CI/CD Pipelines for a Microservices Application
Top Content
Microservices present many advantages for running modern software, but they also bring new challenges for both Deployment and Operational tasks. This session will discuss advantages and challenges of microservices and review the best practices of developing a microservice-based architecture.We will discuss how container orchestration using Kubernetes or Red Hat OpenShift can help us and bring it all together with an example of Continuous Integration and Continuous Delivery (CI/CD) pipelines on top of OpenShift.
React Summit 2022React Summit 2022
21 min
Scale Your React App without Micro-frontends
As your team grows and becomes multiple teams, the size of your codebase follows. You get to 100k lines of code and your build time dangerously approaches the 10min mark 😱 But that’s not all, your static CI checks (linting, type coverage, dead code) and tests are also taking longer and longer...How do you keep your teams moving fast and shipping features to users regularly if your PRs take forever to be tested and deployed?After exploring a few options we decided to go down the Nx route. Let’s look at how to migrate a large codebase to Nx and take advantage of its incremental builds!

Workshops on related topic

React Summit 2023React Summit 2023
145 min
React at Scale with Nx
Featured WorkshopFree
We're going to be using Nx and some its plugins to accelerate the development of this app.
Some of the things you'll learn:- Generating a pristine Nx workspace- Generating frontend React apps and backend APIs inside your workspace, with pre-configured proxies- Creating shared libs for re-using code- Generating new routed components with all the routes pre-configured by Nx and ready to go- How to organize code in a monorepo- Easily move libs around your folder structure- Creating Storybook stories and e2e Cypress tests for your components
Table of contents: - Lab 1 - Generate an empty workspace- Lab 2 - Generate a React app- Lab 3 - Executors- Lab 3.1 - Migrations- Lab 4 - Generate a component lib- Lab 5 - Generate a utility lib- Lab 6 - Generate a route lib- Lab 7 - Add an Express API- Lab 8 - Displaying a full game in the routed game-detail component- Lab 9 - Generate a type lib that the API and frontend can share- Lab 10 - Generate Storybook stories for the shared ui component- Lab 11 - E2E test the shared component
Node Congress 2023Node Congress 2023
160 min
Node Monorepos with Nx
WorkshopFree
Multiple apis and multiple teams all in the same repository can cause a lot of headaches, but Nx has you covered. Learn to share code, maintain configuration files and coordinate changes in a monorepo that can scale as large as your organisation does. Nx allows you to bring structure to a repository with hundreds of contributors and eliminates the CI slowdowns that typically occur as the codebase grows.
Table of contents:- Lab 1 - Generate an empty workspace- Lab 2 - Generate a node api- Lab 3 - Executors- Lab 4 - Migrations- Lab 5 - Generate an auth library- Lab 6 - Generate a database library- Lab 7 - Add a node cli- Lab 8 - Module boundaries- Lab 9 - Plugins and Generators - Intro- Lab 10 - Plugins and Generators - Modifying files- Lab 11 - Setting up CI- Lab 12 - Distributed caching
DevOps.js Conf 2022DevOps.js Conf 2022
76 min
Bring Code Quality and Security to your CI/CD pipeline
WorkshopFree
In this workshop we will go through all the aspects and stages when integrating your project into Code Quality and Security Ecosystem. We will take a simple web-application as a starting point and create a CI pipeline triggering code quality monitoring for it. We will do a full development cycle starting from coding in the IDE and opening a Pull Request and I will show you how you can control the quality at those stages. At the end of the workshop you will be ready to enable such integration for your own projects.
DevOps.js Conf 2022DevOps.js Conf 2022
155 min
Powering your CI/CD with GitHub Actions
Workshop
You will get knowledge about GitHub Actions concepts, like:- The concept of repository secrets.- How to group steps in jobs with a given purpose.- Jobs dependencies and order of execution: running jobs in sequence and in parallel, and the concept of matrix.- How to split logic of Git events into different workflow files (on branch push, on master/main push, on tag, on deploy).- To respect the concept of DRY (Don't Repeat Yourself), we will also explore the use of common actions, both within the same repo and from an external repo.