Integración continua rápida y sencilla con GitLab CI

¿Aún no has descubierto las ventajas que la Integración Continua puede tener en tus desarrollos? ¿Usas GitLab para gestionar tus proyectos y nunca te has parado a pensar que hacen esas pestañas que nunca has usado encima de tus repositorios?

Pues podrías deshabilitarlas en los settings… o continuar leyendo para descubrir algunas formas en las que pueden ayudarte a multiplicar tu productividad de una forma muy sencilla.

Este post pretende ser un resumen de alto nivel de como GitLab interpreta los conceptos principales de Continuous Integration/Delivery y presenta las caracteristicas de la herramienta y su forma de llamar a las cosas, dado que todo puede sonar más complicado de lo que en realidad es. En siguientes artículos, ilustraremos todo esto con una sencilla demo haciendo uso del generador de páginas estáticas que incluye la suite y un caso de uso real de implantación de Integración Contínua con GitLab en un flujo de trabajo.

El crecimiento del producto lo ha catapultado a los stacks tecnológicos de muchas empresas, parte de esta popularidad viene de la mano con ser un fantástico proyecto open-source que seguir; su ciclo de actualización es increíble y son capaces de incluir nuevas funcionalidades el 22 de cada mes. Uno de los factores más importantes en esta ecuación es el hecho de que no solo ofrecen una solución auto-alojada, que te permite tener tus proyectos bajo control en tus servidores, sino que es también una bastante completa. Solo tienes que preguntar a tu colega ops de referencia y te contará como incluso la versión community (no comercial) trae consigo muchas cosas que son increíblemente caras o que simplemente no incluyen otras soluciones SaaS similares.

De vez en cuando pasa, que simplemente nos acomodamos en aquellas plataformas y herramientas que ya conocemos y ni nos percatamos de la aparición de alternativas que pudieran mejorar nuestro día a día. Creo que este es el caso de algunas de las opciones menos conocidas de GitLab. El proyecto es mucho más que un sevidor de control de versiones tradicional, de hecho el año pasado describieron su “masterplan” para convertirse en algo más parecido a una “suite” para cubrir cada uno de los pasos en el ciclo de desarrollo; o en sus palabras: pasar de idea a producción. Y para rematar, tanto en pasadas como en futuras actualizaciones, están incluyendo integraciones con otros servicios muy interesantes que merece la pena tener presentes (p.e. chatops para slack/mattermost o monitorización con Prometheus).

Diferencias con otras herramientas de Integración Continua.

Empecemos describiendo aquello que lo convierte en una opción tan potente. Para empezar, está basado en un modelo de fichero de configuración escrito en YAML y almacenado en la raíz de cada repositorio. Esta aproximación tiene algunas ventajas que vale la pena mencionar con el resto:

1.  Estrecha relación entre los sistemas (tanto Integración Continua como la gestión de versiones son un único producto).

2. La configuración de Integración Continua pasa a estar versionada:

  • Fomentando que cada rama tenga su propia configuración.
  • Permitiendo a los colaboradores aportar también configuraciones.

3. Integración con Docker sin necesidad de configurar nada, incluyendo un Docker registry privado por proyecto.

4. Explorador de artefactos para acceder a los resultados de cada etapa del mismo modo que haríamos en local.

5. Nada de tiempo malgastado en configurar el servidor de Integración Continua.

Desde el punto de vista del usuario, todo esto viene con algunas pegas en comparación con otros sistemas de Integración Continua, dado que emplea un modelo muy “convention over configuration“, que se traduce en una herramienta muy poderosa “de fábrica”, sin perder mucho tiempo en configurarla, pero a cambio el usuario tiene que ceñirse a su manera de hacer las cosas. Es lo que ocurre con la falta de plug-ins e integraciones a los que, por ejemplo, Jenkins nos tiene acostumbrados y que permiten configurar más el detalle de nuestros proyectos (por ejemplo, crear trabajos que hagan uso de más de un repositorio en GitLab no es nada trivial). Pero hay que decir que la mayoría de los escenarios están cubiertos de sobra: alertas por email, navegar por la historia de builds del proyecto o programar ejecuciones de los trabajos son algunos ejemplos.

Pero seamos claros, ni han inventado la rueda ni son los únicos que la están usando: muchas otras herramientas de Integración Continua también descansan en paradigmas similares (.travis.yml, Jenkinsfiles…). Todo esto es cuestión de gustos. Pero el poso que te queda después de probar distintos sistemas es que la que propone GitLab es la más sencilla de configurar a la vez que permite tener la mayor cantidad de detalles bajo control en la misma pestaña del navegador. Han tomado las mejores funcionalidades de cada herramienta y las han empaquetado en una sola aplicación: tiene todo el sentido.

Principales características

Voy a tratar de ilustrar las principales bondades de la herramienta y demostrar lo fácil que es empezar a usarla sin ningún tipo de experiencia cómo sysadmin o molestar a tus devops. Como ya he mencionado, todo gira en torno al fichero .gitlab_ci.yml que contiene la definición de las diferentes stages (o pasos) que contienen diferentes trabajos que tendrán que completarse para que el proyecto pueda ser desplegado correctamente. La estructura del archivo es de lectura natural y una vez hayas visto un par de ejemplos, podrás empezar a escribir los tuyos sin apenas esfuerzo.

No tenemos más que dirigirnos a la documentación de GitLab CI para encontrarnos con basta información y ejemplos de como traducir las necesidades específicas de nuestro proyecto a sus convenciones. Para resumir, vamos a revisar cuales son las opciones de Integración Continua que cualquier repositorio tiene activadas por defecto:

Configuración de Integración/Despliegue Continuo (CI/CD)

La página de configuración da una idea de cómo de sencillo es configurar todo aquello necesario para que se obre la magia de la integración continua:

Runners

Qué pasa si te digo que por fin te puedes olvidar de configurar y gestionar slaves: el cómo se conectan al servidor de Integración Continua, cómo balancear la carga entre todos o cualquier otros detalles que son tanto tediosos como complicados en muchos casos…

Te presento a los Runners! Su instalación se reduce a algo tan sencillo como seguir los tres pasos descritos en la configuración de CI/CD de tu proyecto: instalar el binario correspondiente a tu sistema operativo, pega la URL de tu servidor y el token que aparece en esta página y listo. Además, puedes etiquetar a tus Runners en base a sus capacidades para seleccionarlos en trabajos específicos desde el fichero .gitlab_ci.yml cuando sea necesario.

Los Runners pueden utilizar diferentes executors, que no son más que formas distintas de ejecutar tus scripts/código en ellos; desde el más básico, sobre ssh, pasando por un servicio de contenedores, hasta el cluster kubernetes más grande que se te pueda ocurrir; soportando incluso ejecuciones sobre Powershell/Batch en sistemas Windows.

En su versión auto-gestionada, gitlab.com, también ofrecen la posibilidad de configurar “shared runners“: máquinas virtuales sin coste alguno y compartidas entre todos los usuarios, que se reservan dinámicamente para los proyectos de la plataforma. Esto es ideal para desarrollos open-source con recursos limitados.

Gestión de secrets

En la era de los microservicios, en la que es muy probable que tu proyecto esté integrado con docenas de APIs que utilizan tokens, secrets, contraseñas de aplicación o cualquier otra forma de autorizar ese diálogo, se convierte en prioridad alguna forma elegante de manejar toda esta complejidad. Un auténtico bad smell más frecuente de lo que creeríamos es almacenar todos estos datos en ficheros de configuración en una máquina remota o incluso dejarlos colgando en alguna parte del código. Para poner énfasis en la importancia de esto, simplemente considera cuántos servicios y proyectos están surgiendo en los últimos años para gestionar esta problemática. Los proyectos de GitLab también incluyen un sencillo keystore en su página de settings que pueden ser accedidos desde los scripts de Integración Continua para que los administradores del proyecto los gestionen.

Pipelines

Esta es la funcionalidad central de cualquier sistema de Integración Continua y, a la vez, un concepto realmente simple que se traduce en conectar todos los pasos (stages) que deben seguirse desde el momento en el que dispone de todo el código fuente al punto en el que la aplicación puede ser desplegada. Entre medias, puedes incluir todo aquello que se te ocurra para comprobar que: el código tiene buena pinta (linting), puede compilarse sin errores, funciona de forma esperada (unit tests), se integra con otros sistemas… y cualquier cosa que nos lleve a desplegar con seguridad nuestras aplicaciones.

Container Registry

Imagina tener tu propio docker hub privado en el que almacenar las imágenes de tu proyecto, actualizarlas en cualquier momento que sea necesario sin tener que exponerlas al publico y con la capacidad de utilizarlas desde cualquier sitio con sólo autenticarse. Puedes tener una imagen preparada para cada stage de tu pipeline y abstraer cantidad de información de build a los runners de forma transparente e increíblemente rápida. Esto se vuelve fundamental a la hora de inicializar los entornos, reduciendo el tiempo necesario para ejecutar nuestros trabajos.

Entornos y review apps

A todos nos encanta gitflow, ¿verdad? y es que hay unas cuantas razones para ello. Se construye sobre las premisas de que si cada rama es desarrollada de forma aislada, las nuevas funcionalidades no interfieren con el resto o con la estabilidad de toda la aplicación hasta que son mergeadas en master. Esto nos ayuda tanto a desarrollar funcionalidades como a testarlas.

Cuando los contenedores irrumpieron en nuestras vidas, era obvio cómo el proceso de desplegar entornos diferentes e independientes con configuraciones individuales podía agilizar nuestros despliegues. Y ahora es justo decir que utilizamos los contenedores como estándar de facto en lo que a despliegues se refiere. La mayor parte de los sistemas de Integración Continua se idearon mucho antes de que el primer contenedor de la historia fuese creado, y por tanto, sin Docker en mente. Con GitLab CI ocurre todo lo contrario: fomentan el uso de los contenedores basándose en todos los beneficios que aportan al flujo de trabajo.

Por ejemplo, un escenario que se repite en cada sprint: estás a punto de mergear la rama de una user story que tiene que ser testada por el equipo de QA y que a su vez, introduce nuevas dependencias con librerías y con un nuevo servicio (p.ej. Redis, mongoDB…) para ser desplegada. Solo tienes que actualizar tu Dockerfile para incluir la/las nuevas capas que gestionan estas dependencias y hacer push de dicha imagen a tu Docker registry local. Una vez se suban los cambios de la rama al repositorio, tendrá todo en su lugar para ser desplegada con un click en el entorno de pruebas.

Aquí es donde entran en juego las review apps, que no es más que una forma pija de llamar a entornos creados dinámicamente por rama, para verificar los cambios y verlos desplegados. Cada rama tiene la capacidad de ser desplegada en cuanto se hace el push contra el repositorio. Este proceso puede agilizarse mediante herramientas como dpl que abstraen muchos de los detalles de implementación de las principales plataformas de despliegues en la nube. O en cambio, llamar manualmente a tu script de despliegue personalizado desde ahí.

También integra una terminal interactiva que lanzar desde el navegador y que permite determinar las causas en el caso de que algo fuese mal en nuestros despliegues. Ya no hace falta repetir el mantra de Jenkins en el que clonabas un trabajo configurado, lo renombrabas, ajustabas las ramas en su configuración… y 10 o 15 tediosos pasos después ya podías desplegar tu entorno de pruebas efímero.

Otra funcionalidad que te va a encantar es el history browser. Imagina que has desplegado unos cambios para una demo y 10 minutos antes de empezarla, descubres que esa versión tiene un bug que quedaría muy feo en camara. ¡Ningún problema! es extremadamente sencillo acceder a toda la historia de aquello que se desplegó en cada uno de nuestros entornos y revertir aquellos cambios que nos afectan para volver a cualquier estado anterior. Genial!

Espero que tras esta introducción, los conceptos centrales sobre los que se asienta la Integración Continua en GitLab cobren sentido en tu contexto y en el de tus proyectos. Si no, solo espera a la continuación para descubrir a través de una demo, como podemos empezar a utilizarlo de una forma muy sencilla.