Example 1 :
docker_build_local.ml contains a simple example pipeline:
(* Run "docker build" on the latest commit in Git repository [repo]. *) let pipeline ~repo () = let src = Git.Local.head_commit repo in let image = Docker.build ~pull ~timeout (`Git src) in Docker.run image ~args:["dune"; "exec"; "--"; "docker_build_local"; "--help"]
This monitors a local Git repository (
repo), from which it gets the current head commit.
It copies it to a temporary clone and builds it with
docker build /path/to/clone, then
executes the example with
--help to check that it runs.
You can test it using a clone of the OCurrent repository itself:
$ dune exec -- docker_build_local . current_web [INFO] Starting web server: (TCP (Port 8080)) current [INFO] Result: Running [...] current.docker [INFO] Built docker image sha256:caf89896b8ad0fe08dede715b3b0f73815b4c6e7687dc0b38cb4a269a5ce7106 [...] current [INFO] Result: Ok: ()
If you make a new commit or change branch (e.g.
git checkout -b test HEAD~1) then OCurrent will
notice and build it again.
The example code above works mostly with values of type
Docker.build takes a source current and returns a Docker image current.
If you have a function that works on concrete values then you can use
let+ syntax) to make it work on currents instead.
You can also use
Current.bind (or the
let* syntax) if you can only decide
what the next part of the pipeline should be by looking at a concrete input.
bind limits OCurrent’s ability to analyse the pipeline,
because it must wait for the input to be ready before knowing what happens
It is almost never necessary to use a bind, and many large pipelines (such as
ocaml-ci) don’t use any.
If you feel you must use a bind, consider using
let** instead, which at least
allows you to label the box in the diagram.
OCurrent has a small core language (in
lib_term), but most
functionality is added by external libraries. See the plugins directory for
The example also runs a minimal web UI on port 8080 (use
--port=... to change it),
showing the state of the system. You will need to have graphviz installed in order
to see the diagrams.
A green box indicates a pipeline stage that succeeded, orange means in-progress, grey means cannot be started yet (inputs not ready), yellow means queued or waiting for permission to start, and red means failed.
Clicking on a box shows the log for that operation (though not all operations
head commit doesn’t, for example).
Example 2 :
build_matrix.ml contains a slightly more advanced pipeline:
let weekly = Current_cache.Schedule.v ~valid_for:(Duration.of_day 7) () (* Run "docker build" on the latest commit in Git repository [repo]. *) let pipeline ~repo () = let src = Git.Local.head_commit repo in let build ocaml_version = let base = Docker.pull ~schedule:weekly ("ocaml/opam:debian-ocaml-" ^ ocaml_version) in let dockerfile = let+ base = base in `Contents (dockerfile ~base ~ocaml_version) in Docker.build ~label:ocaml_version ~pull:false ~dockerfile (`Git src) |> Docker.tag ~tag:(Fmt.str "example-%s" ocaml_version) in Current.all [ build "4.10"; build "4.11" ]
Docker.pull step shows the use of a schedule. In this case, we consider
a pulled image to be valid for one week; after that OCurrent will automatically
docker pull again to check for newer versions.
Current.all to build against different versions of OCaml, generating
a suitable Dockerfile for each version (the
ocaml/opam2 image contains multiple
versions of the compiler and the Dockerfile just selects one of them).
The generated images are then tagged with the compiler version used to build them.