Search code examples
groovyjenkinsbuildforever

Do not delete a Jenkins build if it's marked as "Keep this build forever" - Groovy script to delete Jenkins builds


I have the following Groovy script which deletes all builds of a given Jenkins job except one build number that user provides (i.e. wants to retain).

/*** BEGIN META {
  "name" : "Bulk Delete Builds except the given build number",
  "comment" : "For a given job and a given build number, delete all build except the user provided one.",
  "parameters" : [ 'jobName', 'buildNumber' ],
  "core": "1.409",
  "authors" : [
     { name : "Arun Sangal" }
  ]
} END META **/


// NOTE: Uncomment parameters below if not using Scriptler >= 2.0, or if you're just pasting the script in manually.
// ----- Logic in this script takes 5000 as the infinite number, decrease / increase this value from your own experience.
// The name of the job.
//def jobName = "some-job"

// The range of build numbers to delete.
//def buildNumber = "5"

def lastBuildNumber = buildNumber.toInteger() - 1;
def nextBuildNumber = buildNumber.toInteger() + 1;


import jenkins.model.*;
import hudson.model.Fingerprint.RangeSet;

def jij = jenkins.model.Jenkins.instance.getItem(jobName);

println("Keeping Job_Name: ${jobName} and build Number: ${buildNumber}");
println ""

def setBuildRange = "1-${lastBuildNumber}"
def range = RangeSet.fromString(setBuildRange, true);
jij.getBuilds(range).each { it.delete() }
println("Builds have been deleted - Range: " + setBuildRange)

setBuildRange = "${nextBuildNumber}-5000"
range = RangeSet.fromString(setBuildRange, true);
jij.getBuilds(range).each { it.delete() }
println("Builds have been deleted - Range: " + setBuildRange)

This works well for any Jenkins job. For ex: If your Jenkins job name is "TestJob" and you have 15 builds i.e. build# 1 to build 15 in Jenkins, and you want to delete all but retain build# 13, then this script will delete the builds (build# 1-12 and 14-15 - even if you mark any build as "Keep this build forever") and only keep build#13.


Now, what I want is:

  1. what should I change in this script to not delete a build - if a build is marked in Jenkins as "Keep this build forever". I tried the script and it deleted that keep forever build too.

  2. Lets say, if I'm using "Build name setter plugin" in Jenkins, which can give me build names as what name I want i.e. instead of getting just build as build#1 or #2, or #15, I will get build as build# 2.75.0.1, 2.75.0.2, 2.75.0.3, ..... , 2.75.0.15 (as I would have set the build name/description as use some variable which contains 2.75.0 (as a release version value) and suffixed it with the actual Jenkins job's build number i.e. the last 4th digit - ex: set the name as:

    ${ENV,var="somepropertyvariable"}.${BUILD_NUMBER}
    

    In this case, I'll start getting Jenkins builds as 2.75.0.1 to 2.75.0.x (where x is the last build# of that release (2.75.0)). Similarly, when I'll change the property release version to next i.e. 2.75.1 or 2.76.0, then the same Jenkins job will start giving me builds as 2.75.1.0, 2.75.1.1, ...., 2.75.1.x or 2.76.0.1, 2.76.0.2, ...., 2.76.0.x and so on. During the release version change, let say, our build will start from 1 again (as I mentioned above for 2.75.1 and 2.76.0 release versions).

    In this case, if my Jenkins job's build history (shows all builds for 2.75.0.x, 2.75.1.x and 2.76.0.x), then what change should I make in this script to include a 3rd parameter/argument. This 3rd argument will take release /version value i.e. either 2.75.0 or 2.75.1 or 2.76.0 and then this script should delete build numbers on that release only (and should NOT delete other release's builds).


Solution

  • OK - Solution for my question 2 is here: I'm still working on fixing question 1.

    http://scriptlerweb.appspot.com/script/show/102001

    bulkDeleteJenkinsBuildsExceptOne_OfAGivenRelease.groovy

    /*** BEGIN META {
      "name" : "Bulk Delete Builds except the given build number",
      "comment" : "For a given job and a given build numnber, delete all builds of a given release version (M.m.interim) only and except the user provided one. Sometimes a Jenkins job use Build Name setter plugin and same job generates 2.75.0.1 and 2.76.0.43",
      "parameters" : [ 'jobName', 'releaseVersion', 'buildNumber' ],
      "core": "1.409",
      "authors" : [
         { name : "Arun Sangal" }
      ]
    } END META **/
    
    
    // NOTE: Uncomment parameters below if not using Scriptler >= 2.0, or if you're just pasting the script in manually.
    // ----- Logic in this script takes 5000 as the infinite number, decrease / increase this value from your own experience.
    // The name of the job.
    //def jobName = "some-job"
    
    // The release / version of a Jenkins job - i.e. in case you use "Build name" setter plugin in Jenkins for getting builds like 2.75.0.1, 2.75.0.2, .. , 2.75.0.15 etc.
    // and over the time, change the release/version value (2.75.0) to a newer value i.e. 2.75.1 or 2.76.0 and start builds of this new release/version from #1 onwards.
    //def releaseVersion = "2.75.0"
    
    // The range of build numbers to delete.
    //def buildNumber = "5"
    
    def lastBuildNumber = buildNumber.toInteger() - 1;
    def nextBuildNumber = buildNumber.toInteger() + 1;
    
    
    import jenkins.model.*;
    import hudson.model.Fingerprint.RangeSet;
    
    def jij = jenkins.model.Jenkins.instance.getItem(jobName);
    //def build = jij.getLastBuild();
    
    println ""
    println("- Jenkins Job_Name: ${jobName} -- Version: ${releaseVersion} -- Keep Build Number: ${buildNumber}");
    println ""
    println "  -- Range before given build number: ${buildNumber}"
    println ""
    
    def setBuildRange = "1-${lastBuildNumber}"
    def range = RangeSet.fromString(setBuildRange, true);
    jij.getBuilds(range).each {
      if ( it.getDisplayName().find(/${releaseVersion}.*/)) {
         println "     ## Deleting >>>>>>>>>: " + it.getDisplayName();
    
         // Trying to find - how to NOT delete a build in Jenkins if it's marked as "keep this build forever". If someone has an idea, please update this script with a newer version in GitHub.
         //if ( !build.isKeepLog()) {
              it.delete();
         //} else {
         //   println "build -- can't be deleted as :" + build.getWhyKeepLog();
         //}
      }
    }
    
    
    
    println ""
    println "  -- Range after  given build number: ${buildNumber}"
    println ""
    setBuildRange = "${nextBuildNumber}-5000"
    range = RangeSet.fromString(setBuildRange, true);
    jij.getBuilds(range).each {
      if ( it.getDisplayName().find(/${releaseVersion}.*/)) {
         println "     ## Deleting >>>>>>>>>: " + it.getDisplayName();
         it.delete();
      }
    }
    
    println ""
    println("- Builds have been successfully deleted for the above mentioned release: ${releaseVersion}")
    println ""
    

    enter image description here

    One can also call this script via a Jenkins job (requires 3 parameters as mentioned in the scriptler script) -OR call it from browser as well: using the following link:

    http ://YourJenkinsServerName:PORT/job/Some_Jenkins_Job_That_You_Will_Create/buildWithParameters?jobName=Test_AppSvc&releaseVersion=2.75.0&buildNumber=15