Как правильно добиться динамического параллельного действия с декларативным конвейером?

21

В настоящее время мне понадобится реализация, которая должна найти все файлы в каталоге и запустить параллельное задание для каждого найденного файла.

Возможно ли добиться этого с помощью декларативных конвейеров?

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
                        }
                    }
                }
            }
        }
    }
}
thclpr
источник
Как я могу сделать, если я хочу запустить несколько шагов последовательно, а не параллельно?
Фрэнк Эскобар
Конечно, но таким образом вы не можете генерировать параллельные задачи динамически, например, в зависимости от некоторых файлов в хранилище.
Рауль Салинас-Монтеагудо

Ответы:

22

Удалось решить это с помощью следующего кода:

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
                }
            }
        }       
    }
}
thclpr
источник
Также ознакомьтесь с официальными примерами конвейера - jenkins.io/doc/pipeline/examples/#parallel-multiple-nodes
phedoreanu
@phedoreanu Я использую декларативный конвейер ...
Thclpr
@phedoreanu Я отклонил ваше редактирование, у кода для редактирования должны быть веские причины, вашего комментария недостаточно для того, чтобы я мог отредактировать такого рода ответ, который был самостоятельным решением. Я думаю, что вы должны прокомментировать, чтобы обсудить этот вопрос с автором ответа, прежде чем делать это редактирование.
Тенсибай
@phedoreanu Я думаю, что у вас есть лучшая производная работа, тогда, пожалуйста, напишите свой собственный ответ и объясните, почему он лучше (в обработке ошибок, шаблонах и т. д.).
Тенсибай
Привет, я понял то же самое после нескольких неудачных попыток. Моя единственная проблема сейчас заключается в том, что если по каким-то причинам я помещаю два этапа {..} внутри узла, диаграмма этапа рабочего процесса и Blu Ocean путаются. Например, в диаграмме этапов рабочего процесса я получаю NaNy NaNd, а в Blue Ocean - только первый этап.
Джузеппе
6

Это также работает, если вы хотите остаться в 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
                }
            }
        }       
    }
}
primetheus
источник
Если вы хотите назначить каждую параллельную задачу различным узлам Jenkins, просто оберните действия в node {}блок, например так: tests[f] = { node { echo f.toString() } }
primetheus
1

Для этого гораздо проще использовать скриптовые конвейеры, так как вы можете использовать произвольный Groovy, но вы все равно должны делать это с декларативными конвейерами, используя findFilesшаг.

jayhendren
источник
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
                }
            }
        }       
    }
}
Кристиан Грипп
источник