Coletiv is a custom software development studio from Porto that transforms ideas into high-quality applications. We help companies of all sizes design, develop, and launch digital products for iOS, Android, and the web.

From our earliest days, continuous integration (CI) and continuous delivery (CD) have been requirements for every project that we have built. We needed a tool that could cover Elixir as well as the native iOS and Android platforms that we work with. After testing several tools, we settled on CircleCI as our tool of choice.

Sharing our knowledge with the community is a part of Coletiv’s culture. At the beginning of 2019, we wrote, “How to automate the deployment of your Elixir project with CircleCI.” That post caught the attention of the CircleCI team and we were challenged to contribute to the community by creating a CircleCI orb targeted at Elixir-based projects. If you are not familiar with orbs, they are shareable packages of CircleCI configuration. You can read more about orbs in the announcement here.

What did we gain from creating our orb?

Every time we would start a new project, we needed to copy the automation configuration over. If we made an improvement to the config file in one project, the improvement would need to be copied to all of the other projects as well. This was a very tedious and error-prone task. One of the first thoughts that came to mind when we heard about the launch of CircleCI orbs was that it would provide us with the opportunity to have our core configuration centralized in one place and share it across all of our projects.

Orbs also introduce the possibility of sharing the configuration with other developers. This allows for them to take advantage of the orb and also to contribute and improve it. Elixir first appeared in 2011. It is still a young language with many developers beginning to experiment with it. One common struggle developers have with Elixir is configuring CI/CD into their project. Having an orb that others can use will reduce this barrier to entry.

Using the Elixir orb


For our orb, we opted to create a default executor with the following two images found on Docker Hub: circleci/elixir with the default tag 1.8.1, and circleci/postgres with the default tag 11.2-alpine-postgis. These were the latest versions available at the time of writing. You can search for different versions of each image in Docker Hub and pass those versions as parameters to the executor using elixir-version and/or postgres-version.

If you need additional images, you can create and use your own executor. It is common to use different configurations for different types of projects. This orb was originally intended for projects that use Elixir and PostgreSQL, and this is reflected in how the default executor was defined. Some projects will have other dependencies, such as FakeS3, to simulate the AWS S3 service. For those projects, you will need the appropriate Docker images to support it.

Orb jobs and commands

Orb commands are like puzzle pieces that you can fit together to run your project. We’ve searched for extra commands, apart from the basic build and test, to bring added value to projects. We’ve also implemented cache to optimize build times.

These are the commands that the orb supports:

  • build
  • test
  • check-format
  • coveralls
  • credo
  • dialyzer
  • edeliver-deploy
  • appsignal-send-marker

We created a few jobs and examples that you can try. These can be adapted to your project in a matter of minutes.

Here is an example of the minimal code that you will need in order to integrate the orb into your project. The build-and-test job will allow you to run the standard mix test, but you can improve that with different modules available as parameters: check-format, coveralls, credo, and dialyzer:

version: 2.1

  elixir: coletiv/elixir@0.1.0

      - elixir/build-and-test:
          check-format: true
          coveralls: true
          credo: true
          dialyzer: true

Note: If you want to use coveralls, credo, and dialyzer, you will need to install the respective packages.

If you need a more complex setup, like using FakeS3 or another Docker image, here is an example of that setup:

version: 2.1

  elixir: coletiv/elixir@0.1.0

      - image: 'circleci/elixir:1.8.1'
          MIX_ENV: test
      - image: 'circleci/postgres:11.2-alpine-postgis'
      - image: 'circleci/fakes3:0.2.4'
    executor: default
      - elixir/build
      - run: fakes3 -r $HOME/.s3bucket -p 4567 &
      - elixir/coveralls

      - build-and-test

Publishing the orb

Like any other software project, we needed to automate all the checks and deploys for this orb. These are the three essential jobs to complete the task: pack, publish, and increment.

  • Pack, as the name suggests, compiles the folder and files of different keys into one YAML file.
  • Publish deploys a development version of the orb, normally used for testing.
  • Increment normally runs when the code is merged into the master branch and deploys the orb directly into the CircleCI orb Explorer, incrementing its version.

We have created a mini-project in Elixir to test the orb, added it to the orb CI, confirming that the project is compiled and tested after the orb configuration is validated. This is useful because we ensure that the project can run with any new modifications we submit.

For a deeper dive into orb development, including testing and deploying, take a look at part 1 and part 2 of this series of blog posts about how to configure your workflows and improve the versioning of your orb.

Final thoughts

Building an orb was a fun learning experience! By introducing orbs, the CircleCI team has added tremendous value to our projects: shorter, more clean config files, opportunities for reusable config across projects, and an existing repository of other orbs that can be used. If you are exploring projects in Elixir, we encourage you to give our orb a try. If you want to contribute and improve it further, take a look into our orb GitHub repository.

David Magalhães is a Software Engineer and holds a M.Sc. in Informatics and Computing Engineering. Prior to joining Coletiv, David worked for various companies where he held different roles as an Application Security and Software Developer.