CI with Phoenix and GitLab

Continuous Integration is a really valuable resource when trying to get software out to market faster. It's one of the main tools in the Agile/DevOps toolkit to tie together all of your hard work in writing tests for your software and compiling build artifacts for release. Travis CI is extraordinarily popular for open source projects given how easily it integrates with GitHub. For private source projects, GitLab has gained a lot of popularity for private Git hosting and GitLab CI has functionality similar to Travis.

For the purposes of this post, I'll assume that you are already familiar with Phoenix and Elixir and want to improve your code quality and iteration time by adding continuous integration to your Phoenix application using GitLab CI.

To start, make sure you have GitLab and GitLab CI setup. I used the Docker multi-runner as my runner and I'll assume you have too. Once runners are registered with your GitLab server, GitLab CI will monitor all of your repos for a .gitlab-ci.yml file in the root of your repository.

This is the .gitlab-ci.yml file for my Phoenix application. As a note, I'm using Postgres with my app, so some of the configuration is geared towards that. If you are using MySQL or another database engine, you'll need to reconfigure your build. The Elixir Docker image uses Debian as it's base.

image: "elixir:1.2"  
services:  
  - postgres:latest
variables:  
  POSTGRES_DB: communities_of_hope
  POSTGRES_USER: runner
  POSTGRES_HOST: postgres
  POSTGRES_PASSWORD: ""
before_script:  
  - apt-get update && apt-get -y install postgresql-client
  - mix local.hex --force
  - mix local.rebar --force
  - mix deps.get --only test
  - MIX_ENV=test mix ecto.setup
exunit:  
  script:
    - mix test

The first two lines, image and services tell GitLab CI which Docker images we need for our build. Our build will run from the Elixir 1.2 image, but GitLab CI will also run a Postgres container to handle our database. The variables element sets up environment variables in both the Postgres and Elixir images. Since we use environment variables, we have to update our application configuration in config/test.exs:

config :communities_of_hope, CommunitiesOfHope.Repo,  
  adapter: Ecto.Adapters.Postgres,
  username: System.get_env("POSTGRES_USER") || "postgres",
  password: System.get_env("POSTGRES_PASSWORD") || "postgres",
  database: System.get_env("POSTGRES_DB") || "communities_of_hope_test",
  hostname: System.get_env("POSTGRES_HOST") || "localhost",
  pool: Ecto.Adapters.SQL.Sandbox

I added the environment variables, but fell back on defaults so that when the test are run locally, they still work without needing a .env file.

Next in our .gitlab-ci.yml file we have the before_script block:

before_script:  
  - apt-get update && apt-get -y install postgresql-client
  - mix local.hex --force
  - mix local.rebar --force
  - mix deps.get --only test
  - MIX_ENV=test mix ecto.setup

As the name of the element says, these are scripts which run before the build. Since I'm using Postgres and Ecto requires the psql command to be present, the Postgres client packages are installed. Next we install Hex and Rebar. Finally we get all our application's dependencies and setup the database.

Now that our images are configured and setup, we can actually build our application:

exunit:  
  script:
    - mix test

When you first start working on your Phoenix app, you'll probably only have ExUnit tests for your application. If you have other tests which need to be run, you can add different blocks to your Yaml file. For example, if you also have ESpec, your .gitlab-ci.yml file might look like this:

...
exunit:  
  script:
    - mix test
espec:  
  script:
    - mix espec

Now that our .gitlab-ci.yml file is all set, we just commit it back to our repo and look at the builds tab on GitLab.

Dave Long

Read more posts by this author.

Subscribe to Dave Long

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!