Setting up Gitlab CI for Elixir/Phoenix on your VPS

Gitlab is a great development tool, getting better with every release. They give you access to their new-ish pipelining features on Gitlab.com for free. However, I wanted to setup the Gitlab Runner (this is what executes your CI build) on my own VPS using Docker. Gitlab makes this very easy to install, but the documentaion is spread out when it comes to setup and execution. I thought an all in one document showing all the steps would be helpful to the community.

I am hoping this post will help out others looking to run their Elixir/Phoenix application tests through the CI pipeline using their own VPS.

All commands were executed on my VPS as the root user. If you are logged in as a user that has sudo access, you will need to prepend all commands with sudo.

Prerequisites: A VPS or similar server (virtualbox, docker, …)

Setup the Gitlab Runner

Run on your VPS

Install docker

curl -sSL https://get.docker.com/ | sh

Install Gitlab Runner Repo

curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.deb.sh | bash

Install Gitlab Runner

apt-get install gitlab-ci-multi-runner

Login to Gitlab.com and navigate to the project you want to use the runner for. Open the project Settings -> CI/CD Pipelines section.

Settings - CI/CD Pipeline

You will then see the Specific Runners section which contains the URL and key to use to setup your runner.

Obtaining runner reg token

Register the runner

gitlab-ci-multi-runner register

When asked which exector to use, type in docker. You will need to provide the default docker image to use, I used elixir:1.4. Also I set the runner to not be project specific, and to only run tagged builds. The tag I am using for the runner is elixir.

Configure your Elixir application

Create a .gitlab-ci.yml file, at the root of your repo, with the following contents.

image: elixir:1.4

services: - postgres:9.6.2

variables: POSTGRES_DB: project_test POSTGRES_USER: runner POSTGRES_PASSWORD: “s0m3P@ssw0Rd”

stages: - test

before_script: - mix local.hex –force - mix local.rebar –force - mix deps.get - MIX_ENV=test mix ecto.create - MIX_ENV=test mix ecto.migrate

unit-testing: stage: test script: - MIX_ENV=test mix test

tags: - elixir

  • image - Define what Docker image (from Docker Hub) the environment will run on. I chose elixir:1.4 which provides an environment running Erlang 19 and Elixir 1.4.2 (at the time of writing).
  • services - Secondary services our environment requires. Checkout the Gitlab Docker Services documentation for more information. For my use case, I only need Postgresql 9.6.2. This is also a Docker container from Docker Hub.
  • variables - This section is where you setup the credentials for the Postgresql server. Public repos will want to set the ENV vars within the Pipeline settings so they don’t expose their credentials. I have not tested that, and my repo is private, I added them directly in the config. The Elixir applications database configuration will need to match the Postgresql credentials that are setup within .gitlab-ci.yml or ENV vars.
  • stages - Gitlab has three stages in their CI/CD process. I am only going to use test for now, but the other two are build and deploy. I would like to get CD working at some point, so keep an eye out for a post covering deployment.
  • before_script - Commands to execute before any jobs are ran. The application has dependencies that need to install in order to run tests. Hex/Rebar must be installed locally and --force is used as it is ran in non-interactive mode. After that use mix to install the dependencies for the application. Finally use ecto to create and migrate the database.
  • unit-testing - This is the name of the job as it will show up within Gitlab CI. You can name your job as you see fit. This example is pretty small, so checkout the Gitlab docs for more details. The job is going to be executed during the test stage (recall the three stages listed above, this is how you scope jobs to stages). To actually execute the tests, the commands contained within the script section are ran. The MIX_ENV must be set to test to ensure proper scoping to the test env (testing database configuration is used). The tests are executed using the mix test command. Lastly the elixir tag is added to the job, this matches the tag used during runner setup, and allows the runner to execute this job.

Database configuration

The last step before any tests can be ran is to update the config/test.exs file. The database name, username, password, and host should match what was set in the .gitlab-ci.yml file. We didn’t explicitly set the host in that file because it is handled for us. The hostname would be postgres.

# Configure your database (config/test.exs)
config :project, Project.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "runner",
  password: "s0m3P@ssw0Rd",
  database: "project_test",
  hostname: "postgres",
  pool: Ecto.Adapters.SQL.Sandbox

Finishing up

Push the branch to Gitlab, and open the Pipeline tab for the project. You should see the tests running for your branch. The page doesn’t appear to automatically update, a refresh may be needed to see latest pushes. If the tests pass, you should see something similar:

CI run results

Gitlab also has badges build in to spice up your README or project site. Badge

Updates

  • May 5th 2017 - Added which exector to use during runner setup.