Jenkins Pipeline Multiconfiguration Project

时间:2017-10-06 08:56:21

标签: jenkins jenkins-pipeline

原始情况:

我在詹金斯有一份正在运行蚂蚁脚本的工作。我很容易设法使用“多配置项目”在多个软件版本上测试这个ant脚本。

这种类型的项目非常酷,因为它允许我指定我需要的两个软件的所有版本(在我的例子中是Java和Matlab),它将运行我的ant脚本以及我的参数的所有组合。 / p>

然后将这些参数用作字符串,以便在我的蚂蚁使用的可执行文件的位置定义中连接。

  

示例:env.MATLAB_EXE = / usr / local / MATLAB / $ {MATLAB_VERSION} / bin / matlab

这很完美,但现在我正在将这些脚本迁移到它的pipline版本

管道迁移:

我设法使用Parametrized pipelines插件以管道方式实现相同的脚本。有了这个,我实现了我可以手动选择我将使用哪个版本的软件的点,如果我手动触发构建,我还找到了一种方法来执行此操作,定期在每次运行时选择我想要的参数。

这个解决方案似乎相当有效,但并不令人满意。

我的多配置项目有一些功能,但不是:

  1. 使用多个参数,我可以设置插值并执行每个组合
  2. 执行清楚地分开,并且在构建历史/构建详细信息中很容易识别哪些设置已被使用
  3. 只需在参数中添加新的“可能”值即可生成所需的执行
  4. 请求

    所以我想知道是否有更好的解决方案可以满足上述要点。

    长话短说:有没有办法在jenkins中使用管道技术实现多配置项目?

2 个答案:

答案 0 :(得分:6)

我已经看到了这个问题,并且最近也提出了类似的问题,所以看起来这样做很有意思......

在代码中可视化的矩阵/多配置作业实际上只是几个嵌套的循环,每个参数轴一个。

你可以构建一些相当简单的东西,一些硬编码的for循环遍历几个列表。或者你可以变得更复杂,并做一些递归循环,所以你不必硬编码特定的循环。

  

免责声明:我的操作比编写代码要多得多。我对groovy也很陌生,所以这可能会更干净利落,并且可能会有许多更加巧妙的事情可以完成,但无论如何这都可以完成工作。

通过一些工作,这个matrixBuilder可以包含在一个类中,这样你就可以传递一个任务闭包和轴列表并获取任务图。将其粘贴在共享库中,并在任何地方使用它。从多配置作业中添加一些其他功能应该非常容易,例如过滤器。

此尝试使用递归matrixBuilder函数来处理任意数量的参数轴并构建所有组合。然后它并行执行它们(显然取决于节点的可用性)。

/*
    All the config axes are defined here
    Add as many lists of axes in the axisList as you need.
    All combinations will be built
*/
def axisList = [
    ["ubuntu","rhel","windows","osx"],           //agents
    ["jdk6","jdk7","jdk8"],                      //tools
    ["banana","apple","orange","pineapple"]      //fruit
]



def tasks = [:]
def comboBuilder
def comboEntry = []


def task = {
    // builds and returns the task for each combination

    /* Map the entries back to a more readable format
       the index will correspond to the position of this axis in axisList[] */
    def myAgent = it[0]
    def myJdk   = it[1]
    def myFruit = it[2]

    return {
        // This is where the important work happens for each combination
        node(myAgent) {
            println "Executing combination ${it.join('-')}"
            def javaHome = tool myJdk
            println "Node=${env.NODE_NAME}"
            println "Java=${javaHome}"
        }

        //We won't declare a specific agent this part
        node {
            println "fruit=${myFruit}"
        }
    }
}


/*
    This is where the magic happens
    recursively work through the axisList and build all combinations
*/
comboBuilder = { def axes, int level ->
    for ( entry in axes[0] ) {
        comboEntry[level] = entry
        if (axes.size() > 1 ) {
            comboBuilder(axes[1..-1], level + 1)
        }
        else {
            tasks[comboEntry.join("-")] = task(comboEntry.collect())
        }
    }
}

stage ("Setup") {
    node {
        println "Initial Setup"
    }
}

stage ("Setup Combinations") {
    node {
        comboBuilder(axisList, 0)
    }
}

stage ("Multiconfiguration Parallel Tasks") {
    //Run the tasks in parallel
    parallel tasks
}

stage("The End") {
    node {
        echo "That's all folks"
    }
}

您可以在http://localhost:8080/job/multi-configPipeline/[build]/flowGraphTable/查看更详细的作业流程(可在构建页面的“管道步骤”链接下找到。

修改 您可以将舞台向下移动到“任务”创建中,然后更清楚地查看每个阶段的详细信息,但不能在多配置作业之类的整齐矩阵中查看。

...
return {
    // This is where the important work happens for each combination
    stage ("${it.join('-')}--build") {
        node(myAgent) {
            println "Executing combination ${it.join('-')}"
            def javaHome = tool myJdk
            println "Node=${env.NODE_NAME}"
            println "Java=${javaHome}"
        }
        //Node irrelevant for this part
        node {
            println "fruit=${myFruit}"
        }
    }
}
...

或者您可以使用自己的node包装每个stage以获取更多详细信息。

当我这样做时,我注意到我之前代码中的一个错误(现在修复了)。我正在将comboEntry引用传递给任务。我应该发送一份副本,因为虽然阶段的名称是正确的,但当它实际执行时,这些值当然是所遇到的最后一个条目。所以我把它改为tasks[comboEntry.join("-")] = task(comboEntry.collect())

我注意到您可以将原始stage ("Multiconfiguration Parallel Tasks") {}留给执行并行任务。从技术上讲,你现在已经嵌套了阶段。我不确定詹金斯应该如何应对,但它并没有抱怨。但是,“父”阶段时序不包括并行阶段时序。

我还注意到,当新的构建开始运行时,在作业的“舞台视图”上,所有以前的构建都会消失,大概是因为阶段名称并非全部匹配。但是在构建完成后,它们都会再次匹配,旧构建再次出现。

最后,Blue Ocean似乎并没有以同样的方式对其进行虚拟化。它不识别并行过程中的“阶段”,只识别封闭阶段(如果存在),如果不存在则识别“并行”阶段。然后只显示各个并行流程,而不是其中的各个阶段。

答案 1 :(得分:1)

第1点和第3点对我来说并不完全清楚,但我怀疑你只想使用“脚本化”而不是“声明性”管道语法,在这种情况下,你可以让你的工作做你喜欢的任何事情 - 矩阵允许的任何事情项目轴和轴滤波器等等,包括并行执行。声明性语法将语法简单性(以及对“往返”编辑工具和“短语”的友好性)进行交换以获得灵活性。

第2点是关于结果的可视化,而不是执行本身。虽然这是一个复杂的主题,但是像Blue Ocean这样的现有可视化尚未支持的通常的具体要求是能够看到通过轴组合区分的测试结果。这由JENKINS-27395和一些相关问题跟踪,设计正在进行中。