Cómo Configurar GitHub Actions para correr RSpec

No hay ninguna duda que la integración continua tiene enormes ventajas a la hora de simplificar la forma de enviar nuestros proyectos a los entornos en la nube. Por eso, ya antes he configurado este tipo de servidores en Bitbucket, Jenkins e incluso Circle CI.

Ahora, me tocó hacerlo en GitHub Actions y quiero compartir cómo lo logré y algunos aprendizajes.

Voy a partir del resultado final e iré explicando los bloques importantes.

Este es el código para el archivo workflow.yml ubicado en la carpeta .github/workflows.

env:
  POSTGRES_USER: postgres
  POSTGRES_PASSWORD: postgres
  RAILS_ENV: test

name: Rails tests
on: [push, pull_request]
jobs:
  rspec-test:
    name: RSpec
    runs-on: ubuntu-18.04
    services:
      postgres:
        image: postgres:latest
        ports:
          - 5432:5432
        options: >-
          --mount type=tmpfs,destination=/var/lib/postgresql/data
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: nsac_testing
    steps:
      - uses: actions/checkout@v1
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: 2.7.1
          bundler-cache: true
      - name: Install postgres client
        run: sudo apt-get install libpq-dev
      - name: Prepare database
        run: bundler exec rails db:prepare RAILS_ENV=test
      - name: Run tests
        run: bundler exec rake

Los detalles.

Este bloque al inicio existe por dos razones.

env:
  POSTGRES_USER: postgres
  POSTGRES_PASSWORD: postgres
  RAILS_ENV: test

La primera razón es para ayudarnos a reutilizar tales valores en los diferentes bloques subsiguientes de configuración de servicios o pasos a ejecutar.

La segunda razón es que permite que tales variables estén disponibles para la aplicación y pueden ser leídas mediante la instrucción ENV.

Más adelante cuento porque es importante esta segunda razón.

Claves sobre servidores de Integración Continua

Una forma sencilla de verlos es que ellos ejecutan una serie de pasos predefinidos, si algún paso falla, toda la operación es terminada.

Normalmente, el orden de las instrucciones es algo como:

  1. Nombra el flujo
  2. Define las condiciones para ejecutarlo (on: [push, pull_request])
  3. Define las tareas a ejecutar (jobs)
  4. Define cada tarea (rspec-test)
  5. Describe dependencias de la tarea (runs-on, services)
  6. Define cada cosa que hará la tarea (steps)
  7. Define cada cosa de manera individual (uses, name, run)

Con eso en mente, quiero describir brevemente alguna de las partes. Para más info puedes leer la ayuda de GitHub sobre las Actions.

Servicio PostgreSQL

Para este bloque, me permito mencionar algunas cosas:

services:
      postgres:
        image: postgres:latest
        ports:
          - 5432:5432
        options: >-
          --mount type=tmpfs,destination=/var/lib/postgresql/data
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: nsac_testing

Si no se define el bloque postgres las pruebas nunca se van a ejecutar porque se necesita una base de datos para eso.

Lo que está en options son configuraciones útiles para verificar que el servicio esté activo y listo para ejecutar.

Y hay que describir un bloque env para el servicio, a pesar de que en la parte superior hayamos definido otro bloque similar. Esto es porque lo que se describe para este servicio se pasa como argumentos al comando de Docker que crea el contenedor y son valores importantes y requeridos.

NOTA: el valor para POSTGRES_PASSWORD no puede estar vacío o habrá un error sobre el servicio “unhealthy”.

Failed to initialize, postgres service is unhealthy

También es vital definir los valores para usuario y clave de base de datos en el archivo database.yml del proyecto Rails:

default: &default
  host: localhost
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

development:
  <<: *default
  database: nsac_development

test:
  <<: *default
  database: nsac_testing
  username: <%= ENV.fetch("POSTGRES_USER", "") %>
  password: <%= ENV.fetch("POSTGRES_PASSWORD", "") %>

production:
  <<: *default
  url: <%= ENV['DATABASE_URL'] %>

Sin tales valores configurados, va a fallar todo el proceso.

NOTA: también hay que decir el valor para host. Sino, vamos a ver el error:

could not connect to server: No such file or directory

Sobre Ruby y Gemas

Algo que me gustó de GitHub Actions es lo simple que esta parte de configurar Ruby.

- uses: ruby/setup-ruby@v1
  with:
    ruby-version: 2.7.1
    bundler-cache: true

Con la instrucción bundler-cache: true los pasos de instalación de gemas y de paso cachearlas para agilizar futuras ejecuciones quedan cubiertos.

NOTA: acá usé ruby/setup-ruby porque es la forma más actualizada.

Segunda Ventaja de definir un env superior

La segunda ventaja está dada en este bloque:

- name: Prepare database
  run: bundler exec rails db:prepare RAILS_ENV=test

Si bien estoy repitiendo RAILS_ENV=test, si no hubiera definido los variables de entorno en la parte superior, el error siguiente aparecería (me pasó como 8 veces mientras configuraba esto xD)

fe_sendauth: no password supplied
Couldn't create 'nsac_testing' database. Please check your configuration.
rails aborted!
PG::ConnectionBad: fe_sendauth: no password supplied

Esto es porque si bien en el archivo database.yml estoy leyendo las variables de entorno, al crear el contenedor, el flujo no está proveyendo tales variables para ser leídas en el archivo y termina arrojando valores indebidos.

Conclusión

Definitivamente, GitHub Actions es una buena forma de tener un servidor de Integración Continua sin crear cuenta en otro servicio ni tener que aprender una sintaxis YAML externa (aunque sí hay que leer la documentación o buscar un tutorial).

Hay una buena oferta de minutos en la capa gratuita (2000 vs los 50 que da Bitbucket Pipelines).

Al comienzo me ayude de un tutorial y de ahí fui buscando más información a medida que encontraba errores y en el 14avo intento lo conseguí. Decidí compartir acá por si alguien empieza a usar Actions para un proyecto Rails, tal vez encuentre este y tenga un mejor punto de partida que el mío.

Autor: cesc1989

Ingeniero de Sistemas que le gusta escribir y compartir sobre recursos que considera útiles, además que le gusta leer manga y ver anime.

Un comentario en “Cómo Configurar GitHub Actions para correr RSpec”

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. Salir /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios .