Implementando un Laboratorio para CI en GitLab

Resumen de actividades para la session 1:

  • Clonar repositorio basico.
  • Realizar seguimiento de cada una de las fases que permite GitLab.
  • Identificar el codigo al que se quiere realizar el TEST.
  • Identificar el codigo con el que se realiza el test.
  • Identificar los pasos que son ejecutados luego del PUSH sobre el repositorio.

Implementando Laboratorio Integracion Continua con GitLab

El siguiente documento describe aspectos basicos de Integarcion Continual (CI) de una forma practica.

Se realiza utilizando el ambiente GitLab, pues este ambiente tiene todos los componentes necesarios para realizar una implementacion completa, por otro lado permite repositorios publicos y privados, algo que otros ambientes no permiten en su totalidad.

Objetivos

  • Identificar la alternativas libres y gratuitas que permitan el desarrollo de capacidades en el desarrollo de software.
  • Explorar las posibilidades que provee GitLab para el montaje de ambientes de desarrollo de Software.
  • “Aterrizar” con ejemplos practicos, las maneras de asegurar la calidad de software existentes actualmente.

Pre-requisitos

  • Conocimientos basicos en el manejo de GIT, consola de comandos y en general de Linux.
  • Tener una cuenta en GitLab, o en su defecto una implementacion de GitLab.
  • Conocimientos previos basicos con software de pruebas unitarias, en particular de PHPUnit.

Resumen de actividades para la session 1:

  • Clonar repositorio basico.
  • Realizar seguimiento de cada una de las fases que permite GitLab.
  • Identificar el codigo al que se quiere realizar el TEST.
  • Identificar el codigo con el que se realiza el test.
  • Identificar los pasos que son ejecutados luego del PUSH sobre el repositorio.

Repositorio de Proyecto basico

El uso de Git para el control de codigo de manera distribuida es una practica ampliamente generalizada en ambiente de codigo abierto por mas de una decada, pero que solo resientemente han sido adoptadas por empresas desarrolladoras de software tracicionales (por ejemplo Microsoft).

Por tanto, no es raro ver que el control de los proyectos que implementan CI tienen que estar basados sobre Git, estos proyectos son articulados alrededor de las capacidades distribuidas de los desarrolladores y los repositorios de codigo (como GitHub, GitLab, o BitBucket).

The Key Differences : GitLab vs GitHub vs bitbucket

El diseño de los procesos de produccion automatica de codigo suele estar basado principalmente sobre Git y la implementacion de commits, branch y tags, son usualmente utilies para agendar los triggers o disparadores, que realizan parte del automatismo que implica el CI.

En el particular GitLab provee un set de repositorios pre-construidos, con el objetivo de facilitar la adopcion de los conceptos basicos. Estos hacen part de la documentacion official.

GitLab CI Examples

Para entrar en contexto, partiremos del ejemplo clasico, descrito principalmente en el articulo, Testing PHP projects.

Clonando el repositorio basico

[09:47 PM]$ git clone https://gitlab.com/gitlab-examples/php

Cloning into 'php'...
remote: Counting objects: 141, done.
remote: Compressing objects: 100% (85/85), done.
remote: Total 141 (delta 62), reused 120 (delta 53)
Receiving objects: 100% (141/141), 24.53 KiB | 0 bytes/s, done.
Resolving deltas: 100% (62/62), done.
Checking connectivity... done.

Luego usando la interface web de GitLab se crea un nuevo repositorio de codigo:

Architecture viewpoints

Una vez el repositorio vacio es creado se confirma la ruta del repositorio:

Architecture viewpoints

Por ultimo, utilizando la ruta confirmada para su repositorio, se procede a hacer un PUSH del repositorio clonado de la documentacion:

git remote add origin git@gitlab.com:iush/php-ci-basic-example.git
git push origin master

Como el repositorio de ejemplo ya tiene todo un sistema ya implementado, GitLab ejecutara a partir del PUSH todas las operaciones configuradas de test y deploy.

Chequeando el resultado inicial del Test Automatizado

La verficacion de la ejecucion de los procesos automaticos se puede hacer mediante la opcion Pipelines en las pestañas de opcion del proyecto:

Pipeline link

Para el caso particular del ejemplo se puede identficar 2 pruebas basicas sobre el ejemplo; Las pruebas son realizadas sobre el driver PDO sobre MySql para 2 versiones diferentes de PHP.

Pipeline link

El proceso es vigilado mediante su salida en el promt que se puede visualizar cuando se hace clik en alguna de las dos opciones de prueba.

Pipeline link

Para este caso se realizaron las pruebas para 3 posible usos de la funcion de coneccion del codigo de ejemplo.

Pipeline link

El error corresponde a que no todos los modulos de phpuinit estan presentes en la implementacion inicial.

Sobre que software quiero realizar el test.

Para el caso del ejemplo, se quiere probar la conectividad con la base de datos usando el driver PDO de php.

<?php

class HelloWorld
{
    /**
     * @var PDO
     */
    private $pdo;

    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    public function hello($what = 'World')
    {
        $sql = "INSERT INTO hello VALUES (" . $this->pdo->quote($what) . ")";
        $this->pdo->query($sql);
        return "Hello $what";
    }


    public function what()
    {
        $sql = "SELECT what FROM hello";
        $stmt = $this->pdo->query($sql);
        return $stmt->fetchColumn();
    }
}
?>

El codigo declarar una funcio que recibe un string y lo inserta en la base de datos y luego otra funcion que lee lo que se intenta ingresar en la base de datos.

Sobre la secuencia de pasos que realiza el TEST.

En particular para el ejemplo se realizan dos test, uno para php:5.6, y otro para php:7, las imagenes son las definidas en dockerhub en sus repositorios oficiales.

# Select image from https://hub.docker.com/_/php/
image: php:5.6

# Select what we should cache
cache:
  paths:
  - vendor/

before_script:
# Install git, the php image doesn't have installed
- apt-get update -yqq
- apt-get install git -yqq

# Install mysql driver
- docker-php-ext-install pdo_mysql

# Install Xdebug
- pecl install xdebug

# Enable Xdebug
- docker-php-ext-enable xdebug

# Install composer
- curl -sS https://getcomposer.org/installer | php

# Install all project dependencies
- php composer.phar install

services:
- mysql

variables:
  # Configure mysql service (https://hub.docker.com/_/mysql/)
  MYSQL_DATABASE: hello_world_test
  MYSQL_ROOT_PASSWORD: mysql

# We test PHP5.6 (the default) with MySQL
test:mysql:
  script:
  - vendor/bin/phpunit --configuration phpunit_mysql.xml --coverage-text

# We test PHP7 with MySQL, but we allow it to fail
test:php7:mysql:
  image: php:7
  script:
  - vendor/bin/phpunit --configuration phpunit_mysql.xml --coverage-text
  allow_failure: true

En la seccion before_script se realiza la instalacion de las librerias y sotware neceario para que el docker php:5.6 pueda realizar el test.

Adicionalmente, se utiliza el servicio mysql, tambien segun lo definido en Dockerhub (Incluyendo las variables).

Sobre las opciones de Test

Se define la configuracion del test sobre el archivo phpunit_mysql.xml.

<testsuites>
        <testsuite name="Hello World Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

Y se defines 3 tipos de pruebas, a saber, na prueba de la funcion de insercion y lectura con un parametro de entrada, y otro sin parametro.

<?php

class HelloWorldTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var PDO
     */
    private $pdo;

    public function setUp()
    {
        $this->pdo = new PDO($GLOBALS['db_dsn'], $GLOBALS['db_username'], $GLOBALS['db_password']);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->pdo->query("CREATE TABLE hello (what VARCHAR(50) NOT NULL)");
    }

    public function tearDown()
    {
        if (!$this->pdo)
            return;
        $this->pdo->query("DROP TABLE hello");
    }

    public function testHelloWorld()
    {
        $helloWorld = new HelloWorld($this->pdo);

        $this->assertEquals('Hello World', $helloWorld->hello());
    }

    public function testHello()
    {
        $helloWorld = new HelloWorld($this->pdo);

        $this->assertEquals('Hello Bar', $helloWorld->hello('Bar'));
    }

    public function testWhat()
    {
        $helloWorld = new HelloWorld($this->pdo);

        $this->assertFalse($helloWorld->what());

        $helloWorld->hello('Bar');

        $this->assertEquals('Bar', $helloWorld->what());
    }
}
?>

⤧  Previous post General document Software Architecture.