Elixir#

This guide covers configuring Elixir projects on Semaphore. If you’re new to Semaphore, please read our guided tour first.

Hello World#

# .semaphore/semaphore.yml
version: v1.0
name: Hello Semaphore
agent:
  machine:
    type: e1-standard-2
    os_image: ubuntu2004
blocks:
  - name: Elixir example
    task:
      jobs:
      - name: Run some code
        commands:
          - elixir 'IO.puts "Hello world!"'

Phoenix example project#

Semaphore provides a tutorial and demo Phoenix application with a working CI pipeline that you can use to get started quickly:

Supported Elixir versions#

Semaphore supports all versions of Elixir. You have the following options:

Follow the links above for details on currently available language versions and additional tools.

Selecting an Elixir version on Linux#

Semaphore uses kiex to manage Elixir versions. Any version installable with kiex is supported on Semaphore. You may install new versions and change them with sem-version. Here's an example:

blocks:
  - name: Tests
    task:
      prologue:
        commands:
          - kiex install 1.6
          - sem-version elixir 1.6
      jobs:
        - name: Tests
          commands:
            - elixir --version

Test summary#

!!! beta "Feature in beta". Beta features are subject to change.

General test summary guidelines are available here ↗.

Test Summary Tab

Generating JUnit XML report#

We will start with adding junit-formatter ↗ to your mix.exs dependencies:

defp deps do
  [
    # ...
    {:junit_formatter, "~> 3.1", only: [:test]}
  ]
end

Then install the dependencies:

mix deps.get

Now we have to make sure that our formatter is properly configured and used by rspec. There are two ways we can do this:

  • Extend your config/test.exs configuration file
config :junit_formatter,
  report_dir: "/tmp",
  report_file: "junit.xml", # Save output to "/tmp/junit.xml"
  print_report_file: true, # Adds information about file location when suite finishes
  include_filename?: true, # Include filename and file number for more insights
  include_file_line?: true
  • Extend your test/test_helper.exs configuration file
ExUnit.configure(formatters: [JUnitFormatter, ExUnit.CLIFormatter])
ExUnit.start()

Running your tests with this setup will also generate a junit.xml summary report.

Publishing results to Semaphore#

To make Semaphore aware of your test results, you can publish them using test results CLI ↗:

test-results publish /tmp/junit.xml

We advise to include this call in your epilogue:

epilogue:
  always:
    commands:
      - test-results publish /tmp/junit.xml

This way even if your job fails (due to the test failures) results will still be published for inspection.

Example configuration#

Your CI configuration should look similiar to this:

- name: Tests
  task:
    prologue:
      commands:
        - checkout
        - mix deps.get
    jobs:
      - name: Elixir Tests
        commands:
          - mix test
    epilogue:
      always:
        commands:
          - test-results publish /tmp/junit.xml

Demos#

You can see how test results are set up in one of our demo projects ↗.

Dependency caching#

You can use Semaphore's cache command to store and load the build and dependency cache. In the following configuration example, we install dependencies and warm the cache in the first block. Then we use the cache in subsequent blocks.

version: v1.0
name: Elixir & Phoenix Example
agent:
  machine:
    type: e1-standard-2
    os_image: ubuntu2004

blocks:
  - name: Install dependencies
    task:
      env_vars:
        - name: MIX_ENV
          value: test
      jobs:
        - name: mix and cache
          commands:
            - checkout
            # Be sure to use --force to skip confirmation prompts
            - mix local.hex --force
            - mix local.rebar --force
            - cache restore
            - mix do deps.get, compile
            - cache store
  - name: Tests
    task:
      env_vars:
        - name: MIX_ENV
          value: test
      prologue:
        commands:
          - checkout
          # Restore dependencies and compiled code
          - cache restore
      jobs:
        - name: Everything
          commands:
            - mix test

Environment variables#

Semaphore doesn't set language specific environment variables like MIX_ENV. You can set these at the task level.

blocks:
  - name: Tests
    task:
      env_vars:
        - name: MIX_ENV
          value: test
      jobs:
        - name: Everything
          commands:
            - mix test

System dependencies#

Projects may need system packages like database drivers. You have full sudo access so you may install any required packages. Here's an example of installing the Postgres dependencies:

blocks:
  - name: Tests
    task:
      prologue:
        commands:
          - sudo apt-get update && sudo apt-get install -y libpq-dev
          - mix install
      jobs:
        - name: Everything
          commands:
            - mix test