Need to check if folder exists in workspace in groovy script for jenkins pipeline - groovy

I need to check if a specific folder exists, I can not give the full path as some of the folder names will be different each time.
I used the below code -
echo "checking if folder exists"
def files = findFiles glob: '**/*example*'
echo """${files[0].name} ${files[0].path} ${files[0].directory} ${files[0].length} ${files[0].lastModified}"""
example is a folder which is inside -
java-maven-app/src/main/java/com/example
the error, I am getting in pipeline is -

You are getting that error because your files list doesn't have any content. AFAIK findFiles is not capable of finding directories recursively. If you have any known files within the directory you are looking for you may be able to get the full path to that file using findFiles and determine whether your directory exists. But it will not work if the directory is empty. As a better solution, you can use the following script to get a list of all directories recursively.
pipeline {
agent any
stages {
stage('Example') {
steps {
script {
def directories = getDirectories("$WORKSPACE")
echo "$directories"
}
}
}
}
}
#NonCPS
def getDirectories(path) {
def dir = new File(path);
def dirs = [];
dir.traverse(type: groovy.io.FileType.DIRECTORIES, maxDepth: -1) { d ->
dirs.add(d)
};
return dirs
}

Related

gulp clean is not working in correct manner

I have directory structure like this.
dist
|--client
|--assets
|--images
|--bower_components
|--server
|--.bower.json
I am trying to clean dist folder, except assets/images folder.
But when i execute this command in dryRun mode, it doesn't remove assets/images file. But after disabling it, it remove all the files and folder.
gulp.task('clean:dist', () => {
del.sync([
`${paths.dist}/!(.git*|.openshift|Procfile)**`,
`${paths.dist}/client/**`,
`!${paths.dist}/client/assets`,
`!${paths.dist}/client/assets/**`], {
//dryRun: true
});
//console.log('dELETE FIELSE ARE: ' + JSON.stringify(value));
});
value of used constant is:
${paths.dist} ='dist';
The offical del documentation states the following:
The glob pattern ** matches all children and the parent.
So this won't work:
del.sync(['public/assets/**', '!public/assets/goat.png']);
You have to explicitly ignore the parent directories too:
del.sync(['public/assets/**', '!public/assets', '!public/assets/goat.png']);
In your case you delete dist/client/**, which includes the dist/client directory itself. If you just ignore dist/client/assets/** the dist/client directory is still deleted.
You need to explicitly ignore the dist/client directory:
gulp.task('clean:dist', () => {
del.sync([
`${paths.dist}/!(.git*|.openshift|Procfile)**`,
`${paths.dist}/client/**`,
`!${paths.dist}/client`,
`!${paths.dist}/client/assets/**`]);
});

gradle get relative resource path

When I iterate over source repository I do like this
def resourceDir = proj.sourceSets.main.output.resourcesDir
resourceDir.eachFileRecurse(groovy.io.FileType.FILES) { // only files will be recognized
file ->
def path = FilenameUtils.separatorsToUnix(file.toString())
if (FilenameUtils.getExtension(file.toString()) in supportedResourceExt) {
proj.logger.lifecycle("Reading file {}.", file)
//.....
}
}
In log it writes this
Reading file D:\PROJECT_FOLDER\project\subproject\subsubproject\build\resources\main\com\package\something\file.txt
How to get only the part starting with com\package\something\file.txt without explicitly reading it like file.substring(file.indexOf)?
Maybe it's posible to relativize it with project path somehow?
It seems that:
proj.logger.lifecycle("Reading file {}.", file.absolutePath - resourceDir.absolutePath)
should work. Can't check it right now.

Flatten first directory of a FileTree in Gradle

I'm writing a task to extract a tarball into a directory. I don't control this tarball's contents.
The tarball contains a single directory which contains all the files I actually care about. I want to pull everything out of that directory and copy that into my destination.
Example:
/root/subdir
/root/subdir/file1
/root/file2
Desired:
/subdir
/subdir/file1
/file2
Here's what I tried so far, but this seems like a really goofy way of doing it:
copy {
eachFile {
def segments = it.getRelativePath().getSegments() as List
it.setPath(segments.tail().join("/"))
return it
}
from tarTree(resources.gzip('mytarfile.tar.gz'))
into destinationDir
}
For each file, I get the elements of its path, remove the first, join that with /, then set that as the file's path. And this works...sort of. The problem is that this creates the following structure as a result:
/root/subdir
/root/subdir/file1
/root/file2
/subdir
/subdir/file1
/file2
I'm fine with just removing the root directory myself as a final action of the task, but I feel like there should be a much simpler way of doing this.
AFAIK, the only way is to unpack the zip, tar, tgz file :(
There is an open issue here
Please go vote for it!
Until then, the solution isn't very pretty, but not that hard either. In the example below, I am assuming that you want to remove the 'apache-tomcat-XYZ' root-level directory from a 'tomcat' configuration that only includes the apache-tomcat zip file.
def unpackDir = "$buildDir/tmp/apache.tomcat.unpack"
task unpack(type: Copy) {
from configurations.tomcat.collect {
zipTree(it).matching {
// these would be global items I might want to exclude
exclude '**/EMPTY.txt'
exclude '**/examples/**', '**/work/**'
}
}
into unpackDir
}
def mainFiles = copySpec {
from {
// use of a closure here defers evaluation until execution time
// It might not be clear, but this next line "moves down"
// one directory and makes everything work
"${unpackDir}/apache-tomcat-7.0.59"
}
// these excludes are only made up for an example
// you would only use/need these here if you were going to have
// multiple such copySpec's. Otherwise, define everything in the
// global unpack above.
exclude '**/webapps/**'
exclude '**/lib/**'
}
task createBetterPackage(type: Zip) {
baseName 'apache-tomcat'
with mainFiles
}
createBetterPackage.dependsOn(unpack)
Using groovy's syntax, we can use a regex to eliminate the first path segment:
task myCopyTask(type: Copy) {
eachFile {
path -= ~/^.+?\//
}
from tarTree(resources.gzip('mytarfile.tar.gz'))
into destinationDir
includeEmptyDirs = false // ignore empty directories
}

Reading file from Workspace in Jenkins with Groovy script

I want to add a Build step with the Groovy plugin to read a file and trigger a build fail depending on the content of the file.
How can I inject the workspace file path in the groovy plugin ?
myFileDirectory = // Get workspace filepath here ???
myFileName = "output.log"
myFile = new File(myFileDirectory + myFileName)
lastLine = myFile.readLines().get(myFile.readLines().size().toInteger() - 1)
if (lastLine ==~ /.Fatal Error.*/ ){
println "Fatal error found"
System.exit(1)
} else{
println "nothing to see here"
}
I realize this question was about creating a plugin, but since the new Jenkins 2 Pipeline builds use Groovy, I found myself here while trying to figure out how to read a file from a workspace in a Pipeline build. So maybe I can help someone like me out in the future.
Turns out it's very easy, there is a readfile step, and I should have rtfm:
env.WORKSPACE = pwd()
def version = readFile "${env.WORKSPACE}/version.txt"
If you are trying to read a file from the workspace during a pipeline build step, there's a method for that:
readFile('name-of-file.groovy')
For reference, see https://jenkins.io/doc/pipeline/steps/workflow-basic-steps/#readfile-read-file-from-workspace.
Based on your comments, you would be better off with Text-finder plugin.
It allows to search file(s), as well as console, for a regular expression and then set the build either unstable or failed if found.
As for the Groovy, you can use the following to access ${WORKSPACE} environment variable:
def workspace = manager.build.getEnvVars()["WORKSPACE"]
Although this question is only related to finding directory path ($WORKSPACE) however I had a requirement to read the file from workspace and parse it into JSON object to read sonar issues ( ignore minor/notes issues )
Might help someone, this is how I did it-
from readFile
jsonParse(readFile('xyz.json'))
and jsonParse method-
#NonCPS
def jsonParse(text) {
return new groovy.json.JsonSlurperClassic().parseText(text);
}
This will also require script approval in ManageJenkins-> In-process script approval
May this help to someone if they have the same requirement.
This will read a file that contains the Jenkins Job name and run them iteratively from one single job.
Please change below code accordingly in your Jenkins.
pipeline {
agent any
stages {
stage('Hello') {
steps {
script{
git branch: 'Your Branch name', credentialsId: 'Your crendiatails', url: ' Your BitBucket Repo URL '
##To read file from workspace which will contain the Jenkins Job Name ###
def filePath = readFile "${WORKSPACE}/ Your File Location"
##To read file line by line ###
def lines = filePath.readLines()
##To iterate and run Jenkins Jobs one by one ####
for (line in lines) {
build(job: "$line/branchName",
parameters:
[string(name: 'vertical', value: "${params.vert}"),
string(name: 'environment', value: "${params.env}"),
string(name: 'branch', value: "${params.branch}"),
string(name: 'project', value: "${params.project}")
]
)
}
}
}
}
}
}
If you already have the Groovy (Postbuild) plugin installed, I think it's a valid desire to get this done with (generic) Groovy instead of installing a (specialized) plugin.
That said, you can get the workspace using manager.build.workspace.getRemote(). Don't forget to add File.separator between path and file name.
As mentioned in a different post Read .txt file from workspace groovy script in Jenkins I was struggling to make it work for the pom modules for a file in the workspace, in the
Extended Choice Parameter. Here is my solution with the printlns:
import groovy.util.XmlSlurper
import java.util.Map
import jenkins.*
import jenkins.model.*
import hudson.*
import hudson.model.*
try{
//get Jenkins instance
def jenkins = Jenkins.instance
//get job Item
def item = jenkins.getItemByFullName("The_JOB_NAME")
println item
// get workspacePath for the job Item
def workspacePath = jenkins.getWorkspaceFor (item)
println workspacePath
def file = new File(workspacePath.toString()+"\\pom.xml")
def pomFile = new XmlSlurper().parse(file)
def pomModules = pomFile.modules.children().join(",")
return pomModules
} catch (Exception ex){
println ex.message
}

Variable project configuration is bound to in groovy axis plugin for jenkins

I have a multi-configuration build for which I'd like essentally one build to be run for each file matching foo/*/bar/*.xml. I figured the GroovyAxis Plugin would be a nice fit, but I cannot find any documentation on how the build configuration can be accessed from within the script, so I cannot read the workspace-directory from anywhere.
Running something like return new File('.').listFiles().collect{it.toString()} returns all files within the root directory of the server.
Can anyone point me in the right direction?
It took a while to figure this out, but here is a solution. Note that since the Groovy script runs on the master, you must use FilePath to access the files on the slave.
import hudson.FilePath
def workspace = context?.build?.workspace
if (null == workspace) {
return ['noworkspace'] // avoid returning 'default' so the user has a chance of figuring out what went wrong
}
def configDir = workspace.toString() + '/openpower/configs/'
def dir = new FilePath(workspace.channel, configDir)
def files = []
dir.list().each {
def name = it.getName()
if (name.endsWith('_defconfig')) {
files << name.replace('_defconfig', '')
}
}
return files

Resources