Master Branch Must Be Read-Only

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

持续集成很简单。下载Jenkins,安装,创建一个任务,点击按钮,然后收到一封漂亮的邮件,告诉你构建出现了问题(我假设你的构建是自动化的)。然后,修复测试失败(我假设你有测试),再收到一封更好看的邮件,告诉你构建已经成功。

然后,发推文宣称你的团队正在使用持续集成。

然后,几周后,开始将Jenkins的警报过滤到一个单独的文件夹中,这样它们就不再打扰你了。反正,你的团队没时间也没兴趣每次有人破坏了单元测试就去修复它们。

毕竟,我们都知道对于一个有截止日期任务的团队来说,单元测试并不适用,对吗?

错。持续集成可以而且必须运行。

如今,软件开发是团队合作完成的。我们在特性分支上进行开发,并在开发过程中隔离更改。然后,我们将分支合并到master主分支上。每次合并后,我们会对整个产品进行测试,执行所有可用的单元测试和集成测试。这被称为持续集成(也称为“CI”)。

有时候,一些测试会失败。当这种情况发生时,我们称之为“构建失败”。这样的失败是质量控制的一个积极副作用,因为它在错误进入master后立即引起了警示。

众所周知,当修复这个错误成为作者和整个团队的首要任务时,这是一个良好的实践。在持续集成服务器引发警示后,应该立即修复错误。

Jez Humble等人的《持续交付》在第7章的169至186页中完美地解释了这种方法。

市场上有一些很好的工具可以自动化DevOps的流程。其中一些是开源的,你可以下载并安装在自己的服务器上。例如:JenkinsGoCruiseControl。其中一些作为云服务提供,例如:TravisShippable、Wercker等等。

CI很棒,但团队越大(以及代码库越大),构建的破坏就越频繁。而且修复所需的时间也越长。我见过很多例子,一个辛勤工作的团队在几周或试图跟上后,开始忽视Jenkins提出的红旗。

团队根本无法及时修复所有错误。主要是因为业务有其他优先事项。产品所有者不理解“干净构建”的重要性,技术负责人也无法为修复单元测试腾出时间。此外,导致问题的代码已经在“主分支”中,并且在大多数情况下已经部署到生产环境并交付给最终用户。如果业务价值已经交付,修复一些测试的紧迫性是什么呢?

最终,大多数开发团队不会认真对待持续集成的警报。对于他们来说,Jenkins或Travis只是一些花哨的工具,在整个开发和交付流程中没有任何作用。不管持续集成服务器说什么,我们仍然向最终用户交付新功能。我们以后再修复构建问题,这是合乎逻辑的。

四年前,也就是2010年,我在[phpArchitect](https://www.phparch.com/magazine/2010-2/august/)上发表了一篇名为“Prevent Conflicts in Distributed Agile PHP Projects”的文章。在这篇文章中,我提出了一个解决方案(完整文章在PDF中),用于Subversion和PHP。

从那时起,我在多个开源项目和一些商业项目中试验性地使用了这种方法,其中涉及到了PHP、Java、Ruby和JavaScript,以及Git和Subversion。在所有情况下,我的经验都非常积极,这也是rultor.com诞生的原因(稍后再谈)。

所以,这个解决方案很简单——禁止任何人将任何东西合并到master分支,并创建一个任何人都可以调用的脚本。这个脚本将进行合并、测试和提交。脚本不会有任何例外。如果任何分支在一个单元测试中出现错误,整个分支都会被拒绝。

换句话说,我们应该在代码进入master之前就提醒大家。我们应该把测试失败的责任推到作者身上。

比如说,我正在自己的分支上开发一个功能。我完成了开发,但不小心打破了几个测试。这种情况经常发生,我们都会犯错误。我不能将我的更改合并到master分支上。Git会拒绝我的push,因为我没有相应的权限。我只能调用一个神奇的脚本,让它来合并我的分支。脚本会尝试合并,但在推送到master之前,它会运行所有的测试。如果其中任何一个测试失败,我的分支就会被拒绝。我的更改不会被合并。现在,修复它们并再次调用脚本就是我的责任了。

开始时,这种方法会减缓开发速度,因为每个人都必须开始编写更加规范的代码。然而,到最后,这种方法会带来巨大的回报。

一些持续集成服务器提供预先构建功能,这意味着在分支合并到“master”之前对其进行测试。例如,Travis就有这个功能,非常有帮助。当您向一个分支提交新的更改时,Travis会立即尝试构建它,并在GitHub的拉取请求中报告问题。

请注意,预先构建不会合并代码。它只是检查您的个人分支是否干净。合并后,它可能会轻易破坏“master”。当然,这种机制并不能保证没有协作者可以直接向“master”提交代码,从而意外破坏它。预先构建只是一种预防措施,不能完全解决问题。

为了按照上述所述开始工作,您只需要撤销对“master”分支(或Subversion中的“/trunk”)的写权限。

不幸的是,在GitHub中不可能这样做。唯一的解决方案是仅通过分支和拉取请求来进行工作。只需从“协作者”列表中删除所有人,他们将不得不通过拉取请求提交更改。

然后,开始使用Rultor.com,它将帮助您测试、合并和推送每个拉取请求。基本上,Rultor就是我们上面提到的脚本。它作为一个免费的云服务提供。

附注:此文章的简短版本也发布在devops.com上。

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-17 at 16:14

sixnines availability badge   GitHub stars