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,
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 :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
Next in our
.gitlab-ci.yml file we have the
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.