¿Cómo lograr una acción paralela dinámica con una tubería declarativa?

20

Actualmente, voy a necesitar una implementación que debe encontrar todos los archivos dentro de un directorio e iniciar una tarea paralela para cada archivo encontrado.

¿Es posible lograr esto usando tuberías declarativas?

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
fuente
¿Cómo puedo hacer si quiero ejecutar varios pasos secuencialmente y no en paralelo?
Frank Escobar

Respuestas:

22

Logré resolverlo con el siguiente código:

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
fuente
Consulte también los ejemplos oficiales de Pipeline: jenkins.io/doc/pipeline/examples/#parallel-multiple-nodes
phedoreanu
@phedoreanu estoy usando una tubería declarativa ...
thclpr
@phedoreanu He rechazado su edición, el código de edición debería tener buenas razones, su comentario no es suficiente para permitirme una edición de este tipo en una respuesta que fue una solución propia. Creo que debería haber comentado para discutir el asunto con el autor de la respuesta antes de hacer esta edición.
Tensibai
@phedoreanu Creo que tiene un mejor trabajo derivado, luego escriba su propia respuesta y explique por qué es mejor (en el manejo de errores, plantillas, etc.).
Tensibai
Hola, descubrí lo mismo después de algunos intentos fallidos. Mi único problema en este momento es que si coloco dos secciones de etapa {..} dentro de un nodo por alguna razón, el diagrama de la etapa de flujo de trabajo y Blu Ocean se confunden. Por ejemplo, en el gráfico de etapas del flujo de trabajo obtengo NaNy NaNd y en Blue Ocean obtengo solo la primera etapa.
Giuseppe
6

Esto también funciona, si quieres quedarte dentro del Declarative Pipelineespacio

// 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
fuente
Si desea asignar cada tarea paralela a diferentes nodos de Jenkins, simplemente ajuste las acciones en un node {}bloque, de esta manera: tests[f] = { node { echo f.toString() } }
primetheus
1

Es mucho más fácil usar Pipelines con script para hacer esto, ya que puedes usar Groovy arbitrario, pero aún así deberías poder hacerlo con Pipelines declarativos usando el findFilespaso.

jayhendren
fuente
1

Tenga en cuenta que los pasos de compilación dinámica pueden causar algunos problemas en algunos pasos de compilación, por ejemplo, cuando llama a otro trabajo:

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
                }
            }
        }       
    }
}
Christian Gripp
fuente