关于CodeBuild和CodePipeline的说明

356 阅读5分钟

我们应该使用Jenkins还是CodeBuild?这是一个永恒的问题。

一方面,Jenkins允许你在你的版本库中定义构建和管道,另一方面,Jenkins服务器是一个需要维护的猛兽。

CodeBuild和CodePipeline本质上是无服务器的Jenkins......但缺少一些关键的东西。

缺少了什么?

一些不好的东西已经消失了

  • 服务器补丁
  • 构建代理的数量管理
  • 根据负载情况调整Jenkins服务器的规模
  • 为服务器闲置时的时间付费
  • Jenkins主机配置之间的随机变化

缺少一些好东西

  • 一个干净的管道脚本语言
  • 自动发现组织中的构建内容
  • 整体的仪表盘来导航你的组织
  • 构建/管道的单一图片

CodeBuild和管道FTW

尽管失去Jenkins可能会有短期的缺点,但如果你已经在使用AWS,CodeBuild的方法实在是太容易被拒绝了。唯一的转折点是,如果你已经在Jenkins中拥有巨大的不动产,可能不值得迁移。或者,如果你有一套复杂的、相互调用的构建,那么Jenkins可能会有帮助。

最后,如果某个地方的管理员很乐意为你运行一个Jenkins农场,那么也许要走的路是50/50。

弥补差距

在我目前的任务中,我试图解决三个问题:

  • 扫描我们GitHub组织的仓库,自动生成构建和管道
  • 规范构建和管道的工作方式,并进行适当的复制和粘贴
  • 因此,使用声明式管道脚本进行部署

我已经用自己的工具解决了这个问题,下面我大概分享一下我是如何做到的。

适量的复制和粘贴

我们倾向于发现我们的Jenkinsfile 是大量复制和粘贴的来源,也许这是好的。一个基本的buildspec.yaml ,为每一个分支吐出构建,不会有那么多的变化,但却几乎无法参考。

如果不同的 repo 构建的关键部分是共享的资产,你就会得到奇怪的跨项目的依赖性,这其实并没有什么好处。

什么是标准的构建过程?

有很多方法可以使CodeBuild和CodePipeline成熟。我们的流程是:

  • CodeBuild由GitHub的每个PUSH请求触发,进行构建。
  • 如果推送到main ,那么CodeBuild规范就会将构建的资产打包,并将其放入S3供CodePipeline使用。
  • CodePipeline观察S3并在有新包时运行。

尽管CodePipeline可以由GitHub触发,但我们并不希望每个分支都有部署。我们希望每个分支都有一个构建。

如何产生构建和管道

CodeBuild和CodePipeline可以通过Cloudformation模板创建。如果我们有某种工具可以生成一个Cloudformation模板来描述我们需要的所有构建和管道,那么我们就可以部署该模板,构建就会存在。

所以,我们创建一个扫描工具作为一个预定的lambda,扫描GitHub并输出模板。然后,让我们有一个CodePipeline作业,它消耗输出的模板,并部署它来创建各种构建。哦,让我们为预定的lambda定义构建和管道,以及在这个_超级_模板中为生成的模板定义管道。

这意味着你第一次在本地运行lambda时,它就会吐出模板来引导AWS中的整个架构。

这是很不错的。

这也意味着,如果扫描注意到一个不再存在的 repo,或者需要一个构建或管道,产生的模板将省略这些构建,导致这个过程既创建又删除模板(也更新它们)。

那么,我如何创建这样一个东西?

你如何精确地选择这样做,是一个你能制造和支持什么的问题。以下是我使用的技术栈:

  • 用于Lambda的TypeScript
  • Octokit 作为GitHub客户端
  • yaml 作为一个Java/TypeScript yaml读写器
  • jszip 来制作推送到S3的压缩文件

我的解决方案是将它要存储在S3中的模板与已经存在的模板进行比较,如果没有区别,就不重新发布。

诡异的怪癖!Ref

最后一个细节是,.yml 中的Cloudformation模板喜欢使用!Ref ,以代替某些值来引用模板的其他部分。事实证明,让这一点在一个通用的.yml 阅读器上工作是相当困难的。其他的快捷函数也是如此(在我的解决方案中没有使用)。

结论

我花了不少功夫才把它弄好,但在使用它的头几个小时里,它几乎把我所有的构建和管道都喷出来了,而且它们都能工作。我允许每个 repo 对构建和管道的细节有一些控制,如果他们想的话,但到目前为止,我很少需要它。

这个解决方案似乎可以很好地利用现有的工具。我相信它会有一些成长的痛苦,但同样,它似乎在标准和复制/粘贴模板之间取得了良好的平衡。

说白了,要获得一个构建,我只需要写一个buildspec.yaml 文件,一个构建会在几分钟内出现(除非我不耐烦,用手去触发lambda)。

要获得一个管道,我只需写一个小的自定义.yml 文件,其中包含一些参数,描述我想使用我们标准管道的哪些功能。

自定义是通过允许混入的方式实现的,我们可以在Cloudformation模板的标准部分添加一些覆盖值,所以要解释的新语法越少越好。

我可能会在以后的报告中说,这最终使生活变得艰难,但我们目前真的很享受这种方法的蜜月期。