如何使用声明性管道正确实现动态并行操作?


22

当前,我将需要一个实现,该实现必须找到目录中的所有文件并为找到的每个文件启动并行任务。

是否可以使用声明性管道来实现这一目标?

pipeline {
    agent any
    stages {
        stage("test") {
            steps {
                dir ("file_path") {
                    // find all files with complete path
                    parallel (
                        // execute parallel tasks for each file found.
                        // this must be dynamic
                        }
                    }
                }
            }
        }
    }
}

如果我要依次而不是并行运行多个步骤怎么办?
Frank Escobar

可以,但是这样就不能动态生成并行任务,例如,取决于存储库中的某些文件。
劳尔·萨利纳斯-蒙塔古多

Answers:


23

设法用以下代码解决了它:

pipeline {
    agent { label "master"}
    stages {
        stage('1') {
            steps {
                script {
                    def tests = [:]
                    for (f in findFiles(glob: '**/html/*.html')) {
                        tests["${f}"] = {
                            node {
                                stage("${f}") {
                                    echo '${f}'
                                }
                            }
                        }
                    }
                    parallel tests
                }
            }
        }       
    }
}


@phedoreanu我正在使用声明性管道...
thclpr

@phedoreanu我拒绝了您的编辑,编辑代码应该有充分的理由,您的评论不足以允许我对这样的答案进行这种编辑,这是一种自我解决方案。我认为您应该先评论才能与答案作者讨论此事,然后再进行此编辑。
Tensibai '18

@phedoreanu我认为您有更好的派生作品,然后请编写您自己的答案并解释为什么它更好(在错误处理,模板等方面)。
Tensibai '18

嗨,经过几次失败的尝试,我发现还是一样的。现在我唯一的问题是,如果出于某种原因,如果在节点内放置两个阶段{..}部分,则工作流阶段图和Blu Ocean会混淆。例如,在工作流阶段图中,我得到的是NaNy NaNd,而在蓝海中,我得到的只是第一阶段。
朱塞佩

7

如果您想留在Declarative Pipeline空间内,这也可以

// declare our vars outside the pipeline
def tests = [:]
def files

pipeline {
    agent any
    stages {
        stage('1') {
            steps {
                script {
                    // we've declared the variable, now we give it the values
                    files = findFiles(glob: '**/html/*.html')
                    // Loop through them
                    files.each { f ->
                        // add each object from the 'files' loop to the 'tests' array
                        tests[f] = {
                            // we're already in the script{} block, so do our advanced stuff here
                            echo f.toString()
                        }
                    }
                    // Still within the 'Script' block, run the parallel array object
                    parallel tests
                }
            }
        }       
    }
}

1
如果要将每个并行任务分配给不同的Jenkins节点,则只需将动作包装在一个node {}块中,如下所示: tests[f] = { node { echo f.toString() } }
primetheus

1

使用脚本化管道来执行此操作要容易得多,因为您可以使用任意Groovy,但是您仍然应该能够使用该findFiles步骤对声明性管道进行此操作。


1

请注意,动态构建步骤可能会在某些构建步骤中引起一些问题,例如,当您调用其他作业时:

pipeline {
    stages {
        stage('Test') {
            steps {
                script {
                    def tests = [:]
                    for (f in findFiles(glob: '**/html/*.html')) {
                        // Create temp variable, otherwise the name will be the last value of the for loop
                        def name = f
                        tests["${name}"] = {
                            build job: "${name}"
                        }
                    }
                    parallel tests
                }
            }
        }       
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.