Tag Archives: jenkins

Remove Old Job Builds on Jenkins with Groovy Script

Purpose

This article describes a way to use a Groovy script to remove old builds from all jobs up to a set number. In other words, you set how many of the latest builds to keep and run it on the Jenkins Master to cleanup all previous builds for all jobs. This script includes Cloudbees Folders, Basic Projects, Github Organizations plugin and Workflow Multibranch plugin support.

Take the following script and either run it from the CLI or from the Jenkins Management Script Console GUI.

Prerequisites

  • Jenkins 2.x+

Steps Using GUI

  1. Set the 2nd argument to how many builds you wish to keep. In this example all but 10 builds will be deleted for each job. listJobObjects(item, 10, 0)
  2. Select Manage Jenkins on the Master you wish to perform the task on
  3. Select Script Console
  4. Paste the Groovy Script in the script window
  5. Select Run

Steps for CLI

  1. First you have to have a SSH Key pair setup for a user that has adiquite permissions
    1. Generate SSH Key pair
      [codesyntax lang="bash"]

      ssh-keygen -t rsa -b 4096

      [/codesyntax]

    2. Add public key to local admin Jenkins user
      1. Browse People | <username> | Configure
      2. Paste Public key in SSH Public Keys window and Save
  2. Copy the groovy script content to a file such as /tmp/remove-old-builds.groovy
  3. Copy private RSA key if not already on the system i.e. ~/.ssh/id_rsa
  4. Set permissions on the private key if needed
    [codesyntax lang="bash"]

    chmod 0400 ~/.ssh/id_rsa

    [/codesyntax]

  5. Locate the jenkins-cli.jar
    [codesyntax lang="bash"]

    find . -type f -name 'jenkins-cli.jar'

    [/codesyntax]
    OR
    [codesyntax lang="bash"]

    updatedb && locate 'jenkins-cli.jar'

    [/codesyntax]

  6. Run java jenkins cli from Master or you could setup another box with the jar etc.
    [codesyntax lang="bash"]

    java -jar /var/cache/jenkins/war/WEB-INF/jenkins-cli.jar -i ~/.ssh/id_rsa -s http://localhost:8080 groovy /tmp/remove-old-builds.groovy

    [/codesyntax]

Groovy Script

[codesyntax lang="groovy"]

import jenkins.model.*
import hudson.model.*
import com.cloudbees.hudson.plugins.folder.*
import jenkins.branch.*
import org.jenkinsci.plugins.workflow.job.*
import org.jenkinsci.plugins.workflow.multibranch.*

/**
 * Utility function used to delete old builds.
 *
 * @param item the current Jenkins item to process, this can be a Folder or a Project
 * @param numberOfBuildsToKeep the total number of builds to keep. Please note that one more build could be
 *        kept if the first "numberOfBuildsToKeep" builds are all in a failed state.
 */

def deleteOldBuilds(item, Integer numberOfBuildsToKeep, Integer numberOfSuccessfulBuildsKept) {
    def count = 1

    println('Checking for Old Builds...')

    for (build in item.getBuilds()) {
        if(count++ >= numberOfBuildsToKeep) {
            if(item.getBuildStatusIconClassName() == 'icon-blue' && numberOfSuccessfulBuildsKept == 0) {
                println('Keep ' + build)
            } else {
                println('Deleting ' + build)
                build.delete()
            }
        } else if(item.getBuildStatusIconClassName() == 'icon-blue') {
            numberOfSuccessfulBuildsKept++
        }
    }
    println('PRIOR BUILD COUNT: (' + count + ')')
    println ''
}

def listJobObjects(item, Integer numberOfBuildsToKeep, Integer numberOfSuccessfulBuildsKept) {
    if(item instanceof Project) {
        println('PROJECT: (' + item.getName() + ')')
        deleteOldBuilds(item, numberOfBuildsToKeep, numberOfSuccessfulBuildsKept)
    } else if(item instanceof Folder) {
        println ''
        println('FOLDER: (' + item.getName() + ')')
        println('*************************************')
        for (subItem in item.items) {
            listJobObjects(subItem, numberOfBuildsToKeep, numberOfSuccessfulBuildsKept)
        }
    } else if(item instanceof WorkflowMultiBranchProject) {
        println('MULTIBRANCH-PROJECT: (' + item.getName() + ')')
        for (subItem in item.items) {
            listJobObjects(subItem, numberOfBuildsToKeep, numberOfSuccessfulBuildsKept)
        }
    }  else if(item instanceof WorkflowJob) {
        println('MULTIBRANCH-JOB: (' + item.getName() + ')')
        deleteOldBuilds(item, numberOfBuildsToKeep, numberOfSuccessfulBuildsKept)
    } else if(item instanceof OrganizationFolder) {
        println('ORG-FOLDER: (' + item.getName() + ')')
        for (subItem in item.items) {
            listJobObjects(subItem, numberOfBuildsToKeep, numberOfSuccessfulBuildsKept)
        }
    } else {
        println('UNKNOWN: (' + item.getName() + ')')
        println('CLASS: (' + item.getClass() + ')')
        println('INSPECT: (' + item.inspect() + ')')
    }
}

for (item in Jenkins.instance.items) {
    println ''
    listJobObjects(item, 10, 0)
    println('*************************************')
}

[/codesyntax]

Source: bonusbits