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.

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.

new workflow

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