Last active
February 13, 2020 04:34
-
-
Save talenguyen/fd308b043632ead21faec9f34328274b to your computer and use it in GitHub Desktop.
Jenkins cleanup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.cloudbees.hudson.plugins.folder.AbstractFolder | |
import hudson.model.AbstractItem | |
import groovy.transform.Field | |
def jobName = "Android-Verify" // jobName can be set to a Job or a Folder. If a folder, it will clean all jobs in that folder | |
//jobName should be full job name from root if mutliple levels down(for example "Folder1/Folder2/Job") | |
def resetBuildNumber = false // If this is true, the build number will be set back to 1 | |
@Field def dryRun = false // If this is true, the job will run without deletion. | |
@Field def cleanedJobsTotal = 0 | |
@Field def keepDays = 0 // Days to keep. | |
removeBuilds(Jenkins.instance.getItemByFullName(jobName), resetBuildNumber) | |
def removeBuilds(job, resetBuildNumber) { | |
println "removeBuilds => ${job}" | |
def count | |
def now = new Date() | |
if (job instanceof AbstractFolder) { | |
cleanedJobsLimit = 10 //Maximum number of jobs to clean in one run, useful for large systems or slow disks | |
for (subJob in job.getItems()) { | |
if(cleanedJobsTotal >= cleanedJobsLimit){ | |
println "The cleaned jobs limit of " + cleanedJobsTotal + " has been reached. Exiting..." | |
return | |
} | |
else{ | |
removeBuilds(subJob, resetBuildNumber) | |
} | |
} | |
} else if (job instanceof Job) { | |
count = 0 | |
buildsDeleted = false | |
def builds | |
if (job.isBuildable()) { // If PR is merged or closed then it is not buildable. We can safety delete all of its builds, otherwise we keep the last build. | |
builds = job.getBuilds().drop(1) | |
} else { | |
builds = job.getBuilds() | |
} | |
builds.each { | |
println ":: Process " + it | |
def duration = groovy.time.TimeCategory.minus( | |
now, | |
it.getTimestamp().getTime() | |
) | |
println "Build " + duration.days | |
if(job.isBuildable() && duration.days < keepDays){ | |
println "Ignore build that is scheduled within $keepDays days: " + it | |
} | |
else{ | |
println "Delete out date build: " + it | |
if (dryRun) { | |
println "Dry run mode => delete ${it} will be not perform" | |
} else { | |
it.delete() | |
} | |
} | |
} | |
if (job.getBuilds().isEmpty()) { | |
println "Job " + job.name + " is empty and will be deleted" | |
try { | |
job.delete() | |
} catch (e) { | |
} | |
buildsDeleted = true | |
} | |
if(buildsDeleted){ | |
println "Job " + job.name + " cleaned successfully.\n" | |
cleanedJobsTotal++ | |
} | |
if (resetBuildNumber) { | |
job.nextBuildNumber = 1 | |
job.save() | |
} | |
} else { | |
//Do nothing, next job | |
//throw new RuntimeException("Unsupported job type ${job.getClass().getName()}!") | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NOTES: | |
// dryRun: to only list the jobs which would be changed | |
// daysToKeep: If not -1, history is only kept up to this days. | |
// numToKeep: If not -1, only this number of build logs are kept. | |
// artifactDaysToKeep: If not -1 nor null, artifacts are only kept up to this days. | |
// artifactNumToKeep: If not -1 nor null, only this number of builds have their artifacts kept. | |
import jenkins.model.Jenkins | |
def dryRun = "true"; | |
def daysToKeep = 7; | |
def numToKeep = 5; | |
def artifactDaysToKeep = -1; | |
def artifactNumToKeep = -1; | |
Jenkins.instanceOrNull.allItems(hudson.model.Job).each { job -> | |
if (job.isBuildable() && job.supportsLogRotator() && job.getProperty(jenkins.model.BuildDiscarderProperty) == null) { | |
println "Processing \"${job.fullDisplayName}\"" | |
if (!"true".equals(dryRun)) { | |
// adding a property implicitly saves so no explicit one | |
try { | |
job.setBuildDiscarder(new hudson.tasks.LogRotator ( daysToKeep, numToKeep, artifactDaysToKeep, artifactNumToKeep)) | |
println "${job.fullName} is updated" | |
} catch (Exception e) { | |
// Some implementation like for example the hudson.matrix.MatrixConfiguration supports a LogRotator but not setting it | |
println "[WARNING] Failed to update ${job.fullName} of type ${job.class} : ${e}" | |
} | |
} | |
} | |
} | |
return; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment