How to list folders containing a file on jenkins pipeline? - jenkins

I'm trying to list folders containing a certain file on jenkins and use later this array.
I read about findFiles but I can't find a way to use it in this situation.
The finality is that I need to cd to those folders in a loop and perform some actions.
I have only one jenkins where everything is running
Use case:
I have a workspace in which I have packages. I need to run some commands in some folders, I can't do it from the root of y workspace. They may be in subfolders or subsubfolders. The way I can identify a package is when it contains a package.xml (on ROS). Also I don't have any command to list their paths

If nothing else is working then you can try running a normal linux command like:
folders = sh(
script: "locate myfile",
returnStdout: true
)
Then split this to form an array and use the value like :
folders.split("\n")[1]

def packageDirs = findFiles(glob: '**/package.xml')
.findAll { f -> !f.directory }
.collect{ f -> f.path.replace('/', '\\') - ~/\\[^\\]+$/ }
packageDir.each { d ->
dir(d) {
// Process each package here
}
}

Related

File operations in Jenkins Pipeline

I have a pipeline flow defined as:
node("linux_label") {
println("hostname".execute().txt)
def filename = "${WORKSPACE}/submoduleinfo.txt"
stage("Submodule info") {
def submoduleString = sh script: "git -C ${WORKSPACE} submodule status > ${filename}", returnStdout: true
}
String fileContents = new File("$filename}").text
operateOnFile(fileContents)
}
At "new File" I will get an error saying no such file exists. after some troublehshooting I see that the hostname printout will output the jenkins master and not the node "linux_label" where the workspace resides.
Is this how Piepeline should work, i.e. all code that is not part of stage/steps/etc are executed on the jenkins master and not on the wanted node?
What would be a good workaround where I do an operation in one stage and want to operate on the file in the node {} domain?
That is how pipeline works. You can use readFile to read file from a workspace. Since you are using just a content of the file for your processing, this will work.
From tutorial:
readFile step loads a text file from the workspace and returns its
content (do not try to use java.io.File methods — these will refer to
files on the master where Jenkins is running, not in the current
workspace).
In one of our use case, we added some additional functions using Shared pipeline library.
Try this:
if (env['NODE_NAME'].equals("master")) {
return new hudson.FilePath(path);
} else {
return new hudson.FilePath(Jenkins.getInstance().getComputer(env['NODE_NAME']).getChannel(), path);
}

List Jenkins plugins and dependencies (with graph)

I have added many plugins to Jenkins. How can I list the plugins and dependencies? Which plugins depend on which ones? Which ones are orphaned or unused, etc.
Ideally, explain how to make a graph (graphviz/dot...) ?
Copy-paste this groovy snippet to get a list of plugins (this snippet based on this exemple from zendesk.com):
Note: the groovy must be pasted in _Manage Jenkins >> Script Console
def plugins = jenkins.model.Jenkins.instance.getPluginManager().getPlugins()
plugins.each {
println "${it.getShortName()} (${it.getVersion()}) => ${it.getDependencies()}"
}
To produce a graph, execute this snippet to generate a DOT graph (graphviz) file...
def plugins = jenkins.model.Jenkins.instance.getPluginManager().getPlugins()
println "digraph test {"
plugins.each {
def plugin = it.getShortName()
println "\"${plugin}\";"
def deps = it.getDependencies()
deps.each {
def s = it.shortName
println "\"${plugin}\" -> \"${s}\";"
}
}
println "}"
Then use graphviz to generate an image from the output above:
dot -Tsvg plugins.txt > plugins.svg
dot -Tpng plugins.txt > plugins.png
Or copy-paste the output in one of the Graphviz: Online tool capable of accepting larger files

find env variables for a all builds for a job on jenkins

I need to monitor what are the changes going with a job on jenkins(update the changes to a file). Need to list the env variables of a job. JOB_NAME,BUILD_NUMBER,BUILD_STATUS,GIT_URL for that build(all the builds of a job). I didn't find out a good example with the groovy. What is the best way to fetch all the info?
build.getEnvironment(listener) should get you what you need
Depending on what you would like to achieve there are at least several approaches to retrieve and save environment variables for:
current build
all past builds
Get environments variables for current build (from slave)
Execute Groovy script
// Get current environment variables and save as
// a file in $WORKSPACE.
new File(".",'env.txt').withWriter('utf-8') { writer ->
System.getenv().each { key, value ->
writer.writeLine("${key}:${value}")
}
}
Using Groovy Plug-in.
Get environment variables for current build (from master)
Execute system Groovy script
// Get current environment variables and save as
// a file in $WORKSPACE.
import hudson.FilePath
def path = "env-sys.txt"
def file = null
if (build.workspace.isRemote()) {
file = new FilePath(build.workspace.channel, build.workspace.toString() + "/" + path)
} else {
file = new FilePath(build.workspace.toString() + "/" + path)
}
def output = ""
build.getEnvironment(listener).each { key, value ->
output += "${key}:${value}\n"
}
file.write() << output
Using Groovy Plug-in.
Environment variables returned by Groovy scripts are kept in map. If you don't need all of them, you can access individual values using standard operators/methods.
Get environment variables for all past builds (from master)
This approach expecst that you have installed EnvInject Plug-in and have access to $JENKINS_HOME folder:
$ find . ${JENKINS_HOME}/jobs/[path-to-your-job] -name injectedEnvVars.txt
...
ps. I suspect that one could analyze EnvInject Plug-in API and find a way to extract this information directly from Java/Groovy code.
Using EnvInject Plug-in.
To look for only specific variables you can utilize find, grep and xargs tools .
You can use below script to get the Environment Variables
def thread = Thread.currentThread()
def build = thread.executable
// Get build parameters
def buildVariablesMap = build.buildVariables
// Get all environment variables for the build
def buildEnvVarsMap = build.envVars
String jobName = buildEnvVarsMap?.JOB_NAME // This is for JOB Name env variable.
Hope it helps!

How to access grails plugins directory in cloudbees from jenkins

I would like to execute a pre-build (grails) script from jenkins to replace a file in the plugins directory with a file in my SCM.
#!/bin/bash
PLUGINS_ORIG_DIR="plugins"
PLUGINS_DEST_DIR="/home/<my_user_name>/.grails/2.1.1/projects/judo/plugins"
cp -r $PLUGINS_ORIG_DIR/lang-selector-0.3/* $PLUGINS_DEST_DIR
But the script fails because the $PLUGINS_DEST_DIR cannot be found. Which should be the path or which is the best way to accomplish this?
Thank you.
[EDIT]
I have also tried to create an pre-war event, but it does not work either:
/**
* Copy modified resources to plugins directory, before packing the WAR
*/
eventCreateWarStart = { warName, stagingDir ->
def buildSettings = BuildSettingsHolder.getSettings()
def projectPluginsDir = buildSettings.getProperty("projectPluginsDir")
def baseDir = buildSettings.getProperty("baseDir")
ant.copy(todir:"${projectPluginsDir}/lang-selector-0.3", overwrite:true) {
fileset(dir:"${basedir}/plugins/lang-selector-0.3", includes:"**")
}
ant.copy(todir:"${projectPluginsDir}/jquery-datatables-1.7.5", overwrite:true) {
fileset(dir:"${basedir}/plugins/jquery-datatables-1.7.5", includes:"**")
}
}
as did you set your cloudbees account name ?
then you're wrong, should use /home/jenkins or just $HOME, as builds run on general purpose slaves as "jenkins" user
I have solved it by copying files to ${stagingDir}, instead of ${projectPluginsDir}

How do I clear my Jenkins/Hudson build history?

I recently updated the configuration of one of my hudson builds. The build history is out of sync. Is there a way to clear my build history?
Please and thank you
Use the script console (Manage Jenkins > Script Console) and something like this script to bulk delete a job's build history https://github.com/jenkinsci/jenkins-scripts/blob/master/scriptler/bulkDeleteBuilds.groovy
That script assumes you want to only delete a range of builds. To delete all builds for a given job, use this (tested):
// change this variable to match the name of the job whose builds you want to delete
def jobName = "Your Job Name"
def job = Jenkins.instance.getItem(jobName)
job.getBuilds().each { it.delete() }
// uncomment these lines to reset the build number to 1:
//job.nextBuildNumber = 1
//job.save()
This answer is for Jenkins
Go to your Jenkins home page → Manage Jenkins → Script Console
Run the following script there. Change copy_folder to your project name
Code:
def jobName = "copy_folder"
def job = Jenkins.instance.getItem(jobName)
job.getBuilds().each { it.delete() }
job.nextBuildNumber = 1
job.save()
My post
If you click Manage Hudson / Reload Configuration From Disk, Hudson will reload all the build history data.
If the data on disk is messed up, you'll need to go to your %HUDSON_HOME%\jobs\<projectname> directory and restore the build directories as they're supposed to be. Then reload config data.
If you're simply asking how to remove all build history, you can just delete the builds one by one via the UI if there are just a few, or go to the %HUDSON_HOME%\jobs\<projectname> directory and delete all the subdirectories there -- they correspond to the builds.
Afterwards restart the service for the changes to take effect.
Here is another option: delete the builds with cURL.
$ curl -X POST http://jenkins-host.tld:8080/jenkins/job/myJob/[1-56]/doDeleteAll
The above deletes build #1 to #56 for job myJob.
If authentication is enabled on the Jenkins instance, a user name and API token must be provided like this:
$ curl -u userName:apiToken -X POST http://jenkins-host.tld:8080/jenkins/job/myJob/[1-56]/doDeleteAll
The API token must be fetched from the /me/configure page in Jenkins. Just click on the "Show API Token..." button to display both the user name and the API token.
Edit: one might have to replace doDeleteAll by doDelete in the URLs above to make this work, depending on the configuration or the version of Jenkins used.
Here is how to delete ALL BUILDS FOR ALL JOBS...... using the Jenkins Scripting.
def jobs = Jenkins.instance.projects.collect { it }
jobs.each { job -> job.getBuilds().each { it.delete() }}
You could modify the project configuration temporarily to save only the last 1 build, reload the configuration (which should trash the old builds), then change the configuration setting again to your desired value.
If you want to clear the build history of MultiBranchProject (e.g. pipeline),
go to your Jenkins home page → Manage Jenkins → Script Console and run the following script:
def projectName = "ProjectName"
def project = Jenkins.instance.getItem(projectName)
def jobs = project.getItems().each {
def job = it
job.getBuilds().each { it.delete() }
job.nextBuildNumber = 1
job.save()
}
This one is the best option available.
Jenkins.instance.getAllItems(AbstractProject.class).each {it -> Jenkins.instance.getItemByFullName(it.fullName).builds.findAll { it.number > 0 }.each { it.delete() } }
This code will delete all Jenkins Job build history.
Using Script Console.
In case the jobs are grouped it's possible to either give it a full name with forward slashes:
getItemByFullName("folder_name/job_name")
job.getBuilds().each { it.delete() }
job.nextBuildNumber = 1
job.save()
or traverse the hierarchy like this:
def folder = Jenkins.instance.getItem("folder_name")
def job = folder.getItem("job_name")
job.getBuilds().each { it.delete() }
job.nextBuildNumber = 1
job.save()
Deleting directly from file system is not safe. You can run the below script to delete all builds from all jobs ( recursively ).
def numberOfBuildsToKeep = 10
Jenkins.instance.getAllItems(AbstractItem.class).each {
if( it.class.toString() != "class com.cloudbees.hudson.plugins.folder.Folder" && it.class.toString() != "class org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject") {
println it.name
builds = it.getBuilds()
for(int i = numberOfBuildsToKeep; i < builds.size(); i++) {
builds.get(i).delete()
println "Deleted" + builds.get(i)
}
}
}
Go to "Manage Jenkins" > "Script Console"
Run below:
def jobName = "build_name"
def job = Jenkins.instance.getItem(jobName)
job.getBuilds().each { it.delete() }
job.save()
Another easy way to clean builds is by adding the Discard Old Plugin at the end of your jobs. Set a maximum number of builds to save and then run the job again:
https://wiki.jenkins-ci.org/display/JENKINS/Discard+Old+Build+plugin
Go to the %HUDSON_HOME%\jobs\<projectname> remove builds dir and remove lastStable, lastSuccessful links, and remove nextBuildNumber file.
After doing above steps go to below link from UI
Jenkins-> Manage Jenkins -> Reload Configuration from Disk
It will do as you need
If using the Script Console method then try using the following instead to take into account if jobs are being grouped into folder containers.
def jobName = "Your Job Name"
def job = Jenkins.instance.getItemByFullName(jobName)
or
def jobName = "My Folder/Your Job Name
def job = Jenkins.instance.getItemByFullName(jobName)
Navigate to: %JENKINS_HOME%\jobs\jobName
Open the file "nextBuildNumber" and change the number. After that reload Jenkins configuration. Note: "nextBuildNumber" file contains the next build no that will be used by Jenkins.
Tested on jenkins 2.293 over linux. It will remove all the build logs but not the corellative build number
cd /var/lib/jenkins/jobs
find . -name "builds" -exec rm -rf {} \;
Be careful with this command because it executes a rm -rf on each find result. You could exec this first to validate if the result are only the builds folder of you jobs
find . -name "builds"
If you are looking for a solution where you have job inside a Folder you can use getItemByFullName function. It also supports white space in folder and job name.
def jobName = "folder_name/job_name"
def job = Jenkins.instance.getItemByFullName(jobName)
job.getBuilds().each { it.delete() }
job.nextBuildNumber = 1
job.save()

Resources