Jak prawidłowo osiągnąć dynamiczne działanie równoległe za pomocą deklaratywnego potoku?


22

Obecnie potrzebuję implementacji, która musi znaleźć wszystkie pliki w katalogu i uruchomić równoległe zadanie dla każdego znalezionego pliku.

Czy można to osiągnąć za pomocą deklaratywnych potoków?

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

Jak mogę to zrobić, jeśli chcę wykonywać wiele kroków sekwencyjnie, a nie równolegle?
Frank Escobar

Jasne, ale w ten sposób nie można dynamicznie generować równoległych zadań, na przykład w zależności od niektórych plików w repozytorium.
Raúl Salinas-Monteagudo

Odpowiedzi:


23

Udało się go rozwiązać za pomocą następującego kodu:

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

Sprawdź także oficjalne przykłady rurociągów - jenkins.io/doc/pipeline/examples/#parallel-multiple-nodes
phedoreanu

@phedoreanu Używam deklaratywnego potoku ...
thclpr 10.04.18

@phedoreanu Odrzuciłem twoją edycję, kod edytowania powinien mieć dobre powody, twój komentarz nie wystarczy, żebym mógł pozwolić na tego rodzaju edycję odpowiedzi, która była rozwiązaniem własnym. Myślę, że powinieneś skomentować, aby omówić sprawę z autorem odpowiedzi przed wykonaniem tej edycji.
Tensibai

@phedoreanu Myślę, że masz lepszą pracę pochodną, ​​a następnie napisz własną odpowiedź i wyjaśnij, dlaczego jest ona lepsza (w obsłudze błędów, szablonach itp.).
Tensibai

Cześć, wymyśliłem to samo po kilku nieudanych próbach. Moim jedynym problemem jest teraz to, że jeśli wstawię dwie sekcje {..} do węzła z jakichś powodów, wykres etapów pracy i Blu Ocean ulegną dezorientacji. Na przykład na wykresie etapów pracy dostaję NaNy NaNd, aw Blue Ocean dostaję tylko pierwszy etap.
Giuseppe,

7

Działa to również, jeśli chcesz pozostać w Declarative Pipelineprzestrzeni

// 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
Jeśli chcesz przydzielić każde zadanie równoległe do różnych węzłów Jenkinsa, po prostu zawiń akcje w node {}bloku, w ten sposób: tests[f] = { node { echo f.toString() } }
primetheus 29.01.19

1

Jest to o wiele łatwiejsze do użycia skryptuowych potoków, ponieważ możesz użyć dowolnego Groovy, ale nadal powinieneś być w stanie to zrobić z deklaratywnymi potokami za pomocą tego findFileskroku.


1

Należy pamiętać, że kroki kompilacji dynamicznej mogą powodować pewne problemy na niektórych etapach kompilacji, np. Podczas wywoływania innego zadania:

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
                }
            }
        }       
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.