CI/CD流水线创建方法?

本文将用三种方法来创建 CI/CD 流水线 。Monad 不能对流水线进行静态分析,Arrow 语法很难用,我称之为 Dart(不知道它是否已经有名字了)的一种轻量级的 Arrow 方法可以像 Arrow 一样进行静态分析,但语法比 Monad 更简单 。
我需要构建一个用于创建 CI/CD 流水线的系统 。它起初是为了构建一个 CI 系统,测试 Github 上的 OCaml 项目(针对多个版本的 OCaml 编译器和多个操作系统,测试每个提交) 。下面是一个简单的流水线,获取某个 Git 分支最新的提交,构建,并执行测试用例 。
【译者注】CI/CD:持续集成(Continuous Integration)和持续部署(Continuous Deployment)简称,指在开发过程中自动执行一系列脚本来减低开发引入 bug 的概率,在新代码从开发到部署的过程中,尽量减少人工的介入 。

CI/CD流水线创建方法?

文章插图
 
这里的配色标识是:绿色的方框是已经完成,橙色的是正在进行,灰色的意味着这一步还不能开始 。
这里有一个稍微复杂点的例子,它还下载了一个 Docker 基础镜像,使用两个不同版本的 OCaml 编译器并行构建提交,然后测试得到的镜像 。红框表示此步骤失败:
CI/CD流水线创建方法?

文章插图
【CI/CD流水线创建方法?】 
一个更复杂的例子是测试项目本身,然后搜索依赖它的其他项目,并根据新版本测试这些项目:
CI/CD流水线创建方法?

文章插图
 
在这里,圆圈意味着在检查反向依赖项之前,我们应该等待测试通过 。
我们可以用 YAML 或类似的方法来描述这些管道,但这将是非常有限的 。相反,我决定使用一种特定于领域的嵌入式语言,这样我们就可以免费使用宿主语言的特性(例如字符串操作、变量、函数、导入、类型检查等) 。
最明显的方法是使每个框成为正则函数 。然后上面的第一个例子可以是(这里,使用 OCaml 语法):
let example1 commit =let src = https://www.isolves.com/it/cxkf/bk/2021-02-19/fetch commit inlet image = build src intest image第二个可能是:
let example2 commit =let src = https://www.isolves.com/it/cxkf/bk/2021-02-19/fetch commit inlet base = docker_pull "ocaml/opam2" inlet build ocaml_version =let dockerfile = make_dockerfile ~base ~ocaml_version inlet image = build ~dockerfile src ~label:ocaml_version intest imageinbuild "4.07";build "4.08"第三个可能是这样的:
let example3 commit =let src = https://www.isolves.com/it/cxkf/bk/2021-02-19/fetch commit inlet image = build src intest image;let revdeps = get_revdeps src inList.iter example1 revdeps不过,我们想在语言中添加一些附加功能:
  • 管道步骤应尽可能并行运行 。上面的 example2 函数将一次完成一个构建 。
  • 管道步骤应在其输入更改时重新计算 。e、 当我们作出新的承诺时,我们需要重建 。
  • 用户应该能够查看每个步骤的进度 。
  • 用户应该能够为任何步骤触发重建 。
  • 我们应该能够从代码中自动生成图表,这样我们就可以在运行管道之前看到它将做什么 。
  • 一步的失败不应该使整个管道停止 。
对于这篇博客文章来说,确切的附加功能并不重要,因此为了简单起见,我将重点放在同时运行步骤上 。
Monad 方法
【译者注】Monad:函子,单子,来自 Haskell 编程语言,是函数式编程中,一种定义将函数(函子)组合起来的结构方式,它除了返回值以外,还需要一个上下文 。常见的 Monad 有计算任务,分支任务,或者 I/O 操作 。
如果没有额外的功能,我们有如下功能:
val fetch : commit -> sourceval build : source -> image您可以将其理解为“build 是一个获取源值并返回(Docker)镜像的函数” 。
这些函数很容易组合在一起,形成一个更大的函数来获取提交并构建它:
let fab c =let src = https://www.isolves.com/it/cxkf/bk/2021-02-19/fetch c inbuild src
CI/CD流水线创建方法?

文章插图
 
我们还可以将其缩短为 build(fetch c)或 fetch c |>build 。OCaml 中的|>(pipe)运算符只调用其右侧的函数,而参数在其左侧 。
为了将这些函数扩展为并发的,我们可以让它们返回承诺,例如,
val fetch : commit -> source promiseval build : source -> image promise


推荐阅读