如何构建复杂的并行Jenkins流水线

75次阅读
没有评论

问题描述

希望将其定制的Jenkins集成方案转换为流水线。然而,他无法弄清楚如何做到以下操作。是否有人可以提供帮助,并提供一个可以实现以下需求的Jenkins脚本?

1---2---3-----------9---10
|           |    |---4-------|    |           |
|    |---5---6---|        |       |        |---7---|

其中:
– 1: 启动流水线
– 10: 结束流水线
– 5: 构建一些文件,供6和7使用,并作为最终的构件
– 2, 3, 4, 6, 7: 具有jUnit结果文件,应在测试结束时可用,即使有一个失败也应该可用

用户还提出了一种可能的简化方案,即在3, 4, 5之后合并。如下所示:

1---2---3-------6-------9---10
|       |   |   |    |---4---|
7---|    |       |    |---5---|

解决方案

请注意以下操作可能涉及版本差异,备份前做好准备。

最佳解决方案

根据用户提供的需求,使用嵌套的并行语句是一种解决方案。需要注意的是,当前的Jenkins Blue Ocean对这种结构的可视化显示存在问题,但可以通过其他插件如Groovy Postbuild来展示结果。以下是一种实现方法:

  1. 首先,在主要的触发任务的Jenkinsfile中,使用script块来启动嵌套的并行任务:
pipeline {
    agent any
    stages {
        stage('Build Nested Parallel') {
            steps {
                script {
                    def builds = [
                        "subJob1": performTriggerJob('subJob1'),
                        "subJob2": performTriggerJob('subJob2'),
                        "subJob3": {
                            script {
                                performTriggerJob('subJob3').call()
                                parallel (
                                    'nestedJob1': performTriggerJob('nestedJob1'),
                                    'nestedJob2': performTriggerJob('nestedJob2')
                                )
                            }
                        }
                    ]
                    parallel builds
                }
            }
        }
        // 其他阶段
    }
}
  1. 为了在并行任务之间共享结果,可以使用buildResults变量来存储每个任务的结果,然后在流水线的后续阶段中对这些结果进行处理:
stage("Post steps") {
    steps {
        script {
            for (finishedBuildObj in buildResults) {
                buildObj = finishedBuildObj
                projectName = buildObj.getFullProjectName()
                if (buildObj.getResult() != "SUCCESS") {
                    buildObj = buildObj.getPreviousSuccessfulBuild()
                }
                copyArtifacts(
                    projectName: projectName,
                    optional: true,
                    flatten: true,
                    target: 'allArtifacts',
                    fingerprintArtifacts: true,
                    selector: specific(buildObj.getNumber().toString())
                )
            }
        }
    }
}

以上解决方案使用了嵌套的并行语句来实现复杂的流水线结构。每个任务都被定义为一个performTriggerJob函数,并且结果被存储在buildResults列表中,以便在后续阶段中进行处理。请确保为并行任务分配足够的执行器以充分发挥并行运行的优势。

其他方案

另一种可能的方法是通过嵌套的parallel命令来实现并行运行,这要求脚本在scripted pipeline中编写。以下是一个示例脚本:

def performDeploymentStages(String node, String app) {
    stage("build") {
        echo "Building the app [${app}] on node [${node}]"
    }
    stage("deploy") {
        echo "Deploying the app ${app}] on node [${node}]"
    }
    stage("test") {
        echo "Testing the app [${app}] on node [${node}]"
    }
}

pipeline {
    agent {
        label 'master'
    }
    parameters {
        string(name: 'NODES', defaultValue: '1,2,3', description: 'Nodes to build, deploy and test')
        choice(name: 'ENV', choices: 'qa', description: 'Environment')
        string(name: 'APPS', defaultValue: 'app01,app02', description: 'App names')
    }
    stages {
        stage('parallel stage') {
            steps {
                script {
                    def nodes = [:]
                    for (node in params.NODES.tokenize(',')) {
                        def apps = [:]
                        for (app in params.APPS.tokenize(',')) {
                            performDeploymentStages(node, app)
                        }
                        parallel apps
                    }
                    parallel nodes
                }
            }
        }
    }
}

以上脚本中,我们定义了一个performDeploymentStages函数来表示构建、部署和测试阶段。在主pipeline的parallel stage中,我们使用script块来定义并行任务,使用嵌套的parallel命令来实现并行运行。

请注意,这两种方案都需要根据实际需求进行修改和调整。其中最佳解决方案使用了Groovy的Closure来处理并行任务的结果,而另一种方案则使用了函数来表示各个阶段,用户可以根据自己的喜好和需求来选择适合的方法。同时,根据Jenkins版本的不同,一些细节可能需要进行调整以适应最新的特性和插件。

正文完