Si bien somos grandes admiradores de CircleCI y lo usamos para la integración continua tanto para nuestros SDK de iOS como de Android, pero a medida que nuestro equipo crece, nuestras necesidades han cambiado. Como resultado, decidimos establecer nuestra propia infraestructura de CI. En esta publicación, lo guiaré a través de lo que nos motivó a hacerlo y las herramientas que utilizamos.
Desafíos con nuestra infraestructura actual
Si bien CircleCI funciona muy bien para nosotros, queríamos ejecutar nuestras pruebas de IU en dispositivos físicos en lugar de solo simuladores. Esto nos ayudaría a encontrar oscuros problemas de interfaz de usuario y rendimiento. Actualmente, esto no es posible en CircleCI, y aunque hay muchos servicios que le permiten hacer esto, preferimos utilizar el amplio conjunto de dispositivos de prueba que ya teníamos en nuestra oficina.
Además de eso, tenemos una herramienta interna que hemos desarrollado para hacer una combinación de pruebas funcionales y de estrés en el SDK. Esta herramienta realiza ejecuciones nocturnas que tardan muchas horas en completarse, y aunque es posible ejecutarla en CircleCI, no sería rentable.
Nuestra solución de infraestructura CI de iOS
Para ayudar a reducir la fragilidad y la eventual configuración / deriva ambiental, decidimos desde el principio que las compilaciones deben ejecutarse en un entorno aislado, como los contenedores Docker, en lugar de ejecutarlas directamente en la máquina host.
Desafortunadamente, Docker no admite contenedores macOS, por lo que decidimos usar Anka de Veertu . Anka es una tecnología de virtualización para macOS construida sobre Hypervisor.framework que ofrece una interfaz similar a un contenedor y ofrece una interfaz de línea de comandos simple para activar y administrar máquinas virtuales.
El siguiente desafío que enfrentamos fue elegir una interfaz para programar y administrar nuestras compilaciones. Decidimos mantenernos alejados de Jenkins ya que es demasiado complicado configurarlo e ir por algo más moderno.
Después de probar diferentes herramientas, Buildkite parecía adaptarse mejor a nuestras necesidades. Buildkite ofrece una interfaz de usuario simple y moderna con la capacidad de crear fácilmente tuberías sofisticadas.
Como funciona todo
El primer paso que teníamos que hacer era crear una máquina virtual Anka que pudiéramos clonar para cada compilación. Para facilitar ese proceso, utilizamos HashiCorp’s Packer .
Packer nos permite automatizar el proceso de creación de máquinas virtuales a partir de un montón de archivos de confirmación . Con Packer, podemos crear una imagen que tenga Xcode, fastlane, CocoaPods y todas las otras herramientas esenciales para nuestros trabajos de compilación mientras solo tomamos el instalador de macOS descargado de la App Store como entrada.
Las imágenes se crean como capas separadas una encima de la otra. La primera capa solo instala Ruby, Homebrew y algunos otros elementos básicos, mientras que la capa superior instala Xcode, lo que hace que sea mucho más fácil y rápido crear una nueva imagen que tenga una nueva versión de Xcode, basada en la primera capa. Además, dado que todo el proceso se basa en archivos de configuración, puede controlarse en origen y versionarse.
Una vez que se crea la máquina virtual, se agrega al Registro de Anka, que actúa como un depósito central de imágenes de máquinas virtuales versionadas. Todos los agentes de compilación pueden extraer imágenes de este registro y clonarlas para ejecutar canalizaciones de compilación.
Con nuestras imágenes de máquinas virtuales listas y el agente Buildkite ejecutándose en un clúster de minis Mac locales, el siguiente paso fue descubrir cómo aprovisionar una máquina virtual para cada compilación y ejecutar la tubería dentro de ella. Para hacer esto, utilizamos el complemento Chef’s Buildkite para Anka . Con el excelente soporte de Buildkite para complementos, simplemente podemos establecer un paso en nuestras canalizaciones de compilación para que se ejecute usando este complemento.
El complemento hará automáticamente lo siguiente:
- Cree un clon de la imagen específica de la máquina virtual.
- Arranque la máquina virtual casi al instante, gracias a la tecnología de virtualización de Anka.
- Monte el código fuente extraído del host en la máquina virtual.
- Ejecute el paso de canalización dentro de la máquina virtual.
- Elimine la máquina virtual clonada cuando las tuberías tengan éxito, fallen o se cancelen.
Con esta configuración, podemos ejecutar múltiples pasos de canalización simultáneamente en máquinas virtuales separadas en varias máquinas host. Dado que cada máquina solo necesita ejecutar el agente BuildKite y la interfaz de línea de comando de Anka, las máquinas pueden estar en diferentes ubicaciones para que nuestra configuración sea más resistente a las interrupciones.
Escalabilidad
Escalar esta infraestructura es tan simple como agregar nuevas máquinas al clúster de hosts, con Anka CLI y el agente Buildkite ejecutándose en ellas. También podemos agregar máquinas remotas de proveedores como MacStadium para tuberías que no requieren acceso a dispositivos físicos.
Conclusión
Usando Anka y Buildkite, creamos una infraestructura de CI que es fácilmente escalable, reduce la flacidez / deriva ambiental y nos brinda mucha flexibilidad para ejecutar tuberías de construcción que demoran horas en completarse, o tuberías que requieren acceso a dispositivos físicos.
Si bien llevó una inversión de tiempo considerable construir nuestra propia infraestructura de CI, creemos que vale la pena el mayor control y flexibilidad que nos brinda.
Te esperamos en los próximos artículos en donde hablaremos mas acerca de estos temas que hoy en día son de importancia e interés en el mundo de la tecnología.