Skip to content

Instantly share code, notes, and snippets.

@0x1b-xyz
Created March 20, 2013 19:26
Show Gist options
  • Save 0x1b-xyz/5207665 to your computer and use it in GitHub Desktop.
Save 0x1b-xyz/5207665 to your computer and use it in GitHub Desktop.
Script that will clean up orphaned or unused workspaces on all slaves. There are a few environment specific tweaks in the script you may need to remove: 1- We use the Cloudbees folders plugin - if you don't then you'll need to refactor to remove folder support 2- Our standard slave names are prefixed with "worker-" and this script will ignore an…
import hudson.node_monitors.*
import hudson.slaves.*
import hudson.model.*
def hudson = Hudson.instance
hudson.slaves.findAll { it.name.startsWith("worker-") }.each { slave ->
println "\n\nExamining ${slave.name} workspaces ..."
def wsRoot = slave.getWorkspaceRoot()
def space = DiskSpaceMonitor.DESCRIPTOR.get(slave.computer)
println "[${slave.name}] Got path ${wsRoot} and size ${space}"
if (!wsRoot || !space) return
wsRoot.list().each { dir ->
processDispatch(slave, hudson.getItem(dir.name), dir)
}
}
def processFolder(slave, folder, dir) {
println "[${slave.name}] Processing folder: ${folder.fullName}"
dir.list().each { subdir ->
processDispatch(slave, folder.getItem(subdir.name), subdir)
}
}
def processProject(slave, proj, dir) {
println "[${slave.name}] Examining project ${proj.name}"
printDetails(slave, proj, dir)
def age = new Date() - new Date(dir.lastModified())
if (age > 1) { doDelete(slave, proj, dir) }
}
def processDispatch(slave, item, dir) {
if (!item) {
println "[${slave.name}] ${dir.name}, has no Hudson object, will delete"
return processDeadDir(slave, dir)
} else {
if (item instanceof AbstractProject)
return processProject(slave, item, dir)
else if (item instanceof com.cloudbees.hudson.plugins.folder.Folder)
return processFolder(slave, item, dir)
}
println "[${slave.name}] ERROR: Dunno what to do with ${dir.getRemote()} on ${slave.name}"
}
def printDetails(slave, proj, dir) {
def age = new Date() - new Date(dir.lastModified())
def lastBuiltOn = proj.getLastBuiltOn()
def where = lastBuiltOn instanceof DumbSlave ? lastBuiltOn.name : lastBuiltOn
def blocked = proj.getCauseOfBlockage()
println "[${slave.name}] workspace: ${dir.name}, age: ${age} days, last built on: ${where}, blocked: ${blocked?.shortDescription ?: 'nope'}"
}
def doDelete(slave, proj, dir) {
if (proj.scm.processWorkspaceBeforeDeletion(proj, dir, slave)) {
println "[${slave.name}] => deleting: ${dir} on ${slave.name}"
dir.deleteRecursive()
} else {
println "[${slave.name}] => NOT deleting: ${dir} on ${slave.name}"
}
}
def processDeadDir(slave, dir) {
println "[${slave.name}] => deleting dead directory: ${dir} on ${slave.name} "
dir.deleteRecursive()
}
@0x1b-xyz
Copy link
Author

Too bad this doesn't work with multibranch jobs ...

They didn't exist in 2012.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment