处理多个分支的持续集成

86
我一直在处理公司中CI的扩展问题,并尝试确定在处理CI和多个分支时应采取哪种方法。Stackoverflow上有一个类似的问题Multiple feature branches and continuous integration。我开了一个新问题,因为我希望能够得到更多的讨论并在问题中提供一些分析。
到目前为止,我发现有两种主要方法可以采取(或者可能还有其他方法?)。

看起来如果我想为开发人员提供他们自己的定制分支的CI,我需要为Jenkins编写特殊的工具(API或shell脚本或其他什么?)并处理扩展。或者我可以告诉他们更经常地合并到DEV,并在定制分支上不使用CI。你会选择哪一个,还是有其他选项?

4个回答

71
当您谈论扩展CI时,您实际上是在谈论扩展使用CI服务器来处理所有功能分支以及主线。最初,这似乎是一个很好的方法,因为分支中的开发人员可以获得CI作业包括的自动化测试的所有优势。然而,您会遇到管理CI服务器作业的问题(就像您已经发现的那样),更重要的是,您并没有真正进行CI。是的,您正在使用CI服务器,但您并没有持续集成所有开发人员的代码。
执行真正的CI意味着所有开发人员都定期提交到主干。说起来容易,但难点在于在不破坏应用程序的情况下完成它。我强烈建议您查看持续交付,特别是第13章中的管理组件和依赖项部分中的保持应用程序可发布。主要观点如下:
  • 隐藏未完成的新功能(也称为特性切换)。
  • 将所有更改逐步作为一系列小更改进行,每个更改都可以发布。
  • 使用抽象分支对代码库进行大规模更改。
  • 使用组件来解耦应用程序的不同变化速度的部分。
它们非常自我解释,除了抽象分支。这只是一个花哨的术语:
  1. 创建一个抽象层,覆盖需要更改的系统部分。
  2. 重构其余系统以使用抽象层。
  3. 创建一个新的实现,直到完成之前不是生产代码路径的一部分。
  4. 更新您的抽象层以委派给您的新实现。
  5. 删除旧实现。
  6. 如果不再适用,请删除抽象层。

以下段落摘自《高级版本控制》第14章“分支、流和持续集成”中的“分支、流和持续集成”部分,总结了影响。

增量方法当然需要更多的纪律和关心——确实需要更多的创造力——比创建分支并深入重新架构和开发新功能。但它大大降低了您的更改破坏应用程序的风险,并将为您和您的团队节省大量时间,合并、修复损坏和使应用程序进入可部署状态。

放弃特性分支需要进行相当大的思维转变,你总会遇到阻力。根据我的经验,这种阻力基于开发人员不感到安全地提交代码到主线上,这是一个合理的担忧。这反过来通常源于对上述技术的知识、信心或经验缺乏,可能也与您的自动化测试缺乏信心有关。前者可以通过培训和开发支持来解决。后者是一个更难处理的问题,然而分支不提供任何额外的真实安全性,它只是将问题推迟到开发人员对其代码感到足够自信时。


4
汤姆,这种方法只有在以下两种情况下才能发挥良好的效果:1)发布和更新都相对容易;2)大部分的更改都是良好隔离的。这适用于Web开发,但如果你正在进行盒装产品的发布,那么稳定版本必须以任何代价保持稳定,因为在大型企业环境中修补程序非常昂贵,甚至不可能实现。 - Jevgeni Kabanov
13
真正的CI不仅仅是关于集成,它也涉及反馈。 - Anton Arhipov
3
我选择这个答案(至少发放了赏金),但我认为这不是我的问题的解决方案。我在http://www.zeroturnaround.com/blog/continuous-integration-and-feature-branches/写了一个后续。 - toomasr
1
@Jevgeni Kabanov和@toomasr,你们两个似乎都认为真正的CI意味着放弃质量,并且只适用于Web开发,因为很容易推出修复程序。我猜你们担心的是在发布前提交了有问题的代码。是的,这可能会导致一个糟糕的版本,需要花费大量成本来修复。然而,在发布之前的功能分支上提交有问题的代码同样糟糕。如果你认为有区别,请分享你的理由。解决这个问题的一种方法(如果提交是到主干或功能分支)是使用持续交付方法。 - Tom Howard
1
顺便说一句,过去4年里,我的主要开发经验都在金融机构。稳定发布的必要性以及出错的代价(更不用说推出热修补所需的变更控制流程)几乎没有比这更大的了。对我来说,一个封装好的产品将是一种轻松的改变。 - Tom Howard
显示剩余5条评论

4
我会为每个分支设置单独的作业。如果您已经正确设置了Hudson/Jenkins,那么管理和设置这些作业并不困难。快速创建多个作业的方法是从具有类似要求的现有作业中复制并根据需要进行修改。我不确定您是否希望允许每个开发人员为其自己的分支设置自己的作业,但对于一个人(即构建管理员)来说,这并不费力。一旦定制分支合并到稳定分支,相应的作业可以在不再需要时删除。
如果您担心CI服务器的负载,可以设置CI的单独实例甚至单独的从机,以帮助在多个服务器上平衡负载。确保运行Hudson/Jenkins的服务器足够强大。我使用过Apache Tomcat,只需要确保它有足够的内存和处理能力来处理构建队列。
重要的是要明确使用CI所要实现的目标,然后找出一种实现方式,而不需要太多手动操作或重复工作。使用其他外部工具或脚本来简化整个构建管理流程也是可行的。

我认为缺乏工具意味着在这个领域有一些插件/产品的空间。不想自己编写。 - toomasr
1
有一个 Jenkins 的实用程序,可以自动为每个分支创建构建配置:http://entagen.github.com/jenkins-build-per-branch/ - kolen

3
我会选择dev+stable分支。如果您仍然想要自定义分支并担心负载,为什么不将这些自定义分支移动到云端,并让开发人员自己管理,例如http://cloudbees.com/dev.cb 这是Kohsuke现在所在的公司。还有一个Eclipse工具,因此,如果您使用Eclipse,则可以将其紧密集成到开发环境中。

我会将管理多个分支的工具缺失交换为在云上遇到同样的问题吗?我的意思是现在我能够管理负载,但仍然无法管理分支? - toomasr
我是指忘记工具,将管理分配给开发人员 - “如果您想要自定义个人构建,请使用您的CB帐户”。而不影响主服务器的构建性能。虽然他们的API非常简单,因此创建管理工具可能只需要一两周的时间,然后您可以在那里做任何想做的事情。正如生活中通常所发生的,如果您想要特别的东西,最好自己动手做。同时,他们正在快速增长并倾听社区的声音,因此填写功能请求,也许很快就会出现。 - Anton Safonov
哦,明白了。告诉分支所有者挑选他感兴趣的工作,并按照他想要的方式为他的自定义分支设置它们。我喜欢这个想法。 - toomasr

1
实际上,使用特性分支进行构建隔离是真正有问题的。在我们公司中,有一组单独的Maven项目,它们都是一个更大的分发的一部分。这些项目由不同的团队维护,但对于每个分发,所有项目都需要发布。现在,特性分支可能会从一个项目重叠到另一个项目,这时构建隔离就变得非常痛苦。我们尝试过几种解决方案:
  • 为每个特性分支创建单独的快照存储库
  • 在专用从机上共享本地存储库
  • 使用repository-server-plugin与上游存储库
  • 在一个作业中使用一个私有存储库进行全部构建
事实上,最后一个解决方案是最有前途的。所有其他解决方案都存在某种方式的缺陷。与job-dsl插件一起使用,很容易设置新的特性分支。只需复制并粘贴Groovy脚本,调整分支,让种子作业创建新的作业。确保种子作业删除未受管理的作业。然后,您可以轻松扩展到不同的Maven项目中的特性分支。
但正如Tom所说的那样,最好克服使用特性分支的必要性,并教导开发人员进行清洁集成,但这是一个较长的过程,并且许多遗留系统部分将不再受到影响。
以上仅代表个人意见。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接