Integración continua

11.1 Introducción a integración continua

Integración continua es la práctica, en ingeniería del software, de unir todo el trabajo de diferentes desarrolladores en la versión final del proyecto. Esta práctica se ha hecho necesaria en prácticamente todos los entornos de desarrollo y en PHP, aunque no haya una forma estándar, hay herramientas que podemos utilizar para realizar este tipo de tareas.

Tanto en equipos con varios desarrolladores, como en proyectos de código abierto, los cambios a los que está sujeto un proyecto son constantes y generalmente rápidos, por lo que introducir herramientas de monitorización y mejora continua en la calidad del software ayudan a que los equipos mantengan unos varemos de calidad aceptables. Esta práctica es ventajosa tanto para la comunidad que está trabajando en el proyecto, como para los dueños del proyecto.

La integración continua reduce la cantidad de procesos repetitivos que los desarrolladores necesitan realizar cuando construyen o lanzan el software en el que están trabajando, y por lo tanto, reducen el riesgo o se adelantan en la detección de errores.

11.2 Proceso de integración continua

El proceso de integración continua es bastante sencillo, suponiendo que hemos escogido nuestras herramientas. Los pasos a seguir son los siguientes:

  • Un desarrollador finaliza una tarea y el cambio es integrado con el resto del proyecto.

  • La herramienta de integración continua detecta los cambios y ejecuta el conjunto de acciones por las que está configurado. Esto suele incluir tests unitarios, funcionales, de integración, generación de documentación a través de las anotaciones del código, métricas de calidad de código, compilación para lenguajes en los que fuera necesario, etc...

  • El sistema de integración continua notifica al/los desarrolladores en caso de que se produzca un fallo.

Con este sistema, la detección de errores queda automatizada y los errores localizados nada más un desarrollador haya terminado una tarea.

En el caso de que un proyecto tenga un conjunto de tests de integración grande, ejecutar los tests después de cada commit puede no ser una solución viable, dado que los tests funcionales son lentos. Para solventar esta situación, y otras situaciones especiales, las herramientas de integración continua pueden ser configuradas con gran cantidad de detalles.

11.3 Alternativas de herramientas para integración continua

Entre las distintas alternativas de productos de integración continua vamos a agruparlas entre las que necesitan ser instalados por nosotros y los productos online. Entre los primeros tenemos alternativas como Jenkins, PHPCI, TeamCity, Buildbot, Travis CI, Go Continuous Delivery, etc. Entre los sistemas online también contamos con Travis CI y otras alternativas como continuousphp, Bamboo, Codeship, etc.

En el mercado hay multitud de proyectos para solventar el problema de integración continua. Hemos agrupado las distntas opciones en función de los ejemplos que mostraremos a continuación. Para tener una visión más global y tener referencia más detallada podemos consultar el artículo de Wikipedia en inglés "Comparison of continuous integration software" [33], donde podemos ver una tabla con multitud de proyectos de integración continua clasificados por plataforma, licencia, si consta de builder para windows, sistema de notificación, integración con IDEs y otro tipo de integraciones.

Para ilustrar la forma de configurar un proyecto hemos decidido utilizar dos alternativas: Una instalación de Jenkins y la versión online de Travis CI para proyectos de código libre. Travis CI es gratuito para proyectos publicados bajo licencias de código abierto, por lo que podremos utilizarlo sin problemas.

11.4 Jenkins

Pese a que Jenkins [34] es un proyecto escrito en Java, la comunidad PHP lo ha aceptado y utilizado como herramienta de integración continua, ejecutando tanto PHPUnit como otras herramientas para monitorizar la calidad de código [45]. Algunas de estas herramientas son:

  • PHP_CodeSniffer: Herramienta para detectar violaciones en la estandarización del código elegida por el proyecto bajo la integración continua.

  • PHP_Depend: Analizador de código que genera determinadas métricas para asegurar la calidad de código, he indicar posibles refactorizaciones según dichas métricas.

  • PHP Mess Detector: Analizador de código que determina secciones de código muerto, posibles bugs o expresiones complejas.

  • PHP Copy/Paste Detector: Herramienta que encuentra fragmentos de código duplicado en una base de código.

Para ilustrar una integración, configuraremos el proyecto de Strings, mencionado en el capítulo 3.

11.4.1 Instalación de Jenkins en Linux

Lo primero que necesitamos es descargar el fichero binario ejecutable de Jenkins en la página oficial y ejecutar el comando:


java -jar jenkins.jar

Para instalar y ejecutar Jenkins hay otras alternativas, como instalar un contenedor utilizando Docker y utilizar la imagen correspondiente. Este proceso sería similar a la instalación que hicimos en el capítulo 8 con la instalación de WordPress" utilizando Docker*.

Otra alternativa en máquinas con la distribución Linux Ubuntu instalada podemos utilizar los paquetes oficiales siguiendo los comandos:

wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ 
            > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins

Para más información sobre la instalación recomendamos visitar la documentación oficial Jenkins [34].

Una vez instalado Jenkins podemos acceder a la aplicación abriendo un navegador y accediendo a la url http://localhost:8080, que es la configuración por defecto.

11.4.2 Configuración de plugins y otros paquetes

Dado que vamos a configurar nuestro proyecto XStrings utilizando GitHub [10], necesitamos tener instalado Git en la máquina donde ejecutaremos Jenkins. Además, necesitamos tener instalado Composer [11], dado que seguimos el estándar PSR-4 [2] para autolading, y las dependencias de testing de nuestro proyecto.

Jenkins es perfectamente configurable para desarrollos PHP, puesto que la comunidad ha creado multitud de plugins. En nuestro ejemplo haremos uso de algunos plugins. Para hacer uso tenemos que visitar la sección de configuración de Jenkins de la ejecución anteriormente lanzada bajo la URL http://localhost:8080, marcar los plugins deseados y pulsar el botón "Install without restart". Después de que todos los plugins estén instalados necesitamos reiniciar Jenkins.

Para nuestro proyecto vamos a instalar los siguientes plugins:

  • Clover PHP plugin: Lo utilizaremos para integrar los reportes en formato Clover.

  • GIT plugin: Necesitaremos este plugin para acceder a Github, descargar el código y detectar nuevas versiones.

11.4.3 Configuración de nuestro proyecto XStrings

Para configurar nuestra librería, lo primero que necesitamos es crear un proyecto en nuestro Jenkins. Para ello daremos al link "New Item". A continuación rellenaremos los datos necesarios para integrar nuestro proyecto:

  • Rellenaremos "Item name:" con XStrings.
  • Marcaremos la opción "Freestyle project".
  • Pulsamos el botón "Ok".

A continuación se nos presentará la página de configuración del proyecto.

Como indicamos anteriormente, nuestro proyecto integrará el código publicado en un repositorio público de https://github.com/josgilmo/xstring, por lo que lo marcaremos en la sección "Source Code Management" la opción "Git" y rellenaremos el campo "Repository URL" con la url .git de XStrings. En el campo "Branches to build", rellenaremos con "./master", que es la rama que deseamos integrar.

Para nuestro proyecto, hemos decido realizar las siguientes acciones:

  • Ejecutar los tests unitarios.
  • Utilizar la generación del fichero clover.xml para revisar la convertura de tests unitarios.
  • Verificar que la estandarización de código es el deseado.

Estas acciones las configuraremos añadiendo nuevas secciones pulsando en "Add build step", seleccionando "Execute shell" y rellenando cada formulario con el comando correspondiente.

Por último crearemos las acciones posteriores a la ejecución de nuestra integración, en nuestro caso hemos decidido:

  • Publicar resultados del análisis estático de código.
  • Publicar resultados de cobertura de código.
  • Envío de notificación por mail en caso de que falle el proceso de integración.

Para crear estos pasos de post-proceso pulsaremos en "Add post-build action" y seleccionaremos la correspondiente del desplegable de acciones.

Con esta configuración, cada vez que realicemos una modificación sobre la rama master de nuestro proyecto, Jenkins lanzará el proceso de integración y podremos ver los resultados.

11.4.5 Jenkins PHP

Jenkins PHP [46] es una web especializada en información para configurar Jenkins como sistema de integración continua para proyectos en PHP. Está desarrollado por Sebastian Bergmann, creador de PHPUnit. En esa web explican cuales son los plugins necesarios para integrar un proyecto en PHP así como una plantilla de ejemplo basada en Apache Ant para configurar de una forma completa nuestro servidor Jenkins.

11.5 Travis CI

Travis CI [35] es un proyecto de integración continua con varias versiones. Una versión de código libre alojada en https://travis-ci.org, en la que podemos configurar cualquier proyecto de código libre publicado en GitHub. Y otra versión de pago, alojada en http://travis-ci.com, en la que podemos testear cualquier repositorio privado. En esta sección nos centraremos en la versión gratuita para proyectos de código libre.

La principal ventaja por la que utilizar una herramienta como Travis CI es el ahorro que sopone la instalación y configuración de un proyecto bajo integración continua. Además, como Travis CI trabaja en un entorno basado en contenedores, crear configuraciones específicas relativamente complejas es trivial, frente a la instalación de Jenkins. Por ejemplo, supongamos que el proyecto que queremos poner bajo integración continua es un proyecto de código abierto y queremos que sea funcional en la mayor parte de versiones de PHP posibles. Utilizando Jenkins necesitaríamos instalar las distintas versiones de PHP, lo cual no es un trabajo simple, y crear el proceso de integración con cada una de las ejecuciones. Para Travis CI, pese a que es igual de complejo, la herramienta lo proporciona de forma transparente y sencilla.

Trabajar con Travis CI no son todo ventajas. Las dependencias o versiones con las que podemos trabajar vienen dadas por la herramienta y no es posible escoger otra, que en determinados casos podría ser necesaria. A fecha de hoy, la versión más antigua de PHP soportada por Travis CI es 5.3.8, he integrar un proyecto con una versión anterior podría ser no posible o producir problemas.

Además, herramientas de análisis estático de código, reportes de cobertura de código, etc,.. no son proporcionadas por Travis CI, aunque existen otros proyectos que pueden complementarlo, que dan soluciones especializadas para cada parte de la integración continua.

11.5.1 Configuración y uso de Travis CI

Para crear un proyecto en Travis CI, necesitamos tener una cuenta en Github.com y crear una cuenta en Travis CI asociada a la de GitHub a través del protocolo de autentificación Oauth [29] (visto en el capítulo 10 "Testeando API".

Una vez aceptado el acceso a GitHub por parte de Travis CI, seremos redireccionados a una página de Travis CI en la que veremos nuestros repositorios de GitHub. Clickando en los distintos botones On/Off habilitaremos la integración del proyecto deseado en Travis CI. Además, necesitamos configurar los "Services Hooks" en nuestra configuración de cada proyecto, para que en GitHub aparezcan las notificaciones de estado de la integración continua.

Para que se produzca la ejecución de Travis CI, necesitamos configurar el contenedor donde se producirá la integración en la forma que necesita nuestro proyecto. Los contenedores de Travis CI tienen con la mayor parte de los paquetes necesarios para ejecutar un proyecto de integración para PHP. Al igual que hicimos con Jenkins, necesitamos instalar las dependencias y crear el autoloading a través de Composer. Esto, y el resto de configuraciones lo especificaremos en el fichero .travis.yml, que debe estar en la raiz de nuestro proyecto.

El código Yaml que especifica nuestra integración continua es:


language: php

php:
  - 5.4
  - 5.5
  - 5.6
  - 7.0

before_script:
  - composer install --dev

script: vendor/bin/phpunit --configuration phpunit.xml

notifications:
    email:
        - example.mail@example.com

Con esta configuración estamos especificando lo siguiente:

  • Es un proyecto PHP. Travis CI soporta varios lenguajes de programación, por lo que es necesario indicarle el lenguaje la configuración actual.

  • La integración será ejecutada para las versiones PHP5.4, PHP5.5, PHP5.6 y PHP.7. Como comentábamos anteriormente, este proceso en Jenkins sería tedioso puesto que tendríamos que realizar al instalación de cada una de las versiones en la máquina donde ejecutar el proceso de integración.

  • Antes de ejecutar el script de integración instalaremos las dependencias de Composer para un entorno de desarrollo.

  • El script ejecutará los tests con la configuración especificada en el fichero phpunit.xml

  • En caso de que el build falle, se enviará una notificación al correo indicado.

Como podemos ver, teniendo una cuenta de Travis CI y el proyecto a integrar alojado en GitHub, configurar un entorno de integración continua consiste solamente en editar un pequeño fichero en formato Yaml y situarlo en la raíz de nuestro proyecto. La comodidad que ofrece este tipo de servicios frente a la alternativa instalada por nosotros es claramente visible, aunque la perdida de flexibilidad y posibilidades que ofrecen configuraciones propias en Jenkins también son considerables.

results matching ""

    No results matching ""