devops, github actions, phoenix

Github Actions for Phoenix

Github Actions enables you to build, test, and deploy your Phoenix App from GitHub. Actions use the idea of workflows and in this tutorial, we're going to configure a basic build-and-test workflow using a new Phoenix Application.

Let's get started.

Versions

  • Elixir 1.10.1
  • Phoenix 1.4.12

Create Phoenix App

Create a throw-away Phoenix app.  If you haven't created on before, you can follow our Getting Started with Phoenix Guide.

Phoenix comes out of the box with a few tests which should be enough to get us started with Github Actions.

Ensure your tests run successfully before proceeding:

$ mix test

Compiling 16 files (.ex)
Generated status app

18:04:55.437 [info] Already up
...

Finished in 0.04 seconds
3 tests, 0 failures

Configure App

We'll need to configure the test Repo to connect to the postgres hostname, so open config/test.exs:

(replace my_app and MyApp)

config :my_app, MyApp.Repo,
username: "postgres",
password: "postgres",
database: "my_app_test",
pool: Ecto.Adapters.SQL.Sandbox

if System.get_env("GITHUB_ACTIONS") do
config :my_app, MyApp.Repo,
username: "postgres",
password: "postgres"
end

We're targeting Github Actions using an environment variable that will only be set in CI.

This will configure the Repo to use the correct configuration.

Create Workflow

Github Actions uses the concept of workflows to perform different steps.

Create a new file: .github/workflows/ci.yml:

(Update POSTGRES_DB)

name: CI

on: push

jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:11
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: my_app_test
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
env:
MIX_ENV: test
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/[email protected]
- uses: actions/[email protected]
with:
otp-version: 22.2.6
elixir-version: 1.10.1
- uses: actions/[email protected]
with:
path: deps
key: ${{ runner.os }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}
restore-keys: |
${{ runner.os }}-mix-
- uses: actions/[email protected]
with:
node-version: '10.x'
- uses: nanasess/[email protected]
with:
chromedriver-version: '79.0.3945.36'
- run: |
export DISPLAY=:99
chromedriver --url-base=/wd/hub &
sudo Xvfb -ac :99 -screen 0 1280x1024x24 > /dev/null 2>&1 &

- run: mix local.rebar --force
- run: mix local.hex --force
- run: mix deps.get
- run: npm install --prefix assets
- run: npm run deploy --prefix assets
- run: mix test

Breaking it Down

This may look like a lot of code, but it's a basic yaml file that instructs Actions on which commands to run for each step.

Each step in the workflow has a name property that describes the current action.

Here are the steps:

  • Use Ubuntu as a Docker container.
  • Set some environment variables on the container for our app to read.
  • Use Postgres Docker container, and set default user and DB.
  • Checkout the code.
  • Elixir setup action.
  • Check for cached version of mix dependencies.
  • NodeJS action.
  • Optional chromedriver action (feel free to remove this if you're not using integration tests).
  • Install mix dependencies.
  • Compile frontend assets.
  • Run tests.

Test Workflow

Now you can commit your code to the Github repo and under the "Actions" tab you can watch the progress.

$ git add .
$ git commit -m "Add github actions"
$ git push origin

As you can see from the output, the cache action we added runs the Post actions/[email protected] step that will cache our mix deps.

This cache will be used in the Run actions/[email protected] step to save some amount of time per workflow run.

Wrapping Up

There are many more actions and steps that you can customize for your own workflows but this has just covered the most basic use-case.

Hopefully you found this useful!  We'll likely expound on this and cover more CI systems if there's enough interest.

Thanks for reading!

Connect


Author image

About Troy Martin

Ruby, Elixir and Javascript Software Developer.