Pertanyaan Jenkins pipeline - Cara mengulang melalui daftar


Saya diminta untuk membaca nilai dari file di pipeline saya. saya menggunakan membagi() yang menempatkan mereka ke dalam Array. Saya harus memasukkannya ke dalam Arraylist jadi saya menggunakan Arrays.asList (). Masalah yang saya hadapi adalah saya tidak dapat menggunakan ukuran() atau panjangnya() metode jadi saya tidak bisa membuat loop seperti

for (ii = 0; ii < var.length; ii++)

atau

for (ii = 0; ii < var.size; ii++)

karena saya mendapatkan kesalahan: kolom tidak diklasifikasikan java.util.Arrays $ ArrayList length

Jadi saya mencoba menggunakan untuk setiap loop, tetapi ketika saya mengambil beberapa tindakan (seperti perintah ls misalnya) di blok saya akhirnya hanya iterasi 1 kali. Tetapi jika saya hanya menjalankan perintah 'echo' iterates untuk setiap elemen seperti yang seharusnya. Ada saran tentang bagaimana memodifikasi kode saya untuk mendapatkannya untuk iterate untuk setiap elemen dalam daftar saat menggunakan perintah apa pun?

Bekerja dengan benar ....

node{
    wrap([$class: 'ConfigFileBuildWrapper', managedFiles: [[fileId: 'dest_hosts.txt', targetLocation: '', variable: 'DEST_HOST']]]) {
        HOST = Arrays.asList(readFile(env.DEST_HOST).split("\\r?\\n"))
        deploy(HOST)
    }
}

@NonCPS
def deploy(host){
    for (String target : host){
        try {
            echo target
        }
        finally {
           echo target
        }
    }
}

OUTPUT (iterates untuk setiap elemen):

[Pipeline] node
Running on <obfuscated>
[Pipeline] {
[Pipeline] wrap
provisoning config files...
copy managed file [<obfuscated>] to file:/var/lib/jenkins/<obfuscated>
[Pipeline] {
[Pipeline] readFile
[Pipeline] echo
www.testhost.com
[Pipeline] echo
www.testhost.com
[Pipeline] echo
www.testhost2.com
[Pipeline] echo
www.testhost2.com
[Pipeline] }
Deleting 1 temporary files
[Pipeline] // wrap
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

Tetapi jika saya mengambil beberapa tindakan seperti 'ls-l' hanya iterasi 1 kali

node{
    wrap([$class: 'ConfigFileBuildWrapper', managedFiles: [[fileId: 'dest_hosts.txt', targetLocation: '', variable: 'DEST_HOST']]]) {
        HOST = Arrays.asList(readFile(env.DEST_HOST).split("\\r?\\n"))
        deploy(HOST)
    }
}

@NonCPS
def deploy(host){
    for (String target : host){
        try {
            echo target
        }
        finally {
           sh 'ls -l'
        }
    }
}

OUTPUT (hanya 1 kali):

[Pipeline] node
Running on <obfuscated>
[Pipeline] {
[Pipeline] wrap
provisoning config files...
copy managed file [<obfuscated>] to file:/var/lib/jenkins/<obfuscated>
[Pipeline] {
[Pipeline] readFile
[Pipeline] echo
www.testhost.com
[Pipeline] sh
[sandbox%2Fpipeline-test-new1] Running shell script
+ ls -l
total 8
-rw-r--r-- 1 jenkins jenkins 10 Jun 17 16:07 someFile
[Pipeline] }
Deleting 1 temporary files
[Pipeline] // wrap
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

5
2017-07-07 23:59


asal


Jawaban:


ArrayList (dan umumnya Lists) tidak memiliki bidang panjang atau ukuran, mereka memiliki size() metode. Jadi gunakan itu di untuk:

for (ii = 0; ii < var.size(); ii++)

5
2017-07-08 05:09



Sesuai tutorial ini: https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md#serializing-local-variables

... metode yang ditandai dengan anotasi @NonCPS... akan diperlakukan sebagai "asli" oleh mesin Pipeline, dan variabel lokalnya tidak pernah disimpan. Namun itu mungkin tidak membuat panggilan ke langkah-langkah Pipeline

Dalam kasus Anda, itu sh panggilan adalah operasi langkah pipeline, yang tampaknya tidak dapat Anda lakukan dari dalam a @NonCPS metode anotasi.

Mengenai mengubah array menjadi List, maka karena kita berada di tanah Groovy, kamu bisa menggunakan .toList() metode pada larik.


2
2017-08-25 07:34



Saya tidak dapat memberitahu Anda SEBENARNYA mengapa, karena saya belum menemukan cara untuk menemukan informasi yang berguna tentang Jenkins tanpa menghabiskan berjam-jam googling, tapi saya dapat memberitahu Anda ini:

Untuk sesaat saya pikir Anda dapat membuatnya berjalan baik dengan menambahkan 'echo line' SETELAH sh 'echo $ line', tapi itu ternyata disebabkan oleh Jenkins menjalankan versi SEBELUMNYA dari script ...

Saya mencoba segala macam hal dan tidak ada yang berhasil, kemudian saya menemukan ini:

Mengapa setiap loop dalam Jenkinsfile berhenti pada iterasi pertama

Ini adalah bug yang dikenal di Jenkins pipeline!

(bug yang dikenal adalah JENKINS-26481, yang mengatakan "Setidaknya beberapa penutupan dijalankan hanya sekali di dalam skrip Groovy CPS DSL yang dikelola oleh plugin alur kerja")


1
2017-07-17 20:04