Industria: Entrega de alimentos
Productos de JetBrains utilizados: TeamCity
Tamaño de la organización: 10,000
País: Países Bajos
«Buscábamos una solución gestionada para todos nuestros casos de uso de integración continua. Además, necesitábamos agentes autohospedados para controlar qué software se ejecuta y qué herramientas exactas se utilizan. TeamCity Cloud con agentes autohospedados es una solución a medida que encanta a nuestro equipo, compuesto por más de 300 ingenieros, y que mejora muchísimo nuestra productividad.»
— Ivan Babiankou, ingeniero de software de Picnic
Me llamo Ivan Babiankou y soy ingeniero de software de Picnic. Formo parte del equipo de la plataforma Java. Participé en la elección del sustituto de nuestra anterior solución de integración continua y en la migración.
Picnic ha revolucionado la forma de hacer la compra. Empezamos en una sola ciudad neerlandesa, pero Picnic ya está presente en más de 200 ciudades de tres países: Alemania, Francia y los Países Bajos. No tenemos tiendas físicas, sino que Picnic es una aplicación en la que millones de usuarios hacen la compra de forma rápida y sencilla.
Además de la aplicación móvil para los usuarios, hemos creado la mayoría de los sistemas vitales para la empresa, entre los que destaca una solución interna para la gestión de los almacenes. También hemos creado todas las herramientas para planificar las rutas de los conductores, ayudarles a conducir con seguridad, optimizar las rutas de recogida de pedidos en el almacén, etc.
Ahora mismo, Picnic emplea a más de 300 desarrolladores. La pila tecnológica de la empresa está compuesta, entre otros, por GitHub, Java, Python, Swift, Kotlin, TypeScript, Angular, React, Android, iOS, MongoDB y Spring Boot.
Empezamos a fijarnos en JetBrains TeamCity a finales de 2021 porque nuestra anterior solución de integración continua se nos había quedado pequeña. Teníamos dos problemas principales: builds lentos y colas de compilación largas. En hora punta, algunos builds permanecían en la cola hasta una hora antes de ejecutarse.
En nuestra antigua solución, la solución a esto pasaba por aumentar de forma considerable el número y el tamaño de los agentes de compilación para reducir el tiempo total de compilación. Sin embargo, esta solución no era escalable, ya que no abordaba el problema principal de la velocidad de compilación. Decidimos buscar una nueva solución que pudiera hacerlo mejor y más rápidamente.
Para sustituir nuestra solución de integración continua, buscamos un sistema que fuera compatible con nuestra pila tecnológica y que nos ayudara a estandarizar la forma de crear y probar las aplicaciones. Utilizamos Java y Python para el desarrollo de aplicaciones backend, GitHub como VCS, y Kotlin, Swift y React Native para el desarrollo móvil.
Empezamos con una lista larga de 10 proveedores de soluciones y la redujimos a 3: CircleCI, TeamCity y GitHub Actions. Nuestro objetivo principal era reducir los tiempos de espera y mejorar el rendimiento de la integración continua reduciendo el tiempo de compilación.
Otro requisito era tener agentes autohospedados. Durante el análisis, nos dimos cuenta de que nuestra antigua solución no actualizaba demasiado rápido las herramientas en los agentes. Pasábamos entre 2 y 5 minutos en cada build instalando herramientas. Teniendo en cuenta que un build medio dura unos 9 minutos, no tiene sentido dedicar otros 3 minutos a instalar de antemano las herramientas. Así es como llegamos a la idea de contar con agentes autohospedados donde tener las últimas herramientas, el rendimiento adecuado y casi todo lo que necesitábamos para empezar nuestros builds.
La solución de integración continua en la nube también era un requisito previo. En Picnic, intentamos gestionar el menor número de sistemas posible. Con la integración continua, queríamos tener una solución gestionada que no tuviéramos que ejecutar nosotros mismos. Además, con los agentes autohospedados en la nube podemos controlar el software que ejecutamos y las herramientas exactas que utilizamos. Nos da la flexibilidad de controlar todo el entorno de compilación, es decir, el hardware que se utiliza y las herramientas preinstaladas, sin tener que gestionar el servidor de integración continua.
Tenemos unos 300 usuarios de integración continua, la mayoría de los cuales son activos y realizan confirmaciones de forma intensiva en casi 200 proyectos. Estos proyectos siguen una estructura bastante jerárquica en TeamCity, con más de 120 raíces de VCS.
Además, tenemos 40 agentes de compilación para un máximo de 40 builds simultáneos. Ejecutamos casi 1100 builds al día, con un tiempo total de compilación diario cercano a los 10.000 minutos. Los agentes necesitan unos 2 minutos para arrancar y los builds rara vez se ponen en cola durante más tiempo.
En un mes, todo esto suma casi 300 000 minutos de tiempo de compilación.
Utilizamos TeamCity para todo el desarrollo interno. Al abrir una solicitud de incorporación de cambios en GitHub, la integración continua lo construye, ejecuta pruebas de unidad, de integración y de componentes, y da feedback. Esto es más o menos lo que podemos hacer con TeamCity. Lo utilizamos hasta que se produce un artefacto de compilación, que después se lleva a un repositorio para su posterior implementación.
Todos los agentes de build Linux y habituales se ejecutan en nuestro proveedor de nube (AWS). Para las aplicaciones iOS, tenemos algunos Mac Mini conectados a la red de nuestra oficina y a TeamCity. De hecho, el equipo de iOS ya utilizaba TeamCity en local antes de la migración a TeamCity Cloud.
Ejecutamos agentes con instancias bajo demanda. Las instancias de spot siguen siendo una opción muy atractiva a tener en cuenta en mejoras futuras.
Preparamos nuestras propias imágenes y usamos los Cloud Profiles de TeamCity para ejecutar agentes autohospedados. Son, de hecho, máquinas EC2 en AWS. Usamos TeamCity y Packer para construir imágenes de AWS de los agentes.
Después, utilizamos esos agentes con plantillas de lanzamiento y perfiles de nube en TeamCity para empezar a compilar agentes bajo demanda. De momento, son desechables y solo se pueden utilizar en una compilación.
Nos dimos cuenta de que el tiempo de cola era de 2 minutos, en los que se tardaba 1,5 minutos en proporcionar el agente de compilación en AWS. Tener agentes reutilizables de larga duración nos ayudaría a atajar este problema. Con eso, empezaríamos a buscar instancias de spot.
Nuestra política es desactivar la edición en la interfaz de usuario de TeamCity. Uno de nuestros objetivos es estandarizar los procesos, y lo conseguimos utilizando la configuración como código.
Todas las configuraciones de build se almacenan en sus respectivos repositorios como código Kotlin. Hemos construido nuestro propio DSL sobre el DSL de Kotlin en TeamCity, que nos permite definir procesos usando 20 líneas de código como máximo.
Por ejemplo, tendría el build principal que compila la aplicación Java. Ejecutará todas las pruebas y pruebas de componentes. Si todo va bien, subirá los artefactos de build al repositorio apropiado.
Además, tenemos una tarea para el análisis estático del código y otra nocturna para el análisis estático del código que se utilizará en SonarCloud. Todas ellas forman parte de un proceso estándar. Para las aplicaciones Java, es lo que se obtiene desde el principio si se limita a definir los elementos básicos para sus procesos.
Algunos de nuestros equipos tienen muchas pruebas de componentes (DGC). Las escribimos en Python, mientras que la aplicación principal está escrita en Java. La aplicación se empaqueta en una imagen de Docker. A continuación, ponemos en marcha un entorno Docker Compose en el agente de compilación con una infraestructura real (bases de datos, etc.), mientras que los servicios de terceros se simulan. Las pruebas de comportamiento se ejecutan contra la aplicación que se ejecuta en Docker Compose.
En el DSL de Kotlin proporcionado por TeamCity, se pueden realizar todos los ajustes en el proceso de compilación. Es posible cambiar los pasos, los desencadenantes y muchas otras cosas.
De forma predeterminada, damos a los equipos un estándar de oro de los procesos tal como el equipo de la plataforma lo ve. Por ejemplo, ejecutamos las pruebas de componentes como parte del proceso de compilación en el mismo agente, como parte del mismo trabajo.
Hay equipos que tienen cientos de pruebas de componentes, que por desgracia aún no están paralelizadas. En esos casos, permitimos dividir las pruebas de comportamiento de los componentes en suites de pruebas y configurarlas como una cadena de build.
Así, el build principal produce el artefacto y ejecuta pruebas de unidad y pruebas rápidas simples. Si funciona bien, es posible ejecutar tantas suites de pruebas paralelas como sea necesario, que probarían con varias instancias en distintos agentes.
Esto es lo que más nos gusta de usar TeamCity:
Configuración de agentes de compilación de forma predeterminada. Cuando empezamos a fijarnos en TeamCity, vimos que el sistema utiliza agentes optimizados para proceso con un SSD conectado a este, lo que supone un rendimiento superior en comparación con otros procesos de integración continua. Aunque no utilizamos los agentes proporcionados, esto nos impulsó a utilizar instancias optimizadas para proceso para nuestros propios agentes, lo que mejoró el rendimiento.
También nos encanta la funcionalidad de supervisión del rendimiento. Uno de los grandes retos para los equipos reales que utilizan esos procesos fue cómo decidir si usar una instancia pequeña, una mediana o una grande. Comprobar el monitor de rendimiento puede ser una buena forma de tomar la decisión, y simplifica la depuración.
En cuanto a los inconvenientes, tener métricas a través de los proyectos que estamos construyendo en TeamCity sería genial, porque de momento TeamCity solo proporciona esta información por proyecto. No hay forma de ver las métricas de todos los proyectos de Java, por ejemplo.
Además, la curva de aprendizaje del DSL de Kotlin es bastante empinada, especialmente para los ingenieros que no están familiarizados con Java.
Ahora que hemos migrado todos los proyectos a TeamCity, nos encantaría seguir experimentando con agentes de compilación, instancias de spot y demás.
Para hacerlo bien, nos gusta capturar métricas de compilación de manera sistemática. Todas estas métricas están disponibles en TeamCity, pero lo que nos impide avanzar es poder ver estas métricas en todos los proyectos y ver cómo evolucionan con el tiempo.
Según esta información, podríamos tomar decisiones para optimizar los esfuerzos: qué mejorar y en qué centrarnos primero, y cómo nuestros ajustes mejoran o perjudican el rendimiento. Por ahora, estamos pensando en crear un servicio externo que reúna toda esta información. Si estuviera disponible desde el principio, ¡sería mucho mejor!
También vamos a estudiar la optimización y a intentar librarnos de esos minutos extra que tarda el agente en arrancar, ya sea teniendo agentes de larga duración o introduciendo un grupo de agentes que arranquen con antelación.
En Picnic también estamos trabajando en compilar más pruebas de extremo a extremo. Será otro proyecto que se ejecute en TeamCity. En cuanto lo tengamos, valoraremos si trasladamos por completo los procesos de integración e implementación continuas a TeamCity.
Tadeas Kriz, director tecnológico y cofundador de Brightify
Nuestras revisiones de código han mejorado significativamente y hemos podido aprovechar los webhooks de Space con TeamCity para compilar cada rama revisada e implementarla en nuestro QA para poder probar la rama antes de combinarla. Ahora también es más fácil saber quién está fuera de la oficina.
Piotr Polus, responsable técnico de frontend de Miquido
Hemos elegido JetBrains por tres razones: la utilidad, la capacidad de configuración y la disponibilidad de los complementos.
Wooseong Kim, líder de Canal APAC y gerente de Asociaciones, Tangunsoft
JetBrains te ayuda a escribir un código limpio, profesional y fácil de mantener, ¡y de la mayor calidad!