This section documents day-to-day tasks in a project that uses opam-monorepo
.
There are several ways to configure a project to use opam-monorepo
, depending on what is checked into Git.
opam monorepo pull
.duniverse
folder into Git. This ensures that the repository is self-contained, but it can be very large.opam-monorepo
workflow, but it is a way opam-monorepo
can be used to build a project even if it doesn't use opam-monorepo
.As a summary:
duniverse
ignored.duniverse
checked in.duniverse
not checked in.We recommend using the lockfile-in-git workflow. To enable it, first generate a lock file (using opam monorepo lock
), add it to your Git repository, together with project.opam
, and add duniverse/
in .gitignore
.
Manage duniverse explains in more depth how to best manage the files that opam-monorepo
generates.
Note: if you use ocaml-ci, you don't have anything to do. It will detect opam-monorepo
builds and replace the opam-based builds by an opam-monorepo
aware build that implements the rest of this section.
This section is useful if you want to implement a CI system based on opam-monorepo
.
A build consists in three steps:
In this context, "the environment" is a set of programs to be put in $PATH
. An opam-monorepo
build requires an OCaml compiler, Dune, and opam-monorepo
. The project might require system packages ("depexts") too. It's possible to rely on opam
to install this environment, but it's not technically required.
The following assumes that opam is being used.
To set up the environment:
duniverse
folder, and source code are not used)opam-monorepo
. The version to pick depends the lock file format version (x-opam-monorepo-version
field in the lock file). The rule is that a lock file with version 0.N can be interpreted by opam-monorepo
version 0.N.*
, but in most cases, opam-monorepo
can read older versions. As opam-monorepo
reaches version 1.0.0, more stability guarantees will exist.opam show -f depexts
./project.opam.locked
. In a future version, a command opam monorepo depext
will provide a way to install them directly.The next step is to set up a workspace that contains your project and its dependencies.
opam monorepo pull
.In this step, the workspace is ready, so dune build
commands can succeed. The exact command to run depends on the project, but for CI, dune build
followed by dune runtest
is usually the right thing to do (or in a single step, dune
build @all @runtest
). If the goal of that pipeline is to produce release binaries, passing --profile release
might be better. Consult the Dune documentation to know more about the difference.
This build skeleton can benefit from several caching strategies. The first one is to use a layering approach, e.g., by using Docker.
Most of the steps only require the lock file, so they can be cached and invalidated when the lock file changes.
For the OCaml compiler version, this can be a bit too conservative, as it will cause any change in the lock file to rebuild a switch. Instead, it's possible to hardcode the OCaml compiler version in the Docker file, and only check that the version is correct during the "setup environment" phase.
Doing only this will start all builds with an empty _build
directory, so all dependencies need to be built each time. One solution to this is to persist the _build
directory between builds. This can even be done across branches (the cache key is just the project name).
For local development, this means that _build
is expensive to rebuild (similarly to a local opam switch). It is possible to set up a machine-global dune cache to speed up rebuilds.
To upgrade dependencies, run opam monorepo lock
. It will compute a new solution based on the constraints in project.opam
and the current state of opam-repository
. Then locally run opam monorepo pull
to update the duniverse/
folder.
It's recommended to regularly create pull requests to update dependencies. When updating a local copy, developers will need to call opam monorepo pull
.
Note: this section also applies to all the cases where there are changes to the dependencies in project.opam
, for example if a version constraint is modified.
To add a dependency:
project.opam
directly, or if you use opam file generation, add it to dune-project
and run dune build
.opam monorepo lock
.duniverse/
folder using opam monorepo pull
.project.opam
, the lock file, and optionally dune-project
.This has the side effect of upgrading all dependencies too. To get a more conservative upgrade, one can do the upgrade in two steps: