I don’t know if the OP is reading here, but I’m curious as to how one takes the static analysis of a given CI/CD pipeline and turns it into one of those graphs. That wasn’t obvious from the article, at least to my tired brain.

The pp_dot function there outputs a graphviz dot file. There’s a bit of complexity to do with simplifying the graphs. For example, if we have arrows a->b, b->c and a->c then we don’t show the a->c one because it’s somewhat implied by the others, and larger graphs get cluttered easily.

Basically, all the functions and datatypes (fetch, build, commit, etc) are part of an interface (as modules and signatures in OCaml). You have one implementation that actually does the fetching and building, and one implementation that just constructs a graph.
The arrow and promise types are also part of the interface, implemented with either async or graph.

I don’t know if the OP is reading here, but I’m curious as to how one takes the static analysis of a given CI/CD pipeline and turns it into one of those graphs. That wasn’t obvious from the article, at least to my tired brain.

Each term gets a “static” and a “dynamic” part. The static part is used to create the graphs, using this code:

https://github.com/ocurrent/ocurrent/blob/master/lib_term/analysis.ml

The

`pp_dot`

function there outputs a graphviz dot file. There’s a bit of complexity to do with simplifying the graphs. For example, if we have arrows a->b, b->c and a->c then we don’t show the a->c one because it’s somewhat implied by the others, and larger graphs get cluttered easily.Basically, all the functions and datatypes (

`fetch`

,`build`

,`commit`

, etc) are part of an interface (as modules and signatures in OCaml). You have one implementation that actually does the fetching and building, and one implementation that just constructs a graph. The`arrow`

and`promise`

types are also part of the interface, implemented with either`async`

or`graph`

.