Help us learn about your current experience with the documentation. Take the survey.

为验证阶段代码库做贡献

我们在验证阶段做什么?

验证阶段正在构建一个集成到 GitLab 产品中的综合持续集成平台。我们的目标是提供快速、可靠、安全的平台,验证用户做出的假设,并对照 CI/CD 配置中定义的标准进行检查。这些检查可能是单元测试、端到端测试、基准测试、性能验证、代码覆盖率强制执行等。

GitLab CI/CD 提供的反馈使用户能够就成功所需的技术和业务选择做出明智的决策。为什么持续集成是一个关键任务产品?

GitLab CI/CD 是我们向用户和客户传递反馈的平台。

他们贡献持续集成配置文件 .gitlab-ci.yml 来描述他们想要获得答案的问题。每次有人提交代码或触发管道时,我们都需要为 CI/CD 配置中提出的非常重要的问题找到答案。

未能回答这些问题,或者更糟糕的是,提供错误的答案,都可能导致用户做出错误决策。这样的错误决策可能造成非常严重的后果。

我们 CI/CD 平台的核心原则

平台产生的数据应该:

  1. 准确。
  2. 持久。
  3. 可访问。

平台本身应该:

  1. 可靠。
  2. 安全。
  3. 确定性。
  4. 可信。
  5. 快速。
  6. 简单。

自 GitLab CI/CD 诞生以来,我们一直遵循这些原则,它们为我们和我们的用户提供了很好的服务。这些原则的一些例子包括:

  • GitLab CI/CD 提供的反馈和平台产生的数据应该是准确的。如果一个作业失败而我们通知用户成功了,可能会产生严重的负面后果。
  • 反馈需要在用户需要时可用,数据不能在工程师需要时意外消失。
  • 如果平台不安全,我们泄露凭据或密钥,那么一切都无关紧要。
  • 当用户以 CI/CD 配置的形式提供一组前提条件时,每次运行管道的结果都应该是确定性的,否则平台可能不可信。
  • 如果它快速、易于使用且具有良好的用户体验,它将很好地服务于我们的用户。

在验证阶段构建东西

优化前先测量,做出数据驱动的决策

很难优化你无法测量的东西。你怎么知道是否成功了,或者成功的程度有多大?如果你正在处理性能或可靠性改进,请确保在优化之前先进行测量。

测量事物的最好方法是添加 Prometheus 指标。计数器、仪表盘和直方图是快速获得近似结果的绝佳方式。不幸的是,这不是测量尾部延迟的最佳方式。Prometheus 指标,特别是直方图,通常是近似值。

如果你必须测量尾部延迟,比如某件事可能有多慢,或者请求负载可能有多大,请考虑添加自定义应用程序日志并始终使用结构化日志。

使用性能分析和火焰图来理解代码执行路径的真实情况,这很有用!

追求简单的解决方案,避免巧妙的解决方案

有时使用巧妙的解决方案来更快地交付某些东西是很有诱惑力的。我们希望避免发布巧妙的代码,因为它通常更难长期理解和维护。相反,我们希望专注于无聊的解决方案,这些解决方案更容易演进代码库并保持贡献门槛低。我们希望找到尽可能简单的解决方案。

不要将无聊的解决方案与简单的解决方案混淆

无聊的解决方案有时会被误认为是简单的解决方案。通常情况恰恰相反。一个简单的解决方案可能并不简单——例如,包含一个复杂的新库来添加一个非常小的功能,否则可以快速实现——包含这个库比构建这个功能更容易,但它会给产品带来很多复杂性。

另一方面,当有一个简单、经过良好测试和良好维护的库可用时,也可能过度设计一个解决方案。在这种情况下,使用该库可能是有意义的。我们认识到我们一直在平衡简单和简单的解决方案,找到正确的平衡点很重要。

“简单"与"灵活"并不相互排斥

构建简单的并不意味着更高级和灵活的解决方案不可用。这里的一个好例子是编写 .gitlab-ci.yml 配置的复杂性不断增加。例如,你可以使用简单的方法定义环境名称:

deploy:
  environment: production
  script: cap deploy

environment 关键字也可以扩展到另一个级别的配置,提供更大的灵活性。

deploy:
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    url: https://prod.example.com
  script: cap deploy

这种方法可以保护新用户免受平台复杂性的影响,但如果需要,仍然允许他们深入了解。这种方法可以应用于许多其他技术实现。

使事情可观察

GitLab 是一个 DevOps 平台。我们推广 DevOps 是因为它能帮助公司更高效地实现更好的结果。DevOps 文化中的一个重要组成部分是对你正在构建的功能和代码负责。当你不知道你的功能在生产环境中的表现和行为时,做到这一点非常困难。

这就是为什么我们想让我们的功能和代码可观察。它应该以一种作者可以理解功能或代码在生产环境中表现好坏的方式编写。我们通常通过引入 Prometheus 指标和应用程序记录器的适当组合来实现这一点。

TODO 何时使用 Prometheus 指标,何时使用记录器。写几句话关于直方图和计数器。写几句话强调增量发布时指标的重要性。

保护客户数据

使我们的 CI/CD 平台产生的数据持久化很重要。我们认识到用户和客户在 CI/CD 中生成的数据是重要的,我们必须保护它。这些数据不仅重要,因为它们可能包含重要信息,我们还有合规性和审计责任。

因此,当我们编写永久删除数据库中数据的迁移,或者定义新的保留策略时,我们必须格外小心。

作为一般规则,当你编写应该从数据库、文件系统或对象存储中删除数据的代码时,你应该让你的更改得到额外的审查。当你定义新的保留策略时,你应该与产品经理和工程经理再次确认。

获取设计审查

当你为管道处理和转换 CI/CD 状态设计子系统时,尽早请求验证维护者(@gitlab-org/maintainers/cicd-verify)对设计的额外意见,并让其他人也这样做。让验证维护者审查你的设计有助于尽早识别你可能忽略的任何盲点,并可能带来更好的解决方案。

在开始任何开发工作之前进行设计审查,也有助于使合并请求审查更高效。如果设计已经过验证维护者审查,你在维护者审查期间不太可能遇到显著不同的意见或更改请求。结果,合并请求可以更快地合并。

获取更改审查

当你的合并请求准备好审查时,你必须分配审查者,然后是维护者。根据更改的复杂性,你可能希望涉及最了解你所更改代码库区域的人。我们在验证阶段确实有很多领域专家和维护者,当你不确定审查者轮盘分配的审查者或维护者是否对更改有足够的上下文时,请求他们审查你的代码是完全可接受的。

审查者轮盘提供了有用的建议,但由于分配正确的审查者很重要,不应每次都自动进行。分配一个对你正在更新的区域一无所知的人可能没有意义,因为他们的反馈可能仅限于代码风格和语法。根据更改的复杂性和影响,为你的更改分配正确的人进行审查可能非常重要。

如果你不知道该分配谁,请查阅 git blame 或在 #s_verify Slack 频道中询问(仅限 GitLab 团队成员)。

有两种更改/合并请求需要额外的审查关注和额外的审查者:

  1. 更改管道/阶段/构建状态相关代码的合并请求。
  2. 更改身份验证/安全功能相关代码的合并请求。

在这两种情况下,工程师都应请求维护者和领域专家进行审查。如果维护者是领域专家,建议涉及另一个人。

增量发布

当你的合并请求被维护者合并后,是时候向用户和更广泛的社区发布它了。我们通常使用功能标志来实现这一点。虽然不是每个合并请求都需要功能标志,但验证阶段的大多数合并请求应该有功能标志

如果你已经遵循了本页面的建议,你可能已经添加了一些指标和几个记录器,使你的新代码在生产环境中可观察。你现在可以使用这些指标来增量发布你的更改!

典型的场景涉及在几个内部项目中启用几个功能,同时观察你的指标或记录器。请注意,在 Elastic 或 Kibana 中摄取日志可能涉及小的延迟。确认该功能在内部项目中运行良好后,你可以开始为其他项目进行增量发布。

避免使用"按时间百分比"的增量发布。这些容易出错,特别是当你在代码库的多个地方检查功能标志,并且你没有在单个位置记住检查结果时。

不要让我们的宇宙崩溃

在第一次 GitLab Contributes 活动中,我们讨论了保持 CI/CD 管道、阶段和作业状态准确性的重要性。我们考虑了一个与我们早期客户构建的软件相关的假设场景:

如果部署到大型强子对撞机 (LHC)的软件因为 GitLab CI/CD 中的一个错误而崩溃,该错误显示管道通过了,但这个数据不准确,实际部署的软件是无效的?这样的问题可能导致 LHC 出故障,从而产生一个新粒子,然后导致宇宙崩溃。

这将是 GitLab CI/CD 状态处理中一个小错误的不太理想的结果。当你处理 CI/CD 状态时要格外小心,我们不想让我们的宇宙崩溃!

这是一个极端且不太可能发生的场景,但呈现不准确的数据可能会通过蝴蝶效应引发一系列问题。有更可能发生的场景可能产生灾难性后果。GitLab CI/CD 正在被构建医疗、航空和汽车软件的公司使用。持续集成是软件工程的关键任务部分。

完成标准

在验证阶段,我们遵循开发团队的完成标准。我们也希望在回答问题和为用户解决问题时保持高效和DRY

对于任何因解决方案受现有 .gitlab-ci.yml 语法支持而解决的问题,请在 ci-sample-projects 组中创建一个项目来演示该解决方案。

该项目必须具有:

  • 一个简单的标题。
  • 清晰的描述。
  • 一个 README.md,包含:
    • 指向已解决问题的链接。如果出现任何问题,你还应该引导用户在已解决的问题中进行协作。
    • 指向任何相关文档的链接。
    • 对示例正在做什么的详细解释。