# Basic CircleCi Configuration

**URL:** <https://discuss.ocaml.org/t/basic-circleci-configuration/7215>\
**Category:** Ecosystem\
**Created:** [February 5, 2021, 7:50pm UTC](https://discuss.ocaml.org/t/basic-circleci-configuration/7215 "2021-02-05T19:50:33Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![lambda\_foo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lambda_foo/32/275_2.png) [@lambda\_foo](https://discuss.ocaml.org/u/lambda_foo)\
**Post date:** [February 5, 2021, 7:50pm UTC](https://discuss.ocaml.org/t/basic-circleci-configuration/7215/1 "2021-02-05T19:50:33Z")

</div>

I wanted to share a simple configuration for running OCaml projects in [CircleCI](https://circleci.com)  
that I’ve been using. CircleCI is what I’m using at work, it supports a nice feature of  
allowing SSH onto the machine where a build is run. Letting you debug setup issues which is really helpful.

My requirements are simple to build OCaml projects that use OPAM and have simple test requirements (just running unit tests).

First you need to add a file `.circleci/config.yml` with:

```auto
version: 2
jobs:
  build-4.10:
    docker:
      - image: ocaml/opam:ubuntu-18.04-ocaml-4.10
    steps:
      - checkout
      - run:
          name: Build
          command: ./bin/ci

workflows:
  version: 2
  build:
    jobs:
      - build-4.10

```

This creates a job `build-4.10` using docker image `ocaml/opam2:4.10` published by the OCaml team. The `steps` defines the commands to run, we use a built in `checkout` command provided by CirclCI and then a `run` command that executes a shell script `./bin/ci`.

You could use your own docker container in place of `ocaml/opam2:4.10`, maybe pre-installing some things or using a different linux distro. How to run the command could also be inlined rather than being its own file. I chose to make it a file for two reasons, when you SSH to debug a script you can just re-run `./bin/ci`, and you can re-use the steps between local and CI.

Now to the shell script

```auto
#!/bin/sh -eux

WORKING_DIR=$(pwd)

# Install some extras
sudo apt-get install m4 pkg-config -y

# Make sure opam is setup in your environment.
eval `opam config env`
opam update

# Install each package as a dev dependency
find . -type f -name '*.opam' | sort -d | while read P; do
  opam pin add -n "$(basename -s .opam ${P})" . -y --dev
  opam install --deps-only "$(basename -s .opam ${P})" -y
  eval `opam config env`
done

# Run the builds and
dune build
dune runtest

```

This configuration is from a project with multiple `opam` files so we have a `find`  
to locate all those files. One gotcha with this is it’ll sort the file names which may not match the dependency order, if that is the case you will need to explicitly list them.

If you have a single `opam` file then replace that with the following (replacing `project-name` with your project name).

```auto
opam pin add -n "project-name" . -y --dev
opam install --deps-only "project-name" -y

```

Push that into your github main branch, then `Set up Project` in the circleci UI and you should be off and building. From here the circleci docs can help with setting up different builds based off branches. Adding other OCaml builds is as easy as duplicating the `build-4.10` section in YAML, pointing it to another docker container like `4.08` and adding the new build name to `workflows` under `jobs:`.

This configuration doesn’t include any explicit caching, adding opam caching would help speed up builds. What’s the right directory to cache for opam? Just `~/.opam` I assume.

I also tried using the [GitHub - ocaml/ocaml-ci-scripts: Skeletons for CI scripts](https://github.com/ocaml/ocaml-ci-scripts) but they’re too travis-ci specific.

---

<div class="post-metadata">

**Author:** ![avsm](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/avsm/32/6_2.png) [@avsm](https://discuss.ocaml.org/u/avsm)\
**Post date:** [February 8, 2021, 10:07am UTC](https://discuss.ocaml.org/t/basic-circleci-configuration/7215/2 "2021-02-08T10:07:34Z")

</div>

Great writeup Tim! Just a minor correction – you should be using `ocaml/opam` as the base for the Docker images now, since those are the ones [regularly rebuilt](https://base-images.ocamllabs.io).

The migration from the older `ocaml/opam2` might seem messy, but unfortunately we are limited in how much we can do using the registries without breaking a bunch of existing users (I wish we had namespace redirects!). I’ll take a look at fixing up our documentation for CI online as soon as I read through the related GitLab CI thread as well.

---

<div class="post-metadata">

**Author:** ![lambda\_foo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lambda_foo/32/275_2.png) [@lambda\_foo](https://discuss.ocaml.org/u/lambda_foo)\
**Post date:** [February 8, 2021, 10:49am UTC](https://discuss.ocaml.org/t/basic-circleci-configuration/7215/3 "2021-02-08T10:49:42Z")

</div>

Fantastic thanks for the correction @avsm I’ll update the instructions.
