Meilisearch 目前在 GitHub 上维护着 50 多个开源项目。仅在过去六个月中,我们合并了 1000 多个 Pull Requests (PR),其中 160 个来自外部贡献者。

为了确保代码库保持稳定,并且代码质量始终处于顶尖水平,我们必须在合并新的 PR 时非常谨慎。随着贡献数量的增长,自动化此过程成为必要,以便为贡献者简化一切,并为 Meilisearch 的代码库提供安全保障。

在本篇文章中,我将介绍我们为何决定使用 Bors(一个用于 Github Pull Requests 的合并机器人)来为维护者和贡献者创造一个更好的环境。

我们的合并流程

在开源贡献过程中,任何更改都必须在他们自己的独立分支上完成。之后,当该分支上的工作完成时,我们合并前的主要要求之一是,新分支必须与主分支(在我们的大多数仓库中称为 main)保持同步。

如果 PR 未与 main 同步,可以说大部分工作已经完成,但 大部分工作 对我们来说还不够。即使所有自动测试都在 PR 本身通过,但如果 PR 分支和 main 未对齐,它们无法保证在合并后通过。

在使用 Bors 之前,这意味着我们经常不得不要求 PR 作者 重新整理他们的分支,例如,如果在此期间合并了另一个 PR。这使得贡献比我们想要的更加复杂,因为并非所有人都对 Git 的 rebase 命令感到满意。

为什么要重新整理?

在 Meilisearch,我们认为保持清晰的 Git 历史非常重要,主要原因有两个:

  1. 它允许每个人跟踪对项目的全部更改
  2. 在调试时,清晰的历史记录有助于识别引入问题的提交

重新整理的目的是将 PR 分支的提交移动到 main 上最后一个提交之后。因此,重新整理使您的 Git 历史记录保持清晰一致,并与您合并 PR 的顺序一致

重新整理不是将分支与 main 分支同步的唯一方法:您也可以将更改从 main 拉取到 PR 分支,例如。这种方法的问题是,拉取会在 PR 分支中添加一个合并提交,这不会使仓库历史记录保持清晰。

牢记维护清晰的提交树的重要性,重新整理是唯一一种方法,可以保证要合并的工作适合当前生产中的工作。如果测试在最新的分支上通过,那么它们在合并到 main 后也会通过,确保您的生产分支不会出现问题。

寻找完美的工具

牢记我们的重新整理要求,我开始寻找完美的工具。我希望它高效,因此我缩小了范围,只评估了符合以下条件的工具:

  • 免费且开源:该工具必须符合 Meilisearch 及其社区的价值观
  • 评价很高:该工具必须稳定可靠,因为在处理 PR 时出现的任何错误都会产生重大影响
  • 文档完善且易于设置:良好的文档可以节省时间,我们可以用这些时间来改进 Meilisearch

不幸的是,在这个范围内,我没有找到那么多解决方案。

我尝试的第一个工具是 Shipits,我通过 Shopify 工程博客上的这篇文章 发现了它。虽然 Shipits 看起来非常可靠且很有前途,但我认为它更适合复杂的集成流程,而不是只是试图保持其 Git 历史记录清晰的开源项目。

我测试的另一个工具是 Kodiak。设置非常简单,这在很大程度上要归功于他们优秀的文档。它是一个适合我们用例的优秀候选者,但自动合并过程基于我们必须管理的标签,这并不完全符合我们的工作流程。例如,我们合并 PR 时的最低要求是获得一位审阅者的批准;但是,有时我希望两个人审阅一个 PR,并且很容易忘记向 Kodiak 传达这一点。一旦收到第一个批准,Kodiak 会自动合并 PR,因为它已经满足了一位审阅者的要求。

我们还注意到,Kodiak 不会通过重新整理来更新源自 PR 的分支,而是通过将主分支拉取到 PR 分支来创建一个 Git 提交,正如我们所见,这会使仓库的历史记录变得混乱。最终,Kodiak 并不符合我们的需求,即使它的设置和配置提供了无缝且轻松的体验!

与我调查的所有其他工具相反,Bors 是按照原始 Bors 创建者在 这篇文章 中描述的独特而强大的原则构建的

软件工程的非火箭科学规则:自动维护一个始终通过所有测试的代码仓库。

这条“规则”完全符合我们的要求,使 Bors 成为我们的最终选择。

Bors 如何工作?

Bors 是一个合并机器人,这意味着它是一个自动化 PR 合并过程某些方面的应用程序。它的设置简单明了,并且与 Kodiak 一样,文档非常完善。事实上,配置可以是一个简单的 bors.toml 文件,其中包含我们要在合并之前执行的测试的名称。

所有 Bors 命令都必须通过 PR 中的注释给出。要合并 PR,我们只需要使用 bors merge

Bors 首先在运行测试之前应用重新整理,如果测试成功,它会将它们合并回 main。更准确地说,Bors 实际上并没有重新整理 PR 的分支:它将 PR 的提交合并到另一个分支(称为 staging)中,该分支已经与 main 同步。如果测试在 staging 上没有通过,Bors 会返回失败,并且不会合并 PR。

最棒的是:Bors 还能够同时管理多个 PR 的合并,这意味着我们无需逐个合并它们。每个 PR 都被添加到一个队列中,并将在定期间隔内使用 main 上的最新版本进行检查。

如果 Bors 在 PR 和主分支之间发现冲突,则它无法决定要应用哪些最终更改。在这种情况下,贡献者必须手动重新整理分支,如果这种情况发生在你身上,我已经写了这篇关于如何从分叉仓库中重新整理的简短教程

结论:我们解决了哪些问题?

我们在 Meilisearch 已经使用 Bors 几个月了,并且非常满意。我们知道,在提供稳定代码库的同时保持 Git 历史记录清晰可能非常复杂,但到目前为止,Bors 帮助我们极大地优化了工作流程。随着 Bors 集成到我们的工作流程中,

  • 无需再要求 PR 作者重新整理,并等待他们重新整理
  • 无需再逐个测试和合并 PR
  • 不会让我们的贡献者感到沮丧:他们都做出了惊人的贡献,但有些人不太熟悉 Git 的重新整理功能,实际上,这并不总是易于使用,尤其是在从分叉仓库中工作时!

Bors 使维护者和贡献者都更加快乐;因此,我们建议使用与我们相同的用例的项目使用它。