CI/CD for an OCaml Project with GitHub Actions
Build, test, and format-check your dune-based OCaml project.
OCaml projects use OPAM for packages and dune as the build system. The setup-ocaml action handles the OPAM switch and caching. This recipe builds, tests, and checks formatting.
What the pipeline does
- set up OCaml and OPAM with caching
- install deps with opam install
- build with dune build
- run tests with dune test
- check formatting with dune fmt
The workflow
ocaml/setup-ocaml provisions the compiler and caches the OPAM switch. dune runtest executes the test stanzas.
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: '5.2'
- run: opam install . --deps-only --with-test
- run: opam exec -- dune build
- run: opam exec -- dune runtest
- run: opam exec -- dune build @fmtCaching and speed
setup-ocaml caches the OPAM switch and downloaded packages, which is the biggest speedup since building an OPAM switch from scratch is slow. The native compile is CPU-bound; cheaper managed runners such as Latchkey keep builds fast and auto-retry transient OPAM repository fetches.
Deploying
dune build produces a native executable under _build/default. Ship it in a slim container or attach it to a GitHub Release. For library packages, publish to the opam repository by opening a release PR with dune-release.
Key takeaways
- setup-ocaml caches the OPAM switch for big speedups.
- dune build, runtest, and @fmt cover build, test, and format.
- Use dune-release to publish library packages to opam.