GitHub has made actions available to anyone that requests it and is planning on launching in November so now is a good time to start moving your projects across.
There are a lot more features available now including matrix builds and attached services. GitHub also detects an Elixir repository and gives you a starting point for your workflow.
The default workflow looks like this:
name: Elixir CI
on: push
jobs:
build:
runs-on: ubuntu-latest
container:
image: elixir:1.9.1-slim
steps:
- uses: actions/checkout@v1
- name: Install Dependencies
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get
- name: Run Tests
run: mix test
This works great for very basic setups, unfortunately for me the first stumbling block was the container image doesn't have any build tools (eg. make
) so it wasn't able to compile bcrypt_elixir
among other dependencies.
Hovever, the host does have build tools available so instead of running it in a container we can install elixir and erlang (OTP) on the host. GitHub even have an action to do this which is handy!
This makes the basic configuration look like this:
name: Elixir CI
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-elixir@v1.0.0
with:
otp-version: 22.x
elixir-version: 1.9.x
- name: Install Dependencies
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get
- name: Run Tests
run: mix test
This will work as a simple CI for a lot of Elixir projects, but for Phoenix projects we need a bit more.
This configuration sets up a standard Elixir/Phoenix environment (OTP, Elixir and Node) with a Postgres container. It then compiles the code and assets, runs the tests and builds & publishes a release to GitHub releases.
name: Elixir CI
on: push
jobs:
test:
runs-on: ${{ matrix.os }}
name: OTP ${{ matrix.otp }} | Elixir ${{ matrix.elixir }} | Node ${{ matrix.node }} | OS ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-18.04]
otp: [22.x]
elixir: [1.9.x]
node: [12.x]
services:
db:
image: postgres:11
ports: ['5432:5432']
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v1.0.0
- uses: actions/setup-elixir@v1.0.0
with:
otp-version: ${{ matrix.otp }}
elixir-version: ${{ matrix.elixir }}
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node }}
- name: Install dependencies
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get
yarn --cwd assets install
- name: Run tests
run: |
mix compile --warnings-as-errors
mix format --check-formatted
mix test
env:
MIX_ENV: test
- name: Prepare release
run: |
mix compile
yarn --cwd assets deploy
mix phx.digest
mix release
env:
MIX_ENV: prod
- name: Publish release
uses: moomerman/actions/bin/ghr@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_PATH: _build/prod/rel
APPLICATION: <<APP NAME>>
We've also added the strategy/matrix configuration above which isn't entirely necessary in this example but I like how it ends up having all the versions of dependencies clearly labelled in one place and it allows for extending the matrix to other versions very easily.
A couple of gotchas I found so far (which could be user error) are:
I couldn't find a way of specifying the version of an image in the matrix, eg. v11 of postgres above
I tried to use the ofiicial nodejs docker image to execute the
yarn
commands rather than running thesetup-node
action on the host, but this resulted in assets that had permissions that meant the host couldn't modify them which seems like a bug.
The newer format is definitely a lot easier to follow and is extremely powerful. It still takes a while to run, there's no official caching support (though there are a number of optimisations behind the scene) but I expect that to improve soon.
You can see an example of an phoenix project running an adaptation of this configuration on GitHub at moomerman/httping.
If you have any tips or feedback please get in touch via Twitter.
Top comments (0)