Using Elixir with Wercker CI
Here at Appcues, we managed for a long time to avoid needing an in-house backend at all; between Firebase for storage, Keen for analytics, and a small handful of other SaaS offerings, Appcues made it almost two years down the road before we needed more than what other people’s services could provide.
For about a month now, we’ve been building our next platform on Elixir, a modern language which runs on the Erlang VM (a.k.a. BEAM). We were attracted to its approach to concurrency (actors passing messages, shared nothing, immutable everything), its clean web framework Phoenix, and the BEAM VM’s stellar reputation for scalability and near-real-time communications. It felt like a good fit.
We use Wercker CI for test automation on our other projects (traditionally CoffeeScript, lately ES6), so we set out to configure our project to get along with Wercker. Pointing Wercker at our GitHub repo was quite trivial, but then we needed to configure the build process.
CI on Docker
Wercker’s CI system is built around Docker containers. The basic
procedure to integrate with Wercker is to add a wercker.yml to
the project’s root directory, which
indicates the Docker image used to run the project’s tests, as well
as any other auxiliary Docker containers to use (e.g., adding a Postgres
container to provide a testing database) and the specific steps to
execute during a build.
The Docker images can come from Docker Hub,
a global repository of official and unofficial Docker images; this made
it convenient to search for an Elixir dev image. Unfortunately, though,
we could not find an Elixir container which contained everything we
needed to test a Phoenix app: a full install of Erlang R18 and Elixir
1.1 for starters, but also the Postgres client (psql), Git, and a few
Elixir/Erlang tools like Hex and Rebar.
Eventually, we settled on making an
Elixir dev container of our
own,
publishing it to Docker
Hub,
and using that as the box in our wercker.yml.
(Feel free to use it for your own endeavors!)
Configuration
The rest of the wercker.yml file was fairly straightforward:
specifying our test DB setup in services, and entering the
commands for our build steps in build:
# Read more about containers on our dev center
# http://devcenter.wercker.com/docs/containers/index.html
box: appcues/elixir-dev
# This is the build pipeline. Pipelines are the core of wercker
# Read more about pipelines on our dev center
# http://devcenter.wercker.com/docs/pipelines/index.html
# You can also use services such as databases. Read more on our dev center:
# http://devcenter.wercker.com/docs/services/index.html
services:
# http://devcenter.wercker.com/docs/services/postgresql.html
- id: postgres
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
build:
# The steps that will be executed on build
# Steps make up the actions in your pipeline
# Read more about steps on our dev center:
# http://devcenter.wercker.com/docs/steps/index.html
steps:
- script:
name: set env vars
code: |
export MIX_ENV=test
- script:
name: get and compile dependencies
code: |
cd $WERCKER_SOURCE_DIR
yes | mix do deps.get, deps.compile
- script:
name: compile
code: |
yes | mix compile
- script:
name: initialize test db
code: |
mix do ecto.create, ecto.migrate
- script:
name: test
code: |
mix test
Boom
That’s it. There was a little tweaking to get it working
right, like adding yes | before some of the mix commands that got a
little permission-happy – nothing too unexpected.
And we’ve been up and running on Wercker ever since, freeing us to get some actual work done.
Hope this helps!