Elixir GitHub Action for Windows
When our Elixir code is directly interacting with host operating system, it is nice to have automated tests integrated for all targeted operating systems. Github actions makes this task easier than before but unfortunately elixir-setup does not support operating systems other than ubuntu yet. I tried to find a solution for this for one of my elixir library
Using Chocolatey package manager
We can use Chocolatey Action install elixir. Chocolatey also installs Erlang as elixir dependency for us.
choco install elixir
But we can’t access Elixir or mix yet. With github-actions, we have to explicitly update PATH environment variable using an undocumented special syntax
echo "##[add-path]C:\ProgramData\chocolatey\lib\Elixir\bin"
Our workflow for tests might look like this:
name: Elixir
on: push
jobs:
run_tests:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Install Elixir
uses: crazy-max/ghaction-chocolatey@v1.2.2
with:
args: install elixir
- name: Update PATH
run: echo "##[add-path]C:\ProgramData\chocolatey\lib\Elixir\bin"
- name: Install Dependencies
run: |
mix local.hex --force
mix.bat deps.get
- name: Compile
run: mix.bat compile --force --warnings-as-errors
- name: Check format
run: mix.bat format --check-formatted
- name: Run Tests
run: mix.bat test
This approach works, but it has few issues:
Pipeline is slow
When I tested this, the pipeline took 6m 41s. Installation alone took 6m 15s. We install Elixir and Erlang/OTP every time we run this pipeline. This includes downloading packages, extracting and installing.
Changing Elixir and Erlang version is not easy
We can change Elixir version with --version
parameter with chocolatey, but now we sort of depend on chocolatey. Also, we can not combine different Erlang and Elixir with this. Moreover, we are already leaking installation by setting path environment variable explicitly.
Manual setup with cache
Quick look at chocolatey revealed that installing Erlang and Elixir from command-line is not as complicated as I thought. New approach is to manually install Erlang and Elixir and setup action-cache to reuse installation across pipelines.
- check Erlang installation cache
- download and install Erlang if not in cache
- add Erlang to path
- check Elixir installation cache
- download and install Elixir if not in cache
- add Elixir to path
This is slightly more complicated than our previous setup using chocolatey but it is faster and more flexible.
name: Elixir
on: push
env:
OTP_VERSION: 22.2
ELIXIR_VERSION: 1.9.4
jobs:
run_tests:
runs-on: windows-latest
name: Windows
steps:
- name: Cache erlang
uses: actions/cache@v2
id: erlang_cache
with:
path: C:\Program Files\erl10.6
key: erlang-${{ runner.os }}-${{ env.OTP_VERSION }}
- name: Download and install erlang
if: steps.erlang_cache.outputs.cache-hit != 'true'
run: |
Invoke-WebRequest "http://erlang.org/download/otp_win64_$env:OTP_VERSION.exe" -OutFile "C:\otp_win64_$env:OTP_VERSION.exe"
Start-Process -Wait "C:\otp_win64_$env:OTP_VERSION.exe" /S
- name: Add erlang to path
run: echo "##[add-path]C:\Program Files\erl10.6\bin"
- name: Cache Elixir
uses: actions/cache@v2
id: elixir_cache
with:
path: c:\elixir
key: elixir-${{ runner.os }}-${{ env.ELIXIR_VERSION }}
- name: Download and install Elixir
if: steps.elixir_cache.outputs.cache-hit != 'true'
run: |
Invoke-WebRequest "https://github.com/elixir-lang/elixir/releases/download/v$env:ELIXIR_VERSION/Precompiled.zip" -OutFile "C:\elixir_$env:ELIXIR_VERSION.zip"
Expand-Archive "C:\elixir_$env:ELIXIR_VERSION.zip" -DestinationPath c:\elixir
- name: Add elixir to path
run: echo "##[add-path]C:\elixir\bin"
- name: Install Dependencies
run: |
mix local.hex --force
mix.bat deps.get
- name: Compile
run: mix.bat compile --force --warnings-as-errors
- name: Check format
run: mix.bat format --check-formatted
- name: Run Tests
run: mix.bat test
This brings down pipeline execution time from 6m 41s to 2m.
You can check working setup here
Our new setup is still far from ideal. We are leaking Erlang installation path C:\Program Files\erl10.6
which changes with Erlang version. Hopefully we get windows support in setup-elixir soon