Integración continua con Github: Travis CI

Github es uno de los servicios más importantes que existen en este momento en el mundo del desarrollo de software. Pese a haber sido recientemente adquirido por Microsoft, sigue siendo la plataforma de gestión de repositorios más usada del mundo.

Como ya comenté hace tiempo, utilizo personalmente Gitlab como sistema de repositorios de código fuente, pero la verdad es que estaba deseando probar “su” sistema de integración continua, llamado Travis CI.

Nota del autor: Las políticas de uso de Travis CI han cambiado desde que escribí este post y aunque el servicio sigue funcionando, ahora recomendaría el uso de Github Actions y sólo mantengo este post activo por su posible utilidad. Para más información sobre las nuevas políticas de uso de Travis CI, recomiendo el post de Jeff Geerling al respecto.

Primeros pasos

Para comenzar a utilizar Github y Travis CI, primero debemos registrarnos. Una vez que ya estamos dentro, nuestro siguiente paso es crear un repositorio y dotarle de contenido.

En este caso he decidido, crear un repositorio espejo que utilice como fuente, el desarrollo de este blog en Gitlab. Tras crear dicho repositorio en Github, Se tarda menos de cinco minutos en hacer siguiendo estas instrucciones

Si ahora nos metemos en nuestra cuenta de Github, veremos el código de nuestro repo:

tangelov-en-github

Travis CI

Travis CI es un servicio de integración continua de código abierto ajeno a Github, pero hospedado en él y que proporciona dicho servicio de manera gratuita a todos los proyectos de código abierto que se deseen.

Lo primero que debemos hacer, es dar permisos a Travis CI para poder realizar las builds. Al loguearnos en su web con nuestro usuario de Github, nos pedirán permisos.

login-travis-ci

Al igual que en el caso del CI de Gitlab, debemos crear un fichero oculto que será el encargado de gestionar nuestras builds. La idea general de este post es replicar con otro sistema el resultado obtenido en el anterior post. En este caso el fichero que queremos generar se llamará .travis.yml.

Creamos el fichero

Nuestros primeros pasos deberían ser que se clonase el código, instalase nikola y generase el HTML estático que necesitamos.

dist: trusty
sudo: required

language: python
python:
  - "3.6"

before_install:
- pip install -r requirements.txt

script:
  - nikola build

Vamos a explicar un poco que significa ese fichero:

  • dist se corresponde con la distribución con la que se va a lanzar nuestra build. En este caso hemos elegido Ubuntu Trusty. En este link se pueden ver todos los disponibles. Añadimos sudo: required para poder utilizar Docker en un futuro.

  • language se corresponde con el lenguaje de programación utilizado. En este caso vamos a usar Nikola y por eso especificamos python en su versión 3.6.

  • before install se encarga de ejecutar una serie de pasos antes de realizar nada. Lo utilizo para instalar las dependencias del proyecto localizadas en el fichero requirements.txt.

  • script ejecuta una serie de órdenes que nosotros le pasamos.

Aquí podemos ver el resultado de nuestro proceso:

travis-ci-result

Añadimos docker a .travis.yml

Nuestra build ya se descarga el código y genera el código HTML resultante, pero ahora vamos a añadir algunos pasos más.

dist: trusty
sudo: required

services: docker

language: python
python:
  - "3.6"

before_install:
- pip install -r requirements.txt

script:
  - nikola build
  - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USER" --password-stdin
  - docker build -t $DOCKER_USER/tangelov-me:latest .
  - docker push $DOCKER_USER/tangelov-me:latest

Hemos añadido el servicio de docker al fichero, que hace que podamos utilizar los comandos de Docker y tres pasos más que nos loguean en Dockerhub, crean y pushean la imagen a dicho repositorio.

Sin embargo, primero debemos añadir las variables de entorno para que Travis pueda gestionar las credenciales de Docker, en Settings:

travis-ci-conf

Una vez realizado esto podemos ejecutar nuestro job y ver que el resultado es satisfactorio. En Dockerhub se ha creado una nueva imagen totalmente funcional:

dockerhub-result

Configuraciones extra

En el estado actual de las cosas, cualquier push que se haga al repositorio provocará que se lance el job. Como nuestra idea es simular lo que tenemos en Gitlab, en este nuevo entorno, vamos a limitar que sólo ocurra cuando se realicen merges contra la rama principal.

Tan sólo debemos añadir una lista blanca con la rama principal:

dist: trusty
sudo: required

services: docker

language: python
python:
  - "3.6"

branches:
  only:
    - master

before_install:
- pip install -r requirements.txt

script:
  - nikola build
  - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USER" --password-stdin
  - docker build -t $DOCKER_USER/tangelov-me:latest .
  - docker push $DOCKER_USER/tangelov-me:latest

Y listo :D

Documentación

Revisado a 01/05/2023