如何让管道作业等待所有触发的并行作业?

How to make Pipeline job to wait for all triggered parallel jobs?

我已经 Groovy 脚本作为 Jenkins 管道作业的一部分,如下所示:

node {
    stage('Testing') {
        build job: 'Test', parameters: [string(name: 'Name', value: 'Foo1')], quietPeriod: 2, wait: false
        build job: 'Test', parameters: [string(name: 'Name', value: 'Bar1')], quietPeriod: 2, wait: false
        build job: 'Test', parameters: [string(name: 'Name', value: 'Baz1')], quietPeriod: 2, wait: false
        build job: 'Test', parameters: [string(name: 'Name', value: 'Foo2')], quietPeriod: 2, wait: false
        build job: 'Test', parameters: [string(name: 'Name', value: 'Bar2')], quietPeriod: 2, wait: false
        build job: 'Test', parameters: [string(name: 'Name', value: 'Baz2')], quietPeriod: 2, wait: false
    }
}

它并行执行多个其他自由式作业,因为 wait 标志被设置为 false。但是,我希望调用者的工作在所有工作完成后完成。目前,管道作业会触发所有作业并在几秒钟后自行完成,这不是我想要的,因为我无法跟踪总时间,而且我无法一次性取消所有触发的作业。

当所有并行作业完成时,如何更正上述脚本以使管道作业完成?

我曾尝试将构建作业包装在 waitUntil {} 块中,但没有成功。

您应该使用管道 parallel 表达式,它将等待所有派生的作业/子任务完成:

stage('testing') {
    def branches = [:]

    for(i = 0; i < params.size(); i += 1) {
        def param = params[i]

        branches["Test${i}"] = {
            build job: 'Test', parameters: [string(name: 'Name', value: param)], quietPeriod: 2
        }
    }
    parallel branches
}

您可以在 jenkins.io

的管道文档中找到更多示例

但是 不处理多个作业。

Map jobResults = [:]

Boolean failedJobs = false
def buildJobWithParams(def jobs_list, Map results) {
  def branches = [:]    
  for(job in jobs_list)
  {
    print job
    branches["Test-${job}"] = {
       def jobBuild = build job: job, propagate: false
       def jobResult = jobBuild.getResult()
       echo "Build of '${job}' returned result: ${jobResult}"
       results[job] = jobResult
    }
  }    
  return branches
}

stage('Run integration tests') {
      steps {
            def job_branch = buildJobWithParams(item_list, jobResults)
            print job_branch
            parallel job_branch
          }
}

item_list有超过1个作业,但它只会多次执行最后一个作业。

只是 运行 遇到同样的问题,并找到可行的解决方案。只需使用 foreach.

stage('testing') {
    def jobs = [:]

    [1,2,3,4,5].each{
        i -> jobs["Test${i}"] = {
            build job: 'Test', 
            parameters: [string(name: 'theparam', value: "${i}")],
            quietPeriod: 2
        }
    }
    parallel jobs
}

这对我有用。触发 3 个工作。等他们说完。 注意多出的“->”指定groovy闭包。 我在每个循环上有一个 ->,在平行线上有一个。 意思是在运行并联段

时才计算该值
def jobsString = "job1,job2,job3"
ArrayList jobsList = jobsString.split('\,')

def parallelJobs2Run = [:]
jobsList.each { job ->
    echo "Going to parallel for job ${job}"
    parallelJobs2Run["${job}"] = { ->
        echo "Calling job ${job}"
        jobResults=build job: "${pathJenkinsFolder}${job}",
        parameters: [
            string(name: 'param1', value: "${value1}"),
            string(name: 'param2', value: "${value2}")
        ],
        propagate: true,
        wait: true

        // List of values: 
        buildNumber = ${jobResults.number}
        echo "${job} Build number |${buildNumber}| result: |${jobResults.result}|"
        echo "See details on: |${jobResults.absoluteUrl}|"
    }
};
parallel parallelJobs2Run

另一种基本上做同样事情的方法是将您的作业包装在一个单独的阶段,然后将所有子阶段包装在 parallel{} 中,如下所示:

stage('Trigger all dependent jobs') {
    parallel {
        stage('Trigger task 1') {
            steps {
                build job: "task-1"
            }
        }
        stage('Trigger task 2') {
            steps {
                build job: "task-2"
            }
        }
        stage('Trigger task 3') {
            steps {
                build job: "task-3"
            }
        }
    }   
}

这种方法允许你在每个并行阶段做任何你想做的事——上面的任务很可能完全不同(彼此)Jenkins 工作。

此外,上述方法(据我所知)代表了声明式管道语法。