bukhgalter

A microservice to share expenses between friends WIP. Class project for the infrastructure subject


Project maintained by yabirgb Hosted on GitHub Pages — Theme by mattgraham

Integración continua

Servicios elegidos y por qué

He elegido dos servicios de integración continua: travis y circle-ci.

Motivos para elegir travis:

Motivos para elegir circle-ci:

Mi estrategia con los sistemas de CI ha sido la siguiente:

Para probar la estabilidad de mi aplicación con los cambios en el lenguaje he utilizado la ejecución en travis de distintas versiones relevantes como son el canal stable (para verificar que cualquiera con una instalación estandar puede ejecutar el proyecto ) y el canal beta (para predicir posibles problemas con cambios en aspectos que van a entrar al lenguaje). Además de estas versiones compruebo cual es la última versión más antigua que soporta mi aplicación. Actualmente tras haber realizado distintas pruebas esta es la versión 1.40.0.

Para comprobar que los cambios introducidos no introducen ningún fallo uso una versión estable que es la cual se esta usando para el desarrollo. He utilizado la versión 1.44.0 que también se emplea en el contenedor de docker del proyecto desarrollado en el hito anterior. De esta manera se comprueba que respecto a la versión referencia los tests ejecutan de manera correcta.

En el archivo de setup se puede encontrar el proceso de registro en los sistemas elegidos.

Integración continua con travis

Para utilizar travis en integración continua se han seguido los siguientes pasos:

Descipción del archivo .travis.yml

# Elegimos rust como lenguaje. Esto nos probee con utilidades como 
# cargo, rustc para compilar etc.
language: rust

# Instalamos el gestor de tareas elegido para el proyecto
install: make

# le indicamos las versiones con las que queremos trabajar. Hacemos uso
# de la ejecución múltiple de travis
rust:
  # marcamos la ultima version disponible, en general es la que tiene
  # la gente que programa con rust
  - stable
  # Marcamos la version beta para conocer posibles problemas en versiones
  # futuras
  - beta
  # Marcamos la version 1.31 porque es la primera version en la que se incluye
  # la especificación 2018. Con anterioridad a esta version no nos interesa probar
  # - 1.31.0
  # Tras haber probado esta es la versión minima que ejecuta los tests
  - 1.40.0

# Añadimos los directorios de cargo a la cache
cache: cargo

# Finalmente le indicamos que tiene que ejecutar el contenedor de igual
# forma de la que se ejecutan en los tests de la asignatura
scripts:
  - make check
  - make build
  - make test

# No tenemos ninguna actividad que hacer post-ejecución de los tests
# así que no incluimos tareas adicionales

En este archivo hemos elegido Rust como lenguaje y hemos especificado varias versiones de rust para ejecutar los tests. Estas han sido:

También hago uso de la cache de travis para mejorar la velocidad de ejecución de los tests. Esta técnica por defecto guarda el directorio de cargo en $HOME por lo que evitamos descargar siempre todas las dependencias del proyecto y de cargo. Además se guarda el target del proyecto por lo que hacemos uso de las builds incrementales de rust y la ejecución de los tests es más rápida.

Respecto a la ejecución en travis en primer lugar hacemos un check de las dependencias y de nuestro proyecto por lo que encontramos posibles errores de sintaxis y problemas de incompatibilidades. Seguidamente hacemos una construcción del mismo y por último ejecutamos los tests.

Versiones previas del archivo

Con anterioridad se creo una versión que ejecutaba el contenedor de docker creado en el hito anterior. Esta versión se ha descartado para hacer uso de la funcionalidad de matrix execution que en travis funciona de manera rápida. La ejecución del contenedor de docker se ha realizado en circleci, documentado más adelante.

El archivo de travis incluyo comentarios de por qué se realza cada paso y la justificación

# Utilizo ruby como lenguaje base ya que no necesito ninguno en particular
# y biene por defecto con travis
language: ruby

# Le indicamos que vamos a hacer uso de las herramientas de docker para 
# que esten disponibles en la ejecución
services:
  - docker

# Como vamos a hacer uso del contenedor de docker generado por el proyecto
# le indicamos que lo descargue del repositorio de docker hub antes de hacer 
# nada
before_install:
  - docker pull yabirgb/bukhgalter

# Finalmente le indicamos que tiene que ejecutar el contenedor de igual
# forma de la que se ejecutan en los tests de la asignatura
scripts:
  - docker run -t -v `pwd`:/test yabirgb/bukhgalter:latest

# No tenemos ninguna actividad que hacer post-ejecución de los tests
# así que no incluimos tareas adicionales

Configuración de circle-ci

El objetivo para la CI de circle-ci es el que se ha explicado con anterioridad. La decisión de usar circle-ci para el contenedor de docker ha sido tomada tras haber realizado una comparación entre las dos plataformas, travis y circle-ci. Los resultados para dichas pruebas se pueden consultar en el historial de travis y el de circle-ci.

Adjunto una captura del desplegado del contenedor en circle-ci

En este caso la build de circle-ci ha sido más rápida para ejecutar el contenedor de docker que la de travis y por eso me he decantado por usar circle-ci para este cometido.

Respecto al archivo de configuración

version: 2.1
# Trabajos que se van a hacer
jobs:
build:
  # Le decimos que utilizamos una maquina con linux
  machine: true
  steps:
      # Hacemos checkout del repo
      - checkout
      # Ejercutamos el contenedor de docker
      - run: docker run -t -v `pwd`:/test yabirgb/bukhgalter:latest

Como vemos la sintaxis es muy simple y nos permite ejecutar de manera sencilla nuestros tests desde el contenedor de docker. Cabe destacar que ha diferencia de travis, aquí no necesitamos indicar que vamos a trabajar con docker. También al igual que travis podemos especificar que tipo de máquina queremos para los tests. Me he decantado por probar solo en linux porque windows o osx no me ofrecen ninguna ventaja respecto a lo que quiero realizar.

Generación automática de los contenedores para testing

Los contenedores para testing son generados automática cada vez que es necesario. Para ello he usado una estrategia en github actions que se ejecuta de manera inteligente:

Cómo se ha configurado el despliegue

Para realizar el despliegue en dockerhub se han seguido los siguientes pasos:

  1. Crear una cuenta en dockerhub con el mismo nombre de usuario que en github.
  2. Crear un token para el acceso a la cuenta de dockerhub

token de dockerhub

  1. Este token se ha añadido junto al nombre de usuario a los secrets del repositorio de github

secrets

  1. Se ha configurado en github actions los datos de usuario usando el token creado para publicar los contenedores.

La parte del action donde se realiza la publicación del contenedor esta disponible aquí.

También se podía haber configurado un trigger desde docker hub pero he preferido decantarme por esta opción por la libertad que me da para publicar en otras plataformas y porque puede programar como quiero que se construyan los contenedores.

En el caso de los repositorios de github ha sido necesario crear un token de acceso que también se ha añadido a los secrets del repositorio y se ha añadido también al actions para los tests.

Problemas encontrados

Durante el desarrollo del archivo para el workflow me he encontrado con varios problemas:

Fuentes