web-dev-qa-db-fra.com

Obtenir une liste des noms de fichiers dans un dossier donné dans Jenkinsfile (Groovy)

Je ne peux pas créer une simple liste de noms de fichiers dans un répertoire donné dans un pipeline Jenkins scripté. J'ai essayé de nombreux exemples de scripts Groovy publiés sur SO et d'autres forums, mais soit la fonctionnalité est bloquée, soit la méthode est introuvable ou autre).

Cela semble être le plus simple

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

Mais cela résout le chemin relatif de manière incorrecte, donc j'obtiens cette erreur:

Java.io.FileNotFoundException: /./dockerfiles

J'ai également essayé de l'envelopper dans dir avec:

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

Mais j'ai la même erreur:

Java.io.FileNotFoundException: /./dockerfiles

Cela ne donne pas d'erreur, mais n'ajoute qu'un fichier à la liste:

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

Le contenu de dockerfiles manque alors tous les fichiers sauf le premier:

['py365']

Voici un Pipeline minimal pour le reproduire dans Jenkins:

#!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}"
    }
}

Et la sortie, montrant que seul bar1 est imprimé:

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

Vous ne pouvez pas vraiment utiliser le new File et les méthodes Groovy/Java normales pour parcourir les systèmes de fichiers. La sécurité de l'appel est vérifiée par défaut (voir JENKINS-38131 ) et ne fonctionnera même pas en raison de la façon dont Jenkins Pipelines exécute votre code de pipeline.

Une façon de procéder serait d'utiliser l'étape findFiles à partir des étapes de l'utilitaire de pipeline plugin . Il renvoie un FileWrapper[] qui peut être inspecté/utilisé à d'autres fins.

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

Une autre option consiste à décortiquer et capturer la sortie standard:

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

Celui-ci fonctionne, mais c'est moche comme l'enfer:

#!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