en Integración continua

Anatomía de una rutina PHING

Una vez que tenemos instalado un entorno de integración contínua para PHP, incluyendo un subversión, un hudson y jira, por ejemplo, es probable que todavía no sepamos muy bien qué podemos hacer con él (y una vez que sepamos qué PODEMOS hacer, podremos pensar en qué QUEREMOS hacer). Sobre esto tendría que escribir una tonelada de artículos (y, probablemente, acabe haciéndolo… :-) ). Pero vamos a centrarnos ahora en cuál es el papel de en un entorno de integración contínua.

Para el que no lo sepa, phing es un port de Ant para PHP. Tanto Phing en PHP como Ant en Java, permiten definir un archivo XML con una serie de tareas que se ejecutarán (targets) para, por ejemplo, ejecutar comandos svn, creación-destrucción-cambio de directorios y archivos, permisos, o ejecución de las pruebas unitarias, y un largo etc.

¿Pero eso no se puede hacer con un simple script de terminal? Efectivamente. Phing lo que promete es que al hacerlo definiendo un XML que te permitirá mantener un script de manera más sencilla e incluso reutilizarlo (parametrizándolo) entre diferentes proyectos, etc.

¿Pero eso de los XML´s no es “muy Java” y Ruby no nos ha enseñado que son mejores los DSL´s internos que los DSL´s externos? Efectivamente, mucho mejor sería que Phing se hubiera fijado en Rake que en Ant o Maven y las rutinas Phing se escribieran directamente en PHP y no en un XML….

¿Por qué usar Phing y no directamente Ant? Ant está más extendido y se integra mejor con cosas como Hudson. Pero con Ant, si quieres crear tus propias tareas, tendrás que programarlas en Java. Si extiendes las tareas de Phing creando las tuyas propias, lo harás en PHP… Con Phing, además, te aseguras tener tareas para phpunit, phpcs, etc…

Le he dado muchas vueltas a cómo explicar qué papel juega Phing en todo esto, y creo que lo mejor es ver directamente el esqueleto de una rutina Phing:

 
<?xml version="1.0" encoding="UTF-8"?>
<project name="coiig automation" basedir="." default="default">
 
 
    <property name="svnserver.path" value="  ....   " />
 
 
    <target name="default">
        <echo msg="Choose an option:"/>
        <echo msg="construct"/>
        <echo msg="metrics"/>
        <echo msg="  clean"/>
        <echo msg="  phpdoc"/>
        <echo msg="  phpunit"/>
        <echo msg="  phpcs"/>
        <echo msg="  phpmd"/>
        <echo msg="testing"/>
        <echo msg="production"/>
    </target>
 
    <target name="construct">
                   ....... 
    </target>
 
    <target name="metrics"
        depends="clean, phpunit, phpdoc, phpcs, phpcpd, phpmd">
    </target>
 
    <target name="clean">
                  .......   
    </target>
 
    <target name="phpdoc">
               .......
    </target>
 
    <target name="phpunit">
         ........
    </target>
 
    <target name="phpcs">
             .......
    </target>
 
    <target name="phpcpd">
              .......
    </target>
 
    <target name="phpmd">
            ........
    </target>
 
    <target name="testing">
 
 
         .........
    </target>
 
    <target name="production">
       ........
    </target>
</project>

Ésta rutina se guardará en un archivo llamado build.xml, preferiblemente en la raiz de nuestro proyecto.

Si, simplemente, escribimos “phing” en la la raiz de nuestro proyecto, obtendremos la siguiente respuesta:

Este pequeño menú se muestar porque hemos hecho que nuestro target “default” simplemente nos muestro las opciones que tenemos. Si ejecutamos:

  • “phing construct”: phing creará las carpetas que necesitemos para nuestro proyecto, cambiará permisos, creará links, etc… Usaremos esta tarea cuando nos traigamos el código a nuestro ordenador de desarrollo (tras un svn checkout, por ejemplo), o al traernos el código en testing y antes de ejecutar unos test de integración.
  • “phing metrics”: es un target que lo único que hace es agrupar los targets “clean”, “phpdoc”, “phpunit”, etc… Podremos usarlos por separado. Por ejemplo, si queremos simplemente ejecutar nuestro test unitarios, haremos “phing phpunit” y si queremos generar nuestra documentación haremos “phing phpdoc”. Esta tarea la utilizaremos en desarrollo cuando queramos, pero sobre todo la utilizará Hudson para generar sus métricas para el PMD, el CheckStyle, etc….
  • “phing testing” y “phing production”. Ejecuta los comandos necesarios para poner en producción (o en testing) un tag de . Quizá ejecutando unos comandos rsync, etc…

Nota: En un entorno ágil ideal, la puesta en producción debería ser tan fácil como ejecutar un solo comando. Por desgracia esto es muy difícil, y aunque es mi objectivo llegar a conseguirlo, no voy a ocultar que algunas de mis puestas en producción distan bastante de ser tan fáciles como escribir “phing production” y punto… :-)

No entro aquí a detallar lo que debería ponerse en cada target. Primero porque mi solución puede no valer para cualquier proyecto y segundo por no extenderme infinitamente. Prometo seguir ahondando en el tema en futuros artículos…

Escribe un comentario

Comentario

  1. Quisiera un ejemplo completo, por que tengo entendido que se integra con phpUnderControl.

    Y si me pudieras proposionar una guia rapida de instalación en Ubuntu.