Continuous integration 基于云的CI服务器,可基于外部资源处理并发阻塞

Continuous integration 基于云的CI服务器,可基于外部资源处理并发阻塞,continuous-integration,Continuous Integration,我研究基于云的CI系统已经有一段时间了,似乎找不到任何能够满足我主要需求的系统 我正在为Salesforce的开发构建CI流程,但这个问题更一般地涉及依赖外部资源的构建。在我们的构建中,我们将代码部署到云托管的Salesforce实例中,然后在该实例中运行测试。在生成期间,外部资源被有效锁定,如果两个生成同时以相同的外部资源为目标,则生成失败。这意味着基于云的CI系统的正常并发模型将开始在并发性大于1的Salesforce实例(外部资源)上绊倒 更复杂的是,每个项目实际上有5种不同的外部资源(功

我研究基于云的CI系统已经有一段时间了,似乎找不到任何能够满足我主要需求的系统

我正在为Salesforce的开发构建CI流程,但这个问题更一般地涉及依赖外部资源的构建。在我们的构建中,我们将代码部署到云托管的Salesforce实例中,然后在该实例中运行测试。在生成期间,外部资源被有效锁定,如果两个生成同时以相同的外部资源为目标,则生成失败。这意味着基于云的CI系统的正常并发模型将开始在并发性大于1的Salesforce实例(外部资源)上绊倒

更复杂的是,每个项目实际上有5种不同的外部资源(功能、主控、打包、测试版和发行版),需要将依赖外部资源的任何构建的并发性控制为1。例如,我们所有的功能分支都是根据功能外部资源构建的。我们可以通过使用模式feature/*的分支名称来识别这些构建,并且需要确保一次只运行一个功能构建。但是,功能构建不会占用其他4个外部资源,因此理想情况下,任何需要这些资源的构建都应该能够并发运行

我目前在Jenkins中使用Throttle Concurrent Builds插件完成了这项工作,并为每个构建分配了一个Throttle组,以标识它所依赖的外部资源。这成功地防止了并发构建被外部资源绊倒

一些澄清:

  • 我不是问如何在回购级别将并发性降低到1。我知道每个云CI系统都能做到这一点。我应该能够将repo并发设置为N个外部资源(在我的例子中为5)

  • 理想情况下,我希望能够使用分支名称上的正则表达式模式作为阻止并发的“组”。因此,设置如下:如果分支名称与“feature/*”匹配,则将并发性限制为1。我希望避免在构建系统中手动配置新的特性分支,而是在模式上进行匹配


  • 我不得不说,几乎不可能找到一个限制性的谷歌搜索词来帮助我回答这个问题。希望有人曾经遇到过这个问题,并能给我一些启示:)

    我通过一个Drone.io设置来实现这一点

    本质上,我使用grunt插件访问外部托管的Redis db。它为您想要的任何参数提供信号量锁定

    确定该环境的锁是否可用。 如果是这样,Env的钥匙有一个合理的超时 运行测试 把锁打开


    如果锁被持有,获取它的过期时间,然后一直休眠到该时间。

    使用Jenkins管道插件,您可以将阶段并发性设置为1,并且一次只有一件事情通过该阶段。舞台被设计成能够表现这样的事物

    您也可以将构建管道放在repo中的jenkins文件中:(因此,构建的任何分支也都要遵守该锁)


    正如@Jesse Glick在下面的评论中指出的,也许一个更通用的解决方案(与管道不兼容)是使用-然后它将在任何类型的作业之间工作

    我不知道有任何基于云的CI工具能够以您想要的方式管理外部资源,除非您将逻辑作为构建脚本的一部分,您已经说过不希望这样做。如果你决定要这么做,你可以使用Drone或我想象中的任何其他云工具


    在这种情况下,我通常会推荐一种基于代理的系统,例如

    ,那么您是否将并发阻塞作为构建脚本本身的一部分?我真的希望避免这种情况,原因有几个:1。它为一个构建绑定了执行者,而这个构建实际上应该排队2。它扭曲了你的构建时间,我现在在Jenkins中使用旧的构建流插件和节流并发构建。这显然是一个更好的实现。仅供参考,我可能最终会接受这一点作为答案,但我想留出更多的时间,看看是否有非Jenkins选项能够实现相同类型的逻辑。我已经知道如何在Jenkins中做到这一点,但如果在Jenkins中做到这一点,这肯定是更好的方法。这实际上不是适当使用
    stage
    concurrency
    ,后者是为使用与构建顺序相关的特定语义进行节流而设计的。考虑多个特征分支(逻辑上可映射到子项目时,使用流水线:Multibranch)都与一个特征资源竞争。您真正想要的是,在编写本文时,管道将被阻塞。
    stage "build"
    node {
       sh './test-the-awesome'
    }
    
    stage name: "environment test", concurrency: 1
    node {
        sh 'tests that lock the environment'
    }