What is a good strategy for cleaning Jenkins workspace? After getting started with Jenkins in a large team, available workspace space is shrinking, even through jobs/pipelines seems to do due diligence to clean after themselves.
The current approach I am trying: iterate through every node (including master),
under $WORKSPACE, find and delete directories over given age. Does this seem safe?
I tried online groovy code snippets to run via Jenkins console, and those got rejected with errors. I'd rather stick with simple code that is known to work.
Many thanks.
I have a stage for each run that cleans the work space:
node {
try {
stage('Clean Work Space') {
cleanWs()
sh 'pwd'
sh 'ls'
}
}
}
I would also refer to: https://jenkins.io/doc/pipeline/steps/ws-cleanup/
You can use the "Discard Old Builds" option on the Jobs to limit the number of builds stored for every job. This will reduce the disk space usage.
you can use deleteDir() command to clean the work space.
The best strategy to delete the Workspaces is to either go by Sprint numbers (if you are using agile) or by Date modified (to retain latest top 5).
I have created a script that has Groovy scripts for both of the strategies mentioned above.
Here is my detailed blog on strategies to delete Jenkins workspace for all jobs and individual jobs.
https://medium.com/#vishnuteja/jenkins-cleanup-workspace-reduce-disk-usage-18310097d3ef
Here is the code for cleaning up workspaces by Date modified.
import jenkins.*
import jenkins.model.*
import hudson.*
import hudson.model.*
//manager.listener.logger.println new Date(System.currentTimeMillis()).format('MM/dd/yyyy hh:mm:ss a') + " / " + " -- Start Time"
//Get value from String Parameter
MAX_BUILDS = manager.build.buildVariables.get("MAX_BUILDS").toInteger()
for (job in Jenkins.instance.items)
{
int count = 0
manager.listener.logger.println "\n ***Job Name: "+job.name+"***"
if(job.workspace!=null && job.workspace!="") //Check if there is a workspace associated with the Job
{
manager.listener.logger.println "Workspace path : " + job.workspace
String workspace = job.workspace
File folder = new File(workspace)
if(folder!=null && folder.exists()) //Check if the Workspace folder exists
{
// Get all files and folders within the Workspace of current job.
//Iterate through only folders and sort em by Modified Date.
File[] files = new File(workspace).listFiles().sort(){
a,b -> b.lastModified().compareTo a.lastModified()
}
.each{
if(!it.isFile()) //Check only for folders
{
if(count < MAX_BUILDS)
manager.listener.logger.println new Date(it.lastModified()).format('MM/dd/yyyy hh:mm:ss a') + " /" + it.name + " -- Save"
else
{
manager.listener.logger.println new Date(it.lastModified()).format('MM/dd/yyyy hh:mm:ss a') + " /" + it.name + " ** Deleted"
it.deleteDir()
}
count++
}
}
}
else
{
manager.listener.logger.println "Workspace is empty or doesn't exist"
}
}
else
{
manager.listener.logger.println "No Workspace associated with this job"
}
}
}
//manager.listener.logger.println new Date(System.currentTimeMillis()).format('MM/dd/yyyy hh:mm:ss a') + " / " + " -- End Time"
Related
I have a Jenkins instance with multiple teams using it. It gets cluttered frequently and people don't delete their test jobs after testing. Is there a way to delete unused jobs (not run in the last 6 months) including their workspace?
You can use the following Groovy script for this. Comment out the delete part and test it before using just to make sure it's what you need :)
def deleteBefore = "2022/07/01"
Jenkins.instance.getAllItems(Job.class).each { jobitem ->
def jobName = jobitem.getFullName()
def deleteBeforeTime = new Date(deleteBefore).getTime()
def build = jobitem.getLastBuild()
if(build == null || build.getTimeInMillis() <= deleteBeforeTime){ // If no builds, build is null
println build == null ? "Job " + jobName + " has never run, deleting the Job" : "Job " + jobName + " last ran on (" + build.getTime() + ") hence deleting"
jobitem.delete()
}
}
In Jenkins, I want to list all Jenkins jobs using the groovy script, I have tried a couple of groovy scripts to get the jobs, and it's working fine, Now I want to get the count of all Jobs without folders and subfolders.
Below is the groovy script which I have tried to the all jobs list including folder and subfolders, but I need only jobs which are WorkflowJob, FreestyleProject, and maven build
Jenkins.instance.getAllItems(Job.class).each{
println it.name + " - " + it.class
}
and 2 one is how can I get a list of active jobs and disabled jobs list and count
I have tried from below reference, but it's not working
find disabled job link found in google
Someone please can help on this, help is much appreciated
Part 01
I'm not sure what you meant by a Maven build Job. But, here is how to list all the Jobs which are either a Workflow Job or a Freestyle Job and which do not reside in a folder/subfolder.
Jenkins.instance.getAllItems(Job.class).each { jobitem ->
if(jobitem.getName() == jobitem.getFullName()) { // This means it's not in a folder
if(jobitem instanceof org.jenkinsci.plugins.workflow.job.WorkflowJob || jobitem instanceof hudson.model.FreeStyleProject) {
println("Job Name: " + jobitem.getFullName())
}
}
}
Part 02
List disabled Jobs.
Jenkins.instance.getAllItems(Job.class).each { jobitem ->
if(jobitem.isDisabled()) {
println("Job Name: " + jobitem.getFullName())
}
}
List Jobs that are not disabled/active.
Jenkins.instance.getAllItems(Job.class).each { jobitem ->
if(!jobitem.isDisabled()) {
println("Job Name: " + jobitem.getFullName())
}
}
I try to select all current running processes to get the BuildNumber an JobName of the running pipelines to finaly have the possibility to kill them.
However, if I use the Jenkins API to collect the BuildNumber and JobName I will get as return:
[(master)]:
[org.jenkinsci.plugins.workflow.job.WorkflowJob#6b41187c[myPipeline], org.jenkinsci.plugins.workflow.job.WorkflowJob#6296243a[myDeploy]]
I assumed that "#6296243a[myDeploy]" is the information I need. But the "6296243a" is not a valid BuildNumber. I really do not know what this number stands for. Maybe the process id.
The "myDeploy" is the JobName I need to have.
So my question why I will not get a valid "BuildNumber" here?
import jenkins.model.*
import hudson.model.*
def result = []
def buildingJobs = Jenkins.instance.getAllItems(Job.class).findAll {
it.isBuilding()
}
println buildingJobs
Finaly I want to use the both information at:
Jenkins.instance
.getItemByFullName(<JobName>)
.getBuildByNumber(<BuldNumber>)
.finish(hudson.model.Result.ABORTED, new java.io.IOException("Aborting build"));
if I use here the values BuildNumber: 6296243a JobName: myDeploy it will not work. If I use the BuildNumber from the view (2357) it works well.
So anybody has a hint how to receive the real BuildNumber?
From the example code, you provided, buildingJobs will have a List of WorkflowJob objects. Hence you are getting a reference to the objects when you print it.
Here is how you can get the Build IDs and Job names of currently running and paused builds.
Jenkins.instance.getAllItems(Job.class).findAll{it.isBuilding()}.each { job ->
job.getBuilds().each { b ->
if(b.isInProgress()) {
println "Build: " + b.getNumber() + " of Job: " + job.getName() + " is Running. Hence Killing!!!"
}
}
}
I am looking for a way to get a list of build and source code management section in the configuration.
For Example: I have jobs with Testcomplete and SoupUI Pro plug ins, in each jobs, in the configuration section, we input the git repo name, testsuite name, directory etc ...
Currently, I am having to go to each job, click on configuration and get the values I need, would be nice where I can get all this information for all the jobs. I looked in configuration slicing, but it does not have the section I need.
Thank you for your help in advance.
I have not used either plugin you mention, but this crude little groovy script will find every Freestyle job and if it has a gitSCM step, report the primary Git repo url, then for every "Invoke top-level Maven target", report the POM value if set.
Run from <JENKINS_URL>/script or in a Jenkins job with an "Execute System Groovy Script" (not an "Execute Groovy script").
You can modify to find your plugin's builder step and properties. You can get the values by examining <job>/config.xml instead of <job>/configure.
Updated example to specifically include also looking up TestComplete plugin (com.smartbear.jenkins.plugins.testcomplete.TcTestBuilder) values.
Similar approach left to OP for ReadyAPI Functional Testing plugin - (com.smartbear.ready.jenkins.JenkinsSoapUIProTestRunner)
WARNING: soapui-pro-functional-testing:1.6 transmits passwords in clear text. So too does SmartBear's Zephyr products. Does not inspire confidence in a company who's tagline is "quality matters more than ever.... we'll help you get there."
Jenkins.instance.allItems.findAll() {
it instanceof hudson.model.FreeStyleProject
}.each { job ->
if (job.scm instanceof hudson.plugins.git.GitSCM) {
println job.fullName + ' | ' + job.scm.userRemoteConfigs.url[0]
job.builders.findAll() {
it instanceof hudson.tasks.Maven
}.each {step ->
println ' : ' + step?.pom
}
job.builders.findAll() {
it instanceof com.smartbear.jenkins.plugins.testcomplete.TcTestBuilder
}.each {step ->
if (step?.getLaunchType() == 'lcRoutine') {
println ' : ' + step?.getProject() + ' : ' + step?.getUnit() + ' : ' + step?.getRoutine()
}
}
}
}
return
ps: I'm sure there's a cleaner way to iterate but I can't do all the work. Be sure to use the "?" to handle null values
I want to delete old builds for all the jobs I kept inside a folder from the script console, not from Jenkins individual job configuration to discard old builds. I want to keep only the recent 10 builds and remove the older ones. I am asking about the deletion of the old builds of a particular folder and not other jobs in another folder.
The following groovy script will delete all the builds excluding the 10 most recent builds of each job configured in Jenkins.
import jenkins.model.*
import hudson.model.*
Jenkins.instance.getAllItems(AbstractItem.class).each {
def job = jenkins.model.Jenkins.instance.getItem(it.fullName)
if (job!=null){
println "job: " + job;
int i = 1;
job.builds.each {
def build = it;
if (i<=10){
println "build: " + build.displayName + " will NOT BE DELETED";
}else{
println "build: " + build.displayName + " will BE DELETED";
it.delete();
}
i = ++i
}
}
};
The first loop will iterate over all Jenkins items and will store it under job var. If the job is not a Jenkins Job the result can be null, so the if (job!=null) check is there to allow the code to proceed only for Jenkins jobs.
The int i = 1; is the initialization of a counter for each job, that is incremented when a build is found. As far as I know, the build order is preserved, and the most recent build is returned first in the loop. When the counter reaches 10 or more, the if..else enters the else block and deletes the build it.delete()