12/18/2004

12/14/2004

Continuous Integration

Continuous Integration

Este artículo de Martin Fowler y Mathew Foemmel discute sobre la necesidad de que los proyectos de desarrollo de software dispongan de una arquitectura de integración continua. Para ello, introducen la herramienta de opensource, CruiseControl que permite automatizar este proceso. En este post resumo sus características básicas, aunque recomiendo leer el artículo original, que no es tan largo ;)

La idea básica es la de disponer constantemente de una "build" estable, es decir, que la creación esté automatizada, y que exista un core de pruebas que se ejecuten en cualquier momento deseado y aseguren un mínimo. En muchos proyectos se realizan "builds" diarias, pero otras filosofías, como la de eXtremeProgramming plantean que las builds se realicen constantemente, cuando sean necesarias.

Las necesidades básicas para que todo funcione son las siguientes:
  • El código reside en un único lugar (versión actual, y previas): para ello ha de utilizarse una herramienta de configuración con control de fuentes y control de versiones. CVS es quizá la herramienta más utilizada de este tipo.
  • Y no sólo el código: también todo fichero susceptible de cambio en el proceso de construcción de software: scripts, properties, esquemas, documentación, ... todo aquello que NO SE GENERE AUTOMÁTICAMENTE.
  • El proceso de build debe ser tan sencillo como utilizar un único comando.
  • También con un único comando debería poder lanzarse una suite de pruebas de sistema.
  • Consecuentemente, todo el mundo debería de ser capaz, en todo momento, de disponer de un buen ejecutable.

Por otra parte, una build "exitosa" ha de cumplir ciertas reglas para ser considerada como tal:

  • Todo el código fuente "checked out" se extrae.
  • Todo fichero se compila de cero.
  • Los objetos resultantes se enlazan y despliegan si es necesario (.jar). Estos dos últimos puntos requieren utilizar una "make tool" adecuada, más allá de scripts a mano. En Java, una herramienta open source muy usada es "Ant", anuque existe alguna otra, como Maven, que se basa en Ant y permite aún un mayor control.
  • El sistema se arranca automáticamente, y se lanza una suite de pruebas (como mínimo unas "smoke tests"). Las pruebas se basan en el enfoque de XP: test first. No se programa nada sin tener previamente implementada una prueba que sólo funcione si se desarrolla esa característica concreta -es discutible que esto sea posible en la práctica, en todos los casos, pero en sí es una "best practice" recomendable-. Para la realización de pruebas unitarias, el artículo recomienda JUnit (de la familia de xUnit).
  • Todo OK sin intervención "humana": eso es una build exitosa.

El "Master Build" que proponen corre en una sóla máquina, y es un proceso Java que se ejecuta continuamente ( a-la demonio):

  1. Si no hay build ejecutándose, el proceso chequea el repositorio de build cada pocos minutos.
  2. Si no hay nadie que hay realizado un check-in (hace cinco minutos o más, para evitar conflictos con gente que esté realizando un check-in en este preciso momento), sigue esperando.
  3. Si hay alguien, comienza el proceso de build.
  4. Si el proceso termina satisfactoriamente, se marcan las fuentes que fueron chequeadas con un "build number".
  5. El proceso de build envía un correo a los desarrolladores que hicieron check-in con un status del proceso (como dice el artículo, se considera de mala educación el irse del trabajo tras un "check-in" sin esperar a recibir este correo). Además, este status se almacena en un servidor web de la máquina de build para que pueda ser consultado.

Se recomienda realizar siempre builds completas, pero es cierto que en algunos entornos esto es imposible (cierto proyecto en el que estuve tardaba horas y horas), por lo que un esquema mixto (incremental durante el día y una full build por las noches) puede ser adecuado en esos casos.

Hasta ahora sólo nos hemos centrado en la build general. Hay que tener en cuenta que esta build debe poder ser recreada en local, para que cada desarrollador pueda probar que el check-in que va a realizar va a funcionar adecuadamente; para ello, cada vez que se vaya a empezar un nuevo desarrollo -tarea, caso de uso, ...-, hay que sincronizarse con la herramienta de control de código (un checkout completo). Por otra parte, los desarrolladores deberían intentar realizar un check-in diario, para que las builds tengan sentido.

CruiseControl se ocupa de realizar la build continua. En su web hay bastante información sobre cómo utilizar Ant por debajo para realizar esa build, pero también es posible utilizar otras herramientas, como la arriba mencionada Maven.