Wednesday, 5 November 2014

Travis, o cómo elegir un CI para tu proyecto Java open source

Recientemente me incorporé al equipo de desarrollo de Arena, nuestro framework de MVVM UI pensado para que alumnos de diversas carreras universitarias den sus primeros pasos en el desarrollo de interfases de usuario. Hicimos un sprint para empezar a familiarizarnos con las herramientas y ahí detectamos algunos problemas en la forma de trabajo, que dificultaban un poco la incorporación de nuevos desarrolladores.
Los inconvenientes principales eran:
  • Para trabajar en un proyecto (hoy Arena se compone de 7 proyectos distintos) no había otra opción que compilar todos los demás, ya que al no estar sistematizado el deploy no siempre el SNAPSHOT se correspondía con la última versión del código. Entonces perdía un poco de sentido la separación en artefactos distintos.
  • Algunas veces se pusheaba al repositorio código que rompía los tests, o incluso no compilaba. Al no tener releases estables, podía darse el caso de que un deploy del SNAPSHOT rompiera los trabajos prácticos de los alumnos de una cursada, como sucedió alguna que otra vez.
  • Los artefactos se desplegaban en un repositorio propio y no en Maven Central, lo que implicaba un paso extra de configuración a la hora de preparar el entorno de desarrollo. Trataremos este tema en el siguiente post de esta serie.
¿Cómo solucionar esto? Automatizando estas tareas repetitivas por medio de un servidor de integración continua. No es el propósito de este artículo discutir los beneficios de esta práctica (para eso puede leerse este artículo de Martin Fowler), así que vamos a pasar directamente a la solución que puse en marcha.

Eligiendo un CI para Arena

Para los ansiosos, la implementación final de lo que contaré a continuación (incluyendo el próximo post) puede verse en el repositorio de Arena en GitHub. De todos modos, recomiendo leer cada una de las decisiones que tomé para entender qué es lo que hace el CI cada vez que se sube código nuevo al repositorio.

CIs Candidatos

Además de que fuera gratuito para Open Source Software (OSS), se necesitaba que cumpliera tres características:
  1. que fuera fácil de configurar y que no necesitara hosting propio.
  2. que soportara Java de forma nativa.
  3. que tuviera algún mecanismo para subir el settings.xml, necesario para poder hacer el deploy a Sonatype.
Entonces, en ese orden, descarté estos 3 productos:
  1. Jenkins, quizás el más conocido y flexible de los que voy a mencionar, pero con el overhead de tener que hostearlo en servidor propio y configurar todos los plugins.
  2. Semaphore, que suele ser mi opción preferida, pero como todavía no soporta Java “out of the box” es necesario bajar Maven en cada build.
  3. Y por último, drone.io, donde no encontré cómo solucionar el problema del settings.xml.
Finalmente mi elección fue Travis, obviamente en su versión para OSS.
(Un comentario al margen: Travis tiene también una versión para repositorios privados y, gracias a un acuerdo con GitHub, la ofrecen de manera gratuita e ilimitada para estudiantes mediante el student developer pack.)

Configurando Travis

La configuración de Travis está basada en el principio de convention over configuration. Para empezar a compilar y correr nuestros tests, basta crear un archivo llamado .travis.yml e indicar en su interior en qué lenguaje está realizado nuestro proyecto, en nuestro caso Java. El primer archivo de configuración se veía así:
language: java
¿En serio? ¿ya está? No del todo, pero ya estamos en condiciones de probar que funciona avisándole a Travis que monitoree el proyecto (esto se hace desde tu perfil) y luego haciendo un git push de algún cambio (aunque una mejor idea sería crear una branch de prueba y hacer un pull request).
Por defecto, Travis empezará a monitorear el repositorio y disparará un build por cada commit que se suba a cualquiera de sus branches, incluyendo pull requests. Una vez concluido dicho build, se encargará de notificar a GitHub el resultado, quien a su vez nos lo mostrará a nosotros como se ve en la siguiente imagen:
Pull requests validados por Travis
Con esa simple línea de configuración que le dimos, lo que se ejecuta es el default para Java, que consta de dos pasos:
  1. mvn install -DskipTests=true, baja todas las dependencias y compila el proyecto. ¿Y para qué le pone ese flag si también queremos que corra los tests? Cuando algo anda mal, Travis diferencia entre un build errored y uno failed, donde el primer estado está asociado con un error en la instalación (no compila, no se encontró alguna dependencia) y el segundo con alguna validación que se ejecuta (normalmente un test fallido). Entonces si llegara a fallar la instalación, ni siquiera se corren los tests y sabemos con certeza que el resultado es errored
  2. mvn test (no necesita explicación)
Hasta acá llega el primer post de esta duología. En el siguiente post explicaré los pasos necesarios para publicar la aplicación en el Maven Central Repository, utilizando Sonatype OSS como intermediario.
¡No dejen de compartir sus proyectos, ideas o experiencias en los comentarios!

No comments:

Post a comment