Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get a list of filenames in a given folder in Jenkinsfile (Groovy)

I cannot create a simple list of filenames in a given directory in a scripted Jenkins Pipeline. I tried many Groovy Script examples posted on SO and other forums but either the feature is blocked or I get method not found or whatever.

This seems to be the easiest

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

But this resolves the relative path incorrectly, so I get this error:

java.io.FileNotFoundException: /./dockerfiles

I also tried to wrap it in dir with:

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

But got the same error:

java.io.FileNotFoundException: /./dockerfiles

This does not give an error, but only adds one file to the list:

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

The contents of dockerfiles is then missing all the files but the first one:

['py365']

Here is a minimal Pipeline to reproduce it in 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}"
    }
}

And the output, showing that only bar1 is printed:

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
like image 732
tamasgal Avatar asked May 29 '18 14:05

tamasgal


1 Answers

You can't really make use of the new File and normal Groovy/Java ways to traverse file systems. The call is security checked by default (see JENKINS-38131) and won't even generally work because of how Jenkins Pipelines executes your pipeline code.

One way you could do this would be to use the findFiles step from the Pipeline Utility Steps plugin. It returns a FileWrapper[] which can be inspected/used for other purposes.

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

Another option is to shell out and capture the standard out:

node {
  // ... check out code, whatever
  final foundFiles = sh(script: 'ls -1 dockerfiles', returnStdout: true).split()
  // Do stuff with filenames
}
like image 170
mkobit Avatar answered Sep 23 '22 02:09

mkobit