跳转到主要内容
Chinese, Simplified

不到三个月前,我们推出了CircleCI orbs,这是我们针对CircleCI配置的包管理生态系统。在这段时间里,我们已经看到,仅在最初的10周内就创建了300多个ORB,200多个组织在上万个构建中的1000多个项目中使用ORB。我们还通过新的技术合作伙伴计划推出了20多个官方合作伙伴球体。我们非常感谢大家的积极响应。

在这篇文章中,我想回顾一下,并分享一下创建和发布CircleCI orbs的关键设计决策。如果你现在正在使用orbs,并且想了解如何从中获得最大的收益,或者如果你正在考虑设计自己的包管理系统,那么这篇文章适合你。

什么是圆环球(CircleCI orbs)?

ORB是CircleCI配置的可共享包。与大多数其他代码打包系统一样,ORB提供了一组通用的抽象结构元素,使经过测试、封装的构建组件在整个组织以及更广泛的用户生态系统中的重用变得切实可行。ORB有一个用YAML语法定义的领域特定语言(DSL),它表达了构建配置的语义。这使得在构建配置中为封装的命令、作业和执行器编写惯用接口变得简单。

ORB还提供包管理基础设施。这使得发布版本明确的ORB,然后将其导入项目中使用变得非常简单。

设计球体是为了解决什么问题?

我们的工作是帮助团队活跃并加速他们的软件交付。充分利用CircleCI的关键要素之一是我们的构建配置,这是一种基于YAML的语义,用于描述CI管道的工作流、作业和环境。当我们开始构建ORB时,我们想解决与构建配置有关的三个关键问题:

1.更好的DRY支撑

CircleCI 2.0中的配置设计为高度透明、表达性和确定性。然而,这些特性也会使我们的基本语义变得冗长和重复。如果没有好的快捷方式和糖分,配置可能会有很多样板代码,这会妨碍项目设置,并且随着配置的复杂度和范围的增加,它会变得非常笨拙。

2.跨项目的代码重用

许多客户希望通过更好的方式在项目之间共享配置。CircleCI配置以前不容易在团队之间共享,这造成了不必要的冗余,并降低了团队的速度。我们拥有大型团队的客户希望能够轻松传播和实施通用模式和策略,并通过共享实践帮助他们的团队改进。

3.更容易实现通用配置

开发人员试图避免重新发明事物或重新解决已解决的问题。在引导代码时,他们希望在实用可靠的情况下使用现成的、经过磨练的封装。在CircleCI中,对于第一次使用的用户来说,从空白页面开始可能会让人望而生畏,我们希望能够更容易地从一无所有变成有用的东西。

不到三个月前,我们推出了CircleCI orbs,这是我们针对CircleCI配置的包管理生态系统。在这段时间里,我们已经看到,仅在最初的10周内就创建了300多个ORB,200多个组织在上万个构建中的1000多个项目中使用ORB。我们还通过新的技术合作伙伴计划推出了20多个官方合作伙伴球体。我们非常感谢大家的积极响应。

关键设计决策(以及我们做出这些决策的原因)

正如我们所料,设计一个新的包管理系统并不是一个简单的过程。在构建球体时,我们需要平衡可接近性、表达性、可移植性和决定论。我们回顾了其他软件包管理系统以及各种配置模板方法,并迅速集中到我们想要合并的几个关键元素上。

因为ORB比大多数通用包管理器更关注其范围,所以我们可以在设计决策中更加自以为是。在这一过程中,我们对设计的各个部分进行了内部和外部预览,使我们能够在将任何内容整合到代码中之前获得快速反馈。

在讨论ORB本身的设计之前,让我们先从我们构建的基础CircleCI配置模型的一些上下文开始。

关于CircleCI配置的现有决定

当我们开始CircleCI球体的设计过程时,我们知道我们将坚持CircleCI配置的现有设计原则:

1.代码中的配置:总是倾向于允许代码本身包含需要完成的配置,除非设置或其他输入绝对有必要存在于代码之外(例如:计划自动应用于所有分支的项目设置,或计划存在于代码库之外的秘密注入和安全性)。

2.确定性:给定相同的输入,每个构建都应该以相同的方式运行。这可以防止您无法控制的事情发生变化,同时减轻CircleCI对您希望如何运行构建的假设。

3.配置为数据,而不是程序:使用YAML是因为它提供了一种在语法权重和表达能力之间保持合理平衡的方法来编写数据结构。让配置成为数据而不是编程语言,可以使用简单可靠的工具来执行配置语法和模式验证、在构建过程中发生的各种静态分析和数据转换,以及使用一流元数据的自动化文档。例如,Jenkins插件的配置本身不是可执行代码。另一方面,ORB可以被解释为配置组合,而不是特定环境中的可执行软件。虽然这并不能解决所有的依赖性和安全性问题,但它在如何根据运行时环境中执行的内容配置构建之间建立了更清晰的界限。

4.构建行为的声明性:CircleCI配置的语义围绕平台内部构建执行的核心域模型。核心结构由工作流驱动,这些工作流调用并协调表示一组要运行的步骤以及运行这些步骤的执行环境的作业。我们的配置代码本质上是构建流程的元代码,因为我们提供了上层建筑,您可以在其中表达自己的运行时命令和流程编排。我们想让你专注于你的代码在运行时内要做什么,并尽可能地避开你的方式。使用声明性语法可以为您提供一组有表现力的原语,而无需了解内部系统的工作原理或学习一些新的编程语言。

CircleCI配置的现有设计成为我们着手建造ORB时的关键约束。除了这些限制,orb设计还有三个关键领域(没有特定顺序):

  • orb注册表的设计
  • orbs的开发生命周期
  • 我们的领域特定语言(DSL)的语义
  • 我将在下面介绍这些领域以及我们所做的决定。

设计Orb注册表

我们最初的设计建议从居住在你家里的“本地”球体开始。circleci文件夹,将在运行时拉入。球在里面。circleci被认为具有不可接受的风险,因为我们与GitHub的互动方式。“不要将git视为包管理者”是我们对情况进行内部审查时发出的明确警告。这就需要有我们自己的注册中心,这无疑增加了很大的范围(大约60-90天),并为未来创造了一个清晰的设计边界。

  • 1.所有ORB都存在于一个名称空间中:所有ORB都存在于一个名称空间中。没有“空”名称空间,也没有保留的特殊默认值,如for CircleCI或“官方”ORB。我们决定,我们不希望我们创作的球体被视为默认集,或者在我们的名称空间方案中具有特殊意义。我们可能会在未来引入一个认证的Orbs程序或类似程序,但这将在orb上提供一流的元数据,明确定义包含,而不是依赖于特殊名称空间的含义。
  • 2.语义版本控制和锁定:CircleCI希望允许orb作者动态地向orb添加功能和修复。同时,我们希望防止orb下的用户发生变化:修复用户使用的orb,以便用户的配置保持静态,除非用户另有规定。CircleCI选择对所有已发布的修订版实施严格的语义版本控制格式。导入时,我们允许orb用户锁定特定版本,或承担破损风险,并使用最新版本(volatile)。
  • 3.“Volatile”而非“latest”:我们选择使用“Volatile”而非“latest”,因为我们希望鼓励使用特定的版本来实现更大的决定论。我们希望使用volatile的人能够理解他们所做的事情有破损的风险。我们认为“最新的”听起来很新鲜,而“不稳定的”更好地表达了当你愿意接受上游依赖时发生的事情,这些依赖可能会在没有警告的情况下任意变异。另外值得注意的是,我们没有默认为“volatile”或任何版本——在调用ORB时,必须至少指定部分semver或“volatile”。
  • 4.认证与第三方ORB:认证意味着CircleCI将其视为我们平台的一部分。如果使用2.1或更高版本的配置,任何人都可以使用它们,而无需额外选择。目前,只有circleci名称空间得到认证,因为我们自己编写了这些ORB。所有其他被视为第三方。
  • 5.开放与私有球体:所有球体都是开放的,这意味着它们是世界可读的。任何人都可以使用它们并查看其来源。我们不想在代码和机密的运行时环境中引入黑匣子,因此,如果要在作业中运行ORB,应该能够看到它们的功能,这一点很重要。我们可能会增加一些方法,在未来拥有私人球体。

 

Orb开发决策

orbs系统的核心是开发人员如何编写orbs。这里的首要任务是平衡迭代的易用性和从小处开始,同时考虑持久性和不变性,允许ORB的用户将其合并到构建中。以下是orb创作体验的主要特征。

  • 1.修订是不可更改的:为了防止在使用orb的人的构建中出现神秘的更改,我们不允许在orb修订生效后对其进行更改。要发布较新版本的代码,需要发布新版本。
  • 2.开发与生产ORB:一旦我们决定对生产ORB实施严格的、不可变的版本控制,我们想要一种好方法,让您在开发ORB时不污染您的semver进程。因此,orb可以作为“dev:foo”或语义版本化的产品orb发布。Dev ORB可由团队中的任何人更改,并在其上次发布日期后90天过期。生产球体是不可变且持久的,因此您的构建配置不会受到您使用的球体中意外更改的影响。
  • 3.注册时间依赖项解析:如果一个orb(我的orb)导入其他orb,我们将在我的orb添加到注册表时解析并锁定这些依赖项。例如,假设您发布了my orb的1.2.0版,它包含以下orb调用:foo-orb:somenamespace/some-orb:volatile–在您注册my orb的1.2.0版时,最新版本的foo-orb将被压缩到my orb的1.2.0版中。如果发布了新版本的foo orb,则在发布新版本之前,它不会被并入我的orb。我们建议您选择导入的ORB的完全限定版本,以确保确定性行为。
  • 4.透明度:如果你能执行一个球体,你可以看到该球体的来源。这样你就永远不会在你的工作中执行一个黑匣子,那里有你的代码和秘密。ORB不像您的核心软件,更像是一个配置,否则您将复制和粘贴。球体是构建过程的一部分,因此如果可以执行它们,您应该能够看到它们的功能。

DSL设计决策

在orbs内部,我们基于YAML的领域特定语言(DSL)的语法和语义需要增强,以允许参数化和重用。以下是我们在这方面做出的一些关键决定。

  • 1.Orbs封装特定的配置元素,而不是提供通用的模板解决方案。环顾其他工具,我们看到了一些使用通用模板在项目间共享代码片段的配置实例。我们很早就决定将ORB的重点放在使用配置DSL的语义上,并允许调用特定的元素,以便在特定的范围内使用参数,并避免意外的冲突。这种方法还使配置更易于阅读和推理。
  • 2.Baked-in/first-class metadata。CircleCI允许将描述码作为orbs结构的一部分,因此生成文档或通读代码更容易,而无需额外的结构注释。
  • 3.ORB是配置的一个子集。yml。您可能会注意到配置中的配置格式。yml文件与orbs非常相似。早些时候,很明显,配置。实际上,yml是一种特殊的orb——您可以将其视为在CircleCI上运行构建的“根orb”。

接下来呢?

我们很高兴看到这么多团队在短短几周内发布和使用orbs。在2019年,我们希望为orbs添加一些新功能,并继续构建我们自己的orbs,并与我们的合作伙伴合作,使与他们的系统集成更加容易。下面是一些可以了解更多信息或参与帮助我们塑造构建配置未来的资源。

原文:https://circleci.com/blog/designing-a-package-manager-from-the-ground-u…

本文:https://jiagoushi.pro/node/1819

Tags
 
Article
知识星球
 
微信公众号
 
视频号