domingo, 4 de noviembre de 2012

Repositorios en Integración Contínua

Uno de los apartados a destacar en la integración continúa es el uso del repositorio. Es decir, el buen uso.

Cualquier herramienta se puede utilizar para el bien o para el mal, y ciertamente un repositorio mal utilizado nos puede llevar al fracaso por una de las vías más rápidas.

Son frecuentes los casos de versiones incorrectas, clases que no compilan, casos de prueba que dejan de funcionar, y errores q el lunes estaban solucionados y sospechosamente vuelven a escena el viernes.

Una de las principales normas parece ser: subir al repositorio código compilable, probado y compatible con el resto de módulos.

Otros casos curiosos son los de aquellos desarrolladores que parecen inmersos en su propio mundo, con su copia local de código a la que deberían llamar "Mi Tesoro", y que sólo liberan cuando hay ciertas alineaciones planetarias. Tan perjudicial como el que sube código corrupto.


Es por tanto importante establecer las normas del juego antes de iniciar el trabajo con un repositorio.

Otro de los aspectos importantes a determinar en la elección del repositorio es si el repositorio estará alojado en la propia compañía, o si será un servicio proporcionado por un tercero. 


  • En el primer caso habrá que considerar los costes del servicio así como el mantenimiento (instalación, backups, etc ). 
  • En el segundo caso habrá que estudiar las características de los distintos proveedores de dicho servicio.

 También es importante establecer cual va a ser el software de gestión del repositorio, subversion (svn) o git son los más comunes hoy en día. Tendremos que charlar más ampliamente sobre estos en otro momento.




A la hora de elegir el repositorio es bueno haber probado alguno, yo por esto me decanto por un repositorio gratis, con lo que puedo probar a un cierto proveedor y posteriormente puedo contratar el plan adecuado para mis necesidades. 

Una comparativa sobre repositorios svn lo podéis encontrar en svn repository hosting.

 

lunes, 21 de mayo de 2012

Utilizando el log en Gradle

Hemos visto que los ficheros de gestión de proyecto de gradle no son más que código, con lo que podemos sacar notificaciones por consola utilizando la sentencia println:

println sourceSets.main.java.srcDirs

Como ya hemos visto en un post sobre java, utilizar la sentencia println para mostrar mensajes de estado por consola (o fichero) no nos proporciona mucha flexibilidad, por tanto una buena política es la de usar un framework que nos permita elegir la granularidad de los mensajes de log.

Con gradle podemos tener distintos niveles de log, utiliza SLF4J, y así podemos diferenciar los mensajes que queremos ver cuando se realiza la construcción de nuestro proyecto de aquellos que se mostrarán cuando estramos preparando el build.gradle y algo no funciona exactamente como deseamos.

Los niveles de log con que contamos son:

  • ERROR Muestra los mensajes de error.
  • QUIET  Nivel específico de Gradle, no muestra mensajes. Si ejecutamos gradle en este nivel (opción –q al ejecutar), sólo se mostraran mensajes configurados para este nivel. Es el nivel más “silencioso”
  • WARNING Muestra los mensajes de advertencia
  • LIFECYCLE Nivel específico de Gradle, habitualmente son los mensajes de gradle respecto al proceso de construcción. Si ejecutamos gradle es el nivel por defecto.
  • INFO Muestra los mensajes de información
  • DEBUG Muestra los mensajes de depuración

Cambio de nivel de log en la línea de comandos

Cuando ejecutamos gradle podemos elegir en qué nivel de log se va a realizar la ejecución.

Las opciones a nivel de línea de comandos son:

  • <defecto> Si no configuramos ninguna opción se mostrarán los niveles LIFECYCLE y superiores, esto es ERROR, QUIET, WARNING y LIFECYCLE.
  • -q Se mostrarán los niveles QUIET y superior.
  • -i Se mostrarán los niveles INFO y superior.
  • -d Se mostrarán los niveles DEBUG y superior, con lo que cualquier mensaje de log saldrá por consola.

Escribiendo mensajes de log

Como vimos podemos escribir en el fichero build.gradle:

println ‘Texto de log con println’

Usando la propiedad logger de cualquier script de construcción de proyectos (build.gradle) podemos codificar en qué nivel queremos que salgan los mensajes:


logger.quiet("Mensaje que siempre se muestra")
logger.error("Mensaje de nivel ERROR")
logger.warn("Mensaje de nivel WARNING")
logger.lifecycle("Mensaje de nivel LIFECYCLE")
logger.info("Mensaje de nivel INFO")
logger.debug("Mensaje de nivel DEBUG")

Si tecleamos gradle en la línea de comandos podemos ver:

>gradle
Mensaje que siempre se muestra
Mensaje de nivel ERROR
Mensaje de nivel WARNING
Mensaje de nivel LIFECYCLE
:help

Welcome to Gradle 1.0-rc-3.

To run a build, run gradle <task> ...

To see a list of available tasks, run gradle tasks

To see a list of command-line options, run gradle --help

BUILD SUCCESSFUL
Total time: 5.266 secs


Si queremos ver todos los mensajes de log tecleamos gradle –d
                  
El resultado es un tanto extenso, por eso no lo muestro.


Creando nuestro propio logger

Hemos visto que podemos utilizar la propiedad logger para mostrar nuestros mensajes de notificación, pero como nuestros ficheros de configuración de proyecto son código, podemos crear nuestro propio logger. De esta forma creamos un fichero build.gradle de la siguiente forma:


import org.slf4j.Logger
import org.slf4j.LoggerFactory

Logger slf4jLogger = LoggerFactory.getLogger("MiLogger")
slf4jLogger.warn("Mi propio Logger ha sido creado")



El resultado obtenido es:

>gradle
Mi propio Logger ha sido creado
:help

Welcome to Gradle 1.0-rc-3.

To run a build, run gradle <task> ...

To see a list of available tasks, run gradle tasks

To see a list of command-line options, run gradle --help

BUILD SUCCESSFUL

Total time: 3.719 secs


martes, 15 de mayo de 2012

Integrando gradle y eclipse


En el post anterior estuvimos viendo esta fantástica herramienta para construcción de proyectos de software (Java) que es Gradle. Teníamos desarrollado un pequeño proyecto, y copiamos el código fuente de este proyecto a las carpetas oportunas donde gradle toma por defecto el código y el código de las pruebas unitarias.  Es decir, comenzamos la casa por el tejado.

Creando proyectos eclipse desde Gradle

Comencemos por el principio, en mi caso utilizo Eclipse como IDE, lo que voy a hacer es crear un proyecto que pueda importar fácilmente en Eclipse y después configurar Eclipse para poder correr Gradle desde el IDE.

Primero creamos un fichero build.gradle.

apply plugin: 'eclipse'
repositories {
    mavenCentral()
}


Este fichero de construcción nos va a ayudar a crear la estructura adecuada de ficheros y carpetas para poder importar en eclipse el proyecto.

Ejecutamos gradle eclipse y vemos en consola lo siguiente

E:\Gradle\eclipse>gradle eclipse
:eclipseProject
:eclipse

BUILD SUCCESSFUL

Total time: 4.359 secs


Como vimos también podemos incluir algunas dependencias:

apply plugin: 'java'
apply plugin: 'eclipse'
repositories {
    mavenCentral()
 
dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

Ejecutar gradle eclipse

E:\Gradle\eclipse>gradle eclipse
> Building > :eclipseClasspath > Resolving dependencies 'detachedConfiguration1'
:eclipseClasspath
Download http://repo1.maven.org/maven2/commons-collections/commons-collections/3.2/commons-collections-3.2-sources.jar
:eclipseJdt
:eclipseProject
:eclipse

BUILD SUCCESSFUL

Total time: 8.984 secs


Las diferencias en el primer proyecto, y el segundo son claras, ya que en el segundo proyecto puedes ver como se incluye el classpath a las librerías necesarias. Nos únicamente queda importarlo en Eclipse mediante File->Import->Existing proyects into workspace.

Ejecutando Gradle desde Eclipse

Se puede configurar Eclipse para ejecutar Gradle, los pasos que debemos seguir son los siguientes:

Run -> External Tools -> External Tools Configurations...
Seleccionar Program, en el menu de la izquierda, y crear una nueva configuración con el botón de arriba a la izquierda.
Procedemos a configurar cómo se ejecutará Gradle:
Name: entramos Gradle (por ejemplo) como nombre de la aplicación que lanzaremos.
Location: tenemos que seleccionar GRADE_HOME\bin\gradle.bat
Working Directory: introducimos ${project_loc} para que ejecute gradle en el proyecto en el que estemos trabajando.
Arguments: introducimos ${string_prompt} para que pregunte por un nombre de tarea para gradle cuando sea ejecutado (por ejemplo como vimos en el anterior post: build, o como hemos visto en este post eclipse).


martes, 8 de mayo de 2012

Descubriendo GRADLE



Gradle es una de estas herramientas que te da buen feeling desde que la descubres, te permite gestionar y construir proyectos de software (Java). Te ofrece la versatilidad de Ant, la rigidez de Maven, tiene muy buena documentación, y además los scripts de construcción de tu proyecto no son xml sino que son código.

Instalación

Instalar Gradle teniendo una jdk cuya versión  sea superior a 1.5 es tan sencillo como descomprimir el zip que puedes descargar de www.gradle.org, añadir GRADLE_HOME/bin a la variable de entorno PATH. Con esto sólo tienes que teclear gradle-v y comprobar que sale algo como:

------------------------------------------------------------
Gradle 1.0-rc-3
------------------------------------------------------------
Gradle build time: domingo 29 de abril de 2012 23H51' UTC
Groovy: 1.8.6
Ant: Apache Ant(TM) version 1.8.2 compiled on December 20 2010
Ivy: 2.2.0
JVM: 1.7.0_03 (Oracle Corporation 22.1-b02)
OS: Windows XP 5.1 x86


Java plugin

Una vez instalado nos centramos en crear nuestro primer proyecto, yo por mi parte he cogido un pequeño proyecto en el que demostraba como generar dos clases y ejecutar las pruebas unitarias de estas dos clases.

Como mencionaba gradle nos permite introducir código (groovy) en nuestros scripts de construcción de proyectos, podemos incluir sentencias como las siguientes para sacar por consola la configuración de gradle:

println "Code" //Código principal del proyecto
println sourceSets.main.java.srcDirs
println "Classes" //Clases generadas del proyecto principal
println sourceSets.main.output.classesDir

println "Tests" // Código de pruebas del proyecto
println sourceSets.test.output.classesDir


Usando la configuración por defecto gradle asume que la estructura del proyecto es la siguiente:

src/main/java  código fuente java
src/test/java  código fuente de las pruebas

Con lo que depositamos ahí nuestro código desarrollado anteriormente.

Gradle está construido basado en plugins, iremos viendo algunos de ellos, para este primer ejemplo veremos el plugin Java. Este plugin añade capacidades de compilación, pruebas y empaquetamiento a un proyecto.

Para declarar la utilización del plugin sólo tenemos que incluir la sentencia:

apply plugin: 'java'

Declaramos así mismo los repositorios del proyecto, en nuestro caso reutilizamos los repositorios de maven.

repositories {
    mavenCentral()
}

Añadimos las dependencias al proyecto. Como vemos hay dos grupos de dependencias, por un lado las de la tarea de compilación y por otro lado las de la tarea de pruebas unitarias.

dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

Podemos declarar también la generación de un archivo jar, que por defecto se genera de la siguiente forma:

[baseName]-[appendix]-[version]-[classifier].[extension]

Siendo baseName, appendix, version, classifier y extension atributos, las tareas en gradle son objetos, de la clase Jar. Igual podemos construir el fichero manifest:

jar {
    baseName= 'junitBlog'
    version = '1.0'
    manifest {
        attributes 'Implementation-Title': 'Atherindarl project', 'Implementation-Version': version
    }
}

Creo un jar llamado junitBlog-1.0.jar.

Juntando los diversos elementos en un único fichero build.gradle

apply plugin: 'java'


println "Code"
println sourceSets.main.java.srcDirs
println "Classes"
println sourceSets.main.output.classesDir
println "Tests"
println sourceSets.test.output.classesDir

jar {
    baseName= 'junitBlog'
    version = '1.0'
    manifest {
        attributes 'Implementation-Title': 'Atherindarl project', 'Implementation-Version': version
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

test {
    systemProperties 'property': 'value'
}



Tecleando gradle build vemos como las distintas tareas de gradle se van ejecutando.

>gradle build

Code
[E:\Gradle\junit\src\main\java]
Classes
E:\Gradle\junit\build\classes\main
Tests
E:\Gradle\junit\build\classes\test
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 9.484 secs


Gradle nos ofrece la estructura de tareas básicas que puede tener un proyecto: compilar, probar, generar jar. Podemos añadir código a nuestro build.gradle, y diversos plugins dependiendo de nuestras necesidades que nos permiten una gran flexibilidad.