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


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
                        }
                    }
                }
            }
        }
    }
}

Как я могу сделать, если я хочу запустить несколько шагов последовательно, а не параллельно?
Фрэнк Эскобар

Конечно, но таким образом вы не можете генерировать параллельные задачи динамически, например, в зависимости от некоторых файлов в хранилище.
Рауль Салинас-Монтеагудо

Ответы:


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
                }
            }
        }       
    }
}

Также ознакомьтесь с официальными примерами конвейера - 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
                }
            }
        }       
    }
}

Если вы хотите назначить каждую параллельную задачу различным узлам 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
                }
            }
        }       
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.