Integración Contínua I – Gradle

Introducción

Podemos leer en Wikipedia que la integración continua es un modelo informático propuesto inicialmente por Martin Fowler que consiste en hacer integraciones automáticas de un proyecto lo más a menudo posible para así poder detectar fallos cuanto antes. Entendemos por integración la compilación y ejecución de tests de todo un proyecto.

El proceso suele ser, cada cierto tiempo (horas), descargarse las fuentes desde el gestor de versiones compilarlo, ejecutar tests y generar informes.

Yo uso git como gestor de versiones, guardando el código en github.com, como ya sabéis. La herramienta de compilación por defecto en Eclipse es ant, pero dado que Google ha marcado el camino hacia Gradle, optaremos por usarlo también nosotros. Sonar es una herramienta que analiza nuestro código y nos informa sobre código duplicado, estándares de codificación, pruebas unitarias, cobertura de código, complejidad ciclomática, posible errores, comentarios y diseño del software. Con el servicio testflight podremos subir nuestra apk para que un grupo de testers (a los que habremos invitado a nuestro “equipo”) puedan ponerla a prueba. Y para que no sea una carga tener que ir usando tantas herramientas, jenkins nos permite crear tareas para realizarlas secuencialmente y, si queremos, programarlas para que se ejecuten periódicamente.

En esta serie de artículos, explicaré cómo instalar las herramientas y configurar los servicios en Ubuntu (linux), que es el sistema operativo con el que trabajo. Los usuarios de Windows quizá tengan que seguir algún paso diferente en lo tocante a la instalación y temas de variables de entorno, pero la configuración y el uso debería ser el mismo.

Gradle

Gradle se define a sí mismo en su página web como “Gradle is build automation evolved. Gradle can automate the building, testing, publishing, deployment and more of software packages or other types of projects such as generated static websites, generated documentation or indeed anything else.”. En castellano sencillo, viene a decir que Gradle es un compilador automatizado con esteroides. Cuando terminemos nuestra instalación de Gradle, podremos con un sencillo comando de Terminal ejecutar una compilación que, inmediatamente, genere un apk ya firmado (sin tener que pasar por los pasos de eclipse de Archivo > Exportar… etc).

Instalación

Descarga

Iremos a la página de descargas de Gradle y elegiremos la versión 1.6 del desplegable “previous releases”. A fecha de redacción de este artículo (18/sep/2013), la versión estable actual 1.7 no es compatible con la compilación de proyectos Android, por lo que usaremos la última de que tenemos constancia que sí funciona para lo que queremos.

Descomprimimos la carpeta y la dejamos en nuestra $home, sin la versión en ella. De ese modo, deberíamos tenerla en /home/miusuario/gradle.

Configuración

La configuración de Gradle pasa por meter dos rutas en variables de entorno. Como no querremos tener que estar usando export cada vez que iniciemos sesión, editaremos el fichero .profile que tenemos en nuestra $home. Debe quedar tal que así:
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
    fi
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

# Android tools
export PATH=${PATH}:~/android/tools
export PATH=${PATH}:~/android/platform-tools
export PATH=${PATH}:~/gradle/bin
export ANDROID_HOME=/ruta/absoluta/hacia/android-sdks

Las líneas en azul son las que nos interesan. La primera añade la ruta al directorio de ejecutables de Gradle al $PATH, de manera que podamos invocar la herramienta sin precisar la ruta dónde está. La segunda la necesita Gradle para encontrar los sdks de android y así poder compilar nuestros proyectos Android.

Uso

Para poder usar Gradle con nuestros proyectos, debemos tener un par de ficheros en ellos. Obligatorio es el build.gradle, en el que le indicaremos que el proyecto es Android, cuáles son las librerías externas (.jar), la versión objetivo del sdk (targetSdkVersion en el Manifest), etc. Ejemplo:

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:0.4+'
    }
}

apply plugin: 'android'

dependencies {
    compile files('libs/android-support-v4.jar')

}

android {
    buildToolsVersion "17.0"
    compileSdkVersion 18

     sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aild.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        instrumentTest.setRoot('tests')
    }
}

Vemos la línea en rojo, que es dónde debemos introducir todas las librerías .jar que esté usando nuestro proyecto. La que he dejado de ejemplo es la support library, pero cualquier otra que se quiera usar debe figurar ahí con su ruta, si bien lo habitual es que estén todas juntas dentro de libs/.

Guardamos esto como “build.gradle” en la raíz de nuestro repositorio. Luego, en el Terminal, nos moveremos al mismo directorio y ejecutaremos el comando

gradle build

Veremos que se genera en nuestro repositorio un directorio build/ dentro del cual, entre otros, está el directorio apk/, donde se generan nuestras aplicaciones.

miApp-debug-unaligned.apk : la app sin firmar y sin pasar por el optimizador zipalign.
miApp-release-unsigned.apk : la app sin firmar, pero optimizada por zipalign.

Ahora vamos a añadir un fichero de propiedades que nos ayude a firmar la apk. Para ello tendremos que tener nuestra keystore dentro de nuestro repositorio. Hecho eso, podemos crear nuestro gradle.properties como sigue:

keyStore=alberovalley.ks
keyStorePassword=miPasswordDeEsteKeystore
keyAlias=AlberoValley
keyAliasPassword=MiPasswordDeEstaFirma

Eclipse trae una herramienta para crear un Almacén de Claves (keystore) y las claves (firmas, cada cual tiene un “alias”) que almacena. En androideiti.com tienen una guía para firmar aplicaciones en la que cubren la parte de la creación del Almacén y la clave. Creado el fichero, hay que recordar tener al menos una copia dentro de nuestro repositorio. En mi caso, dicho fichero es alberovalley.ks y está en la raíz del mismo, por lo que el valor para keyStore (que es dónde guardo la ruta al Almacén de Claves) es el propio nombre del fichero. Para acceder a las diferentes claves que guarda un Almacén, tienes una contraseña, que aquí vemos en keyStorePassword. Dentro puede haber mas de una clave, por lo que se usan alias para identificarlas. Yo, original que soy, he llamado a mi firma AlberoValley y como tal la identifico en keyAlias. Por último, en keyAliasPassword ponemos la contraseña que nos permite firmar con nuestra clave.

Con esto listo, sólo tenemos que añadir unas líneas al final de nuestro build.gradle para que nos saque una apk ya firmada:

android {
    signingConfigs {
        release
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

if (    project.hasProperty('keyAlias') &&
    project.hasProperty('keyAliasPassword') &&
    project.hasProperty('keyStore') &&
    project.hasProperty('keyStorePassword')

    ) {
    android.signingConfigs.release.keyAlias = keyAlias
    android.signingConfigs.release.keyPassword = keyAliasPassword
    android.signingConfigs.release.storeFile = file(keyStore)
    android.signingConfigs.release.storePassword = keyStorePassword    
}

Aquí le decimos primero que queremos firmar el apk, y después que los datos del almacén de claves que guarda nuestra firma los encuentra en el gradle.properties bajo esas variables.

Ahora, si volvemos a ejecutar el comando

gradle build

y cuando todo termine OK, vamos al subdirectorio build/apk/ y vemos, entre otras cosas, lo siguiente:

miApp-release.apk: ésta es nuestra app firmada y optimizada, lista para subirse al Play Store. Las otras apk que salen son desechables.

Conclusión

Con esto ya tenemos una forma muy rápida y sencilla de compilar y firmar sin necesidad de tener que estar introduciendo las tediosas contraseñas en la interfaz de Eclipse. Bien configurado, un comando de Terminal y tenemos nuestras apks firmadas calentitas, con lo que nos ahorra de tiempo a la hora de testear, ya que los dispositivos Android no admiten dos apks de mismo nombre de paquete (com.alberovalley.miapp) siendo una sin firmar (de desarrollo o debug, las que hemos visto hasta ahora) y otra firmada (que hemos cubierto hoy). Además, si tienes un grupo de testers, quieres darle la versión firmada, porque es mas cómodo y transparente para ellos y, además, porque si la app guarda datos, no tienen que desinstalar la de desarrollo y perder lo que hayan introducido, sino que van instalando las firmadas una sobre otra y, una vez en producción, sólo tienen que ir aceptando las actualizaciones.

Agradecimientos

La presente serie de artículos ha sido posible gracias a las inestimables ayuda y paciencia de @spCoder, que tuvo a bien compartir conmigo su conocimiento de los entresijos de la Integración Continua y de las herramientas de que trata esta serie.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: