Wie erreicht man mit einer deklarativen Pipeline eine dynamische Parallelität?

18

Derzeit benötige ich eine Implementierung, die alle Dateien in einem Verzeichnis finden und für jede gefundene Datei eine parallele Aufgabe starten muss.

Ist dies mit deklarativen Pipelines möglich?

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
quelle
Wie kann ich vorgehen, wenn ich mehrere Schritte hintereinander und nicht parallel ausführen möchte?
Frank Escobar

Antworten:

21

Konnte es mit dem folgenden Code lösen:

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
quelle
Schauen
phedoreanu 10.04.18
@phedoreanu Ich verwende deklarative Pipeline ...
thclpr
@phedoreanu Ich habe Ihre Bearbeitung abgelehnt. Der Bearbeitungscode sollte gute Gründe haben. Ihr Kommentar reicht mir nicht aus, um eine Bearbeitung dieser Art für eine Antwort zuzulassen, die eine Selbstlösung war. Ich denke, Sie hätten kommentieren sollen, um die Angelegenheit mit dem Antwortautor zu besprechen, bevor Sie diese Bearbeitung durchführen.
Tensibai
@phedoreanu Ich denke du hast eine bessere abgeleitete Arbeit, dann schreibe bitte deine eigene Antwort und erkläre, warum es besser ist (in Fehlerbehandlung, Vorlagen, etc.).
Tensibai
Hallo, das habe ich auch nach einigen Fehlversuchen herausgefunden. Mein einziges Problem im Moment ist, dass, wenn ich aus bestimmten Gründen zwei Abschnitte {..} innerhalb eines Knotens platziere, das Workflow-Stage-Chart und Blu Ocean verwirrt werden. Zum Beispiel in der Workflow-Tabelle bekomme ich NaNy NaNd und in Blue Ocean bekomme ich nur die erste Stufe.
Giuseppe
5

Dies funktioniert auch, wenn Sie im Declarative PipelineRaum bleiben möchten

// 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
quelle
Wenn Sie jede parallele Aufgabe verschiedenen Jenkins-Knoten zuweisen möchten, schließen Sie die Aktionen einfach node {}wie tests[f] = { node { echo f.toString() } }
folgt
1

Es ist viel einfacher, skriptbasierte Pipelines zu verwenden, da Sie beliebiges Groovy verwenden können. Sie sollten jedoch weiterhin in der Lage sein, dies mit deklarativen Pipelines zu tun, die den findFilesSchritt verwenden.

Jayhendren
quelle
0

Beachten Sie, dass dynamische Erstellungsschritte in einigen Erstellungsschritten zu Problemen führen können, z. B. wenn Sie einen anderen Job aufrufen:

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
quelle