Hacia un framework de desarrollo guiado por pruebas para Vala - tercera parte - DevOps - Integración Continua con Jenkins
Posted on Tue 19 January 2016 in Vala
Integración Continua o IC está ampliamente usado en TDD para mantener la base de código de un proyecto bien ordenada, reduciendo los errores y asegurando que hay siempre ejecutables disponibles para desplegar. Proporciona medios para automatizar el proceso de compilar y probar, así que los desarrolladores se pueden enfocar en escribir pruebas y el código que las pasara. Mediante la instalación de un sistema que compila y prueba el software en las plataformás que las soporta, los problemás de despliegue pueden ser identificados temprano y la distribución de los nuevos lanzamientos automatizados.
Dado que uno de los objetivos de Valadate es integrarse en las cadenas de herramientas ya existente, y con ganas de aprovechar los beneficios numerosos para el proyecto si mismo, tome un pequeño break de DevOps para instalar un sistema basado en Jenkins en mi red local. Jenkins es un servidor de Integración Continua de codigo abierto que está ampliamente usado. Escrito en Java, se puede ejecutar en cualquier en cualquier sistema, dado que tenga suficiente potencia. Llevándose al extremo, decidí instalarlo en un Raspberry Pi 2 que tenia por ahí. Por que Jenkins y por que en un Raspberry Pi?
En primero, el Jenkins es una plataforma robusta y mantenida que está ampliamente usado. Hay una plétora de complementos que integrarse bien con Git, Docker, TAP y muchos otros herramientas y protocoles de IC. Se basa en el modelo de amo-esclavo, donde el servidor amo dirige las operaciones de compilar en cualquier numero de esclavos. Un esclavo puede ser cualquier otra computadora en la red que puede comunicarse con Jenkins, o directamente a través de SSH o con un complemento. Es fácil de configurar y sencillamente funciona. Me parecía una buena elección por empezar.
En segundo, la Raspberry Pi. Uno de las consideraciones en armar el sistema de IC fue que el servidor amo debe ser accesible por la internet y disponible 24x7. Dado que cuando no hay tareas en marcha el servidor está más o menos desocupado, utilizando una computadora de plena potencia seria una perdida de energía y dióxido de carbono. Me di cuenta que una de las Raspberry Pi que no estaba ocupada podría hacer el trabajo, así que después de una búsqueda rápida de Google para confirmar que sea posible, seguí con la instalación. La guía más comprensiva que encontré sugirió huevadas como descargar paquetes de código fuente pero dado que esa fue para una versión previa de Raspbian, intentaba con sudo apt-get install jenkins y salio nomás.
Con el servidor de Jenkins ya en marcha, agregue el port de Gherkin que recién lancé como una prueba y arme una maquina con Fedora 23 como esclavo y dentro de 5 minutos lo había hecho checkout, compilado y ejecutado las pruebas y...
\O/ \O/ \O/
A pesar de tener poco potencia, la Raspberry Pi parece adecuada para la tarea, como no compilar nada. Algunas de las paginas de configuración tarden un ratito en cargar pero para el uso ordinario parece rápida. No solo eso, sino puedes hacer cosas chulas también.
Animado por el éxito inicial, arme un esclavo de Docker. Para esta configuración, reanime un antiguo servidor que había sido mothballed, con la idea que como un esclavo de compilar, no necesitara estar en linea todo el tiempo y con Wake On Lan (WOL) puedo mandar que Jenkins despierte el servidor cuando necesite hacer una tarea y adormecerlo cuando se termina. Eso todavía se queda por hacer pero me parece sencillo.
Con esta configuración, el esclavo es un anfitrión de Docker y se arranca y ejecutar un contenedor armado de un Dockerfile en la raíz del repositorio. Es este contenedor que ejecutar la compilación, no el anfitrión, asimismo es posible probar tu software en casi cualquier plataforma que se puede dockerize. Que guay no? Entonces, arme un contenedor de Ubuntu y...
Como que? Mire el log y...
./.libs/libgherkin3.so: undefined reference to `g_value_init_from_instance'
Maldito sea! En la prisa de portear Gherkin, lo hice en mi nuevo sistema de Fedora 23 y no lo había probado nada en Ubuntu. Comprobé los documentos y por cierto, GLib.Value.init_from_instance() está disponible a partir de la version 2.42 de GLib y el Ubuntu 15.04 solamente lleva la versión 2.40. D'oh! Así que tengo que refactorizarlo o declarar GLib 2.42 como requisito.
Este caso en particular es un muy buen ejemplo de los beneficios de Integración Continua. Si tuviera el servidor de Jenkins armado antes de portear el código, me habría dado cuenta de la incompatibilidad casi de inmediato y lo habría arreglado en aquel momento, más bien que refactorizarlo más tarde.
Aunque seria bonito ignorar la existencia de los otros sistemás operativos, la verdad triste es que no todo el mundo usar el Linux como su escritorio principal, incluso ya mucha gente que tal vez querría usar mi software. Conciente de esa realidad brutal, decidí armar esclavos de Windows y Mac OSX para probar la compatibilidad multiplataforma de mis proyectos.
Para el esclavo de Windows, instale una nueva VM de Windows 7 en VirtualBox, ejecutando en el mismo servidor que el anfitriona de Docker. Para la cadena de herramienta, instale MingGW64 y MSYS2 y todas las bibliotecas necesarias y voila! Pues, no exactamente voila, el linker de MinGW es tan despacio que me costo bastante tiempo depurarlo pero ya funciona bien. El proceso no es totalmente automático - tengo que arrancar y apagarlo a mano. Hay un complemento de VirtualBox para hacer todo eso pero actualmente no soporta la versión 5. Tambien aprendí por las malas que hay que deshabilitar las actualizaciones automáticas para Windows, si no se trabara en la pantalla de arranca fallada. Además para darle prisa un poquito, tengo pensado compilar los binarios en un contenedor de Docker a ejecutar las pruebas el la VM de Window para asegurar que funcionan correctamente.
Ahora bien, si has asistido a cualquier conferencia mayor de Linux en los últimos anos, podrías concluir que estuvieras en WWDC con todo los equipos de Apple que se veía en todas partes. Vaya, aun mi esposa, una guru de software libre, usaba un MacBook Air por mucho tiempo hasta que compró un Microsoft Surface. Y es la verdad, es unos de los equipos más chulo y caro para ejecutar una Maquina Virtual de Linux. No me entiendes mal - tengo uno en el escritorio, lo uso para email, IRC y la sesión ocasional de Photoshop (por lo menos hasta que el Gimp soporte mejor las tablas). Desafortunadamente, está un poco descuidado así que necesitara un poquito de limpieza antes de ser puesto a disposición, ojala antes del comienzo de la semana que viene.
Lo largo del camino, descubrí que nuestro Modem de Cable de mierda, proporcionado por Comcast no soporta las resoluciones DNS de horquilla cuando redirigí los puertos del servidor Jenkins. Intentaba resolver eso mediante instalar dnsmásq en la Raspberry Pie pero aun así necesitaba editar a mano los archivos de resolv.conf en cada maquina. Al final, puse el Modem de Comcast en modo puente y arme un viejo pero confiable WRT-54GL con DD-WRT como el nuevo Gateway/Router. Aun tiene problemás con el DHCP de IPv6 pero por lo menos funciona bien.
Entonces ya está, un sistema de Integración Continua multiplataforma compilando proyectos basados en Vala. Está en vivo en la internet ahora, así que se puede ver aqui (se requiere login de Github).
Venga, ya estamos listos para empezar a construir Valadate! Sintonice de nuevo prontito para la cuarta parte - Quien pone a prueba el probador?