🐪 OCaml on GitHub

Using OCaml in GitHub with Actions/Workflows etc.
Published on Thursday, 12 October 2023

In this article I'll show you how to setup and configure GitHub Actions to work with an OCaml Library.

Rob Anderson @jamsidedown (Site) decided he's going to be doing ⭐️ AoC this year in OCaml! They wrote a new library ocaml-cll an OCaml circular linked list library, in preperation for this as it's been needed in other languages for previous questions.

To help out we looked at how to build the package using GitHub Actions.

See the example here: ocaml-example main.yml

Or the production one: ocaml-cll main.yml

Firstly as with most builds you setup your env with the language you need:

Another useful action is actions-ocaml.

- name: 🐪 Set-up OCaml
  uses: ocaml/setup-ocaml@v2
  with:
    ocaml-compiler: "5.0"
    dune-cache: true

Once configured you need to install any dependencies from your .opam/dune-project file.

- name: ⬇️ Install opam deps
  run: opam install . --deps-only --with-test

It's worth installing any global packages you need like odoc etc.

- name: ⬇️ Install opam global deps
  run: opam install odoc ocamlformat dune-release

Next build your project:

- name: 🔨 Build
  run: opam exec -- dune build

And test:

- name: 🧪 Test
  run: opam exec -- dune runtest

Or with coverage:

- name: 🧪 Test and Coverage
  run: "opam exec -- dune runtest --instrument-with bisect_ppx --force"
- name: 📄 Coverage Report"
  run: "opam exec -- bisect-ppx-report summary"

You can then build the docs:

- name: 📄 Build Docs
  run: opam exec -- dune build @doc

Then decide if you want to upload that as an artifact and deploy it to either GitHub Pages or another service.

Once you have a package you can add it to the opam-repository, example PRs here:


Complete:

jobs:
  build:
    runs-on: ubuntu-latest

    defaults:
      run:
        working-directory: src/helloworld

    steps:
      - name: 🛎️ Checkout
        uses: actions/checkout@v4

      - name: 🐪 Set-up OCaml
        uses: ocaml/setup-ocaml@v2
        with:
          ocaml-compiler: "5.0"
          dune-cache: true

      - name: ⬇️ Install opam deps
        run: opam install . --deps-only --with-test

      - name: ⬇️ Install opam global deps
        run: opam install odoc ocamlformat dune-release

      - name: 🔨 Build
        run: opam exec -- dune build

      - name: 🧪 Test
        run: opam exec -- dune runtest

      - name: 📄 Build Docs
        run: opam exec -- dune build @doc
      
      - name: Upload API Docs artifact
        uses: actions/upload-artifact@v3.1.3
        with:
          name: docs
          path: ./src/helloworld/_build/default/_doc/_html

      - name: Deploy API Docs
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          user_name: 'github-actions[bot]'
          user_email: 'github-actions[bot]@users.noreply.github.com'
          publish_dir: ./src/helloworld/_build/default/_doc/_html
          destination_dir: docs
          enable_jekyll: true

ocaml-cll