wake-up-neo.com

Abrufen einer Liste der Dateinamen in einem bestimmten Ordner in Jenkinsfile (Groovy)

Ich kann in einer Jenkins-Pipeline mit Skript keine einfache Liste von Dateinamen in einem bestimmten Verzeichnis erstellen. Ich habe viele Beispiele für Groovy-Skripte ausprobiert, die in SO und anderen Foren veröffentlicht wurden, aber entweder ist die Funktion blockiert oder die Methode wurde nicht gefunden oder was auch immer.

Dies scheint am einfachsten zu sein

def DOCKER_FILES_DIR = './dockerfiles'
// ...
def dir = new File(DOCKER_FILES_DIR);
def dockerfiles = [];
dir.traverse(type: FILES, maxDepth: 0) {
    dockerfiles.add(it)
}

Aber dies löst den relativen Pfad falsch auf, so dass ich diesen Fehler erhalte:

Java.io.FileNotFoundException: /./dockerfiles

Ich habe auch versucht, es in dir zu wickeln mit:

def DOCKER_FILES_DIR = './dockerfiles'
// ...
def dockerfiles = [];
dir("${env.WORKSPACE}"){
    def dir = new File(DOCKER_FILES_DIR);
    dir.traverse(type: FILES, maxDepth: 0) {
        dockerfiles.add(it)
    }
}

Habe aber den gleichen Fehler:

Java.io.FileNotFoundException: /./dockerfiles

Dies gibt keinen Fehler aus, sondern fügt der Liste nur eine Datei hinzu:

def DOCKER_FILES_DIR = './dockerfiles'
// ...
def dockerfiles = [];
def dir = new File("${env.WORKSPACE}/${DOCKER_FILES_DIR}");
dir.traverse(type: FILES, maxDepth: 0) {
    dockerfiles.add(it.getName())
}

Dem Inhalt von dockerfiles fehlen dann alle Dateien bis auf die erste:

['py365']

Hier ist eine minimale Pipeline, um sie in Jenkins zu reproduzieren:

#!groovy
import static groovy.io.FileType.FILES

node('master') {
    FILES_DIR = './foo'
    cleanWs()

    sh """
        mkdir foo
        touch foo/bar1
        touch foo/bar2
        touch foo/bar3
    """

    def filenames = [];
    def dir = new File("${env.WORKSPACE}/${FILES_DIR}");
    dir.traverse(type: FILES, maxDepth: 0) {
        filenames.add(it.getName())
    }

    for (int i = 0; i < filenames.size(); i++) {
        def filename = filenames[i]
        echo "${filename}"
    }
}

Und die Ausgabe zeigt, dass nur bar1 wird gedruckt:

Started by user Tamas Gal
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/TestHome
[Pipeline] {
[Pipeline] cleanWs
[WS-CLEANUP] Deleting project workspace...[WS-CLEANUP] done
[Pipeline] sh
[TestHome] Running Shell script
+ mkdir foo
+ touch foo/bar1
+ touch foo/bar2
+ touch foo/bar3
[Pipeline] echo
bar1
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
6
tamasgal

Sie können die new File - und normalen Groovy/Java-Methoden zum Durchlaufen von Dateisystemen nicht wirklich nutzen. Der Aufruf ist standardmäßig sicherheitsüberprüft (siehe JENKINS-38131 ) und funktioniert im Allgemeinen nicht, da Jenkins Pipelines Ihren Pipeline-Code ausführt.

Eine Möglichkeit, dies zu tun, ist die Verwendung des Schritts findFiles aus den Schritten des Pipeline-Dienstprogramms Plugin . Es wird ein FileWrapper[] zurückgegeben, das für andere Zwecke geprüft/verwendet werden kann.

node {
  // ... check out code, whatever
  final foundFiles = findFiles(glob: 'dockerfiles/**/*')
  // do things with FileWrapper[]
}

Eine andere Möglichkeit ist, den Standardausgang auszuspielen und zu erfassen:

node {
  // ... check out code, whatever
  final foundFiles = sh(script: 'ls -1 dockerfiles', returnStdout: true).split()
  // Do stuff with filenames
}
22
mkobit

Dieser funktioniert, aber er ist höllisch hässlich:

#!groovy

node('master') {
    FILES_DIR = './foo'
    cleanWs()

    sh """
        mkdir foo
        touch foo/bar1
        touch foo/bar2
        touch foo/bar3
    """

    def TMP_FILENAME = ".docker_files_list"
    sh "ls ${FILES_DIR} > ${TMP_FILENAME}"
    def filenames = readFile(TMP_FILENAME).split( "\\r?\\n" );
    sh "rm -f ${TMP_FILENAME}"

    for (int i = 0; i < filenames.size(); i++) {
        def filename = filenames[i]
        echo "${filename}"
    }
}
3
tamasgal