At Apaches Hudson installation I have sometimes seen the situation where too many builds are stuck and therefore blocking the executors. And sadly for me – the executors my own jobs require …
Having a policy to use the „build timeout plugin“ and kill jobs which are running too long (thinking more of „not running any more“ 😉 is good. But having a program which checks this is better …
So I tried a little bit Groovy’in for the Groovy console:
hudsonInstance = hudson.model.Hudson.instance
allItems = hudsonInstance.items
activeJobs = allItems.findAll{job -> job.isBuildable()}
wrappableJobs = activeJobs.findAll{job -> job instanceof hudson.model.BuildableItemWithBuildWrappers}
jobsWithoutTimeout = wrappableJobs.findAll { job ->
job.getBuildWrappersList().findAll{it instanceof hudson.plugins.build_timeout.BuildTimeoutWrapper }[0] == null
}
println "There are $jobsWithoutTimeout.size jobs without timeout:"
jobsWithoutTimeout.each { println "- $it.name" }
x = ""
In line 1 we get the reference to the Hudson singleton. Then we get the list of all item in line 2 which we filter in line 3 to get only buildable items, like our jobs. The line 4 contains the first thing special to this requirement: the item must be able to have a BuildWrapper.
But the most thing is done in line 5 which filters again with a closure: get all BuildWrappers for the job, but only if it is our TimeOut-Plugin. Because it can be registered only once, I check the first element of that list. It must be null for being a problem. Otherwise the job has a timeout setting.
After that, the last two lines are simply out … and the last line supresses the result output in the console.
Update:
Antoine Tulme had consulted Kohsuke Kawaguchi and he sees three possibilities of forcing the timeout setting:
- We cannot make the timeout field mandatory.
- We can create a plugin that presets the timeout field.
- We can iterate over the projects and set a value for the timeouts en masse.
Good, so I evaluate my „iteration solution“ a little more.
We have a list of all jobs without settings and so we only have to iterate over this list, instantiate and initialize the BuildTimeoutWrapper and add it to the jobs wrapper-list:
jobsWithoutTimeout.each { job ->
defaultTimeout = 180
defaultFailBuild = false
plugin = new hudson.plugins.build_timeout.BuildTimeoutWrapper(defaultTimeout, defaultFailBuild)
job.getBuildWrappersList().add(plugin)
}
BTW – If you want to work with a plugin, you could start with the Create Job Advances Plugin – maybe this requires code enhancement … and it will only for future jobs, not for existing one.
Update:
The last update of the script for setting the timeout value is this:
hudsonInstance = hudson.model.Hudson.instance
allItems = hudsonInstance.items
activeJobs = allItems.findAll{job -> job.isBuildable()}
defaultFailBuild = true
println "Cur | Est | Name"
activeJobs.each { job ->
// Get the Timeout-PlugIn
wrapper = job.getBuildWrappersList().findAll{it instanceof hudson.plugins.build_timeout.BuildTimeoutWrapper }[0]
// Get the current Timeout, if any
currentTimeout = (wrapper != null) ? wrapper.timeoutMinutes : ""
// Calculate a new timeout with a min-value
defaultTimeout = Math.round(job.estimatedDuration * 2 / 1000 / 60)
if (defaultTimeout < 10) defaultTimeout = 10
// Update the timeout, maybe requires instantiation
action = (wrapper != null) ? "updated" : "established"
if (wrapper == null) {
plugin = new hudson.plugins.build_timeout.BuildTimeoutWrapper(defaultTimeout, defaultFailBuild)
job.getBuildWrappersList().add(plugin)
} else {
wrapper.timeoutMinutes = defaultTimeout
}
// String preparation for table output
String defaultTimeoutStr = defaultTimeout
defaultTimeoutStr = defaultTimeoutStr.padLeft(5)
String currentTimeoutStr = currentTimeout
currentTimeoutStr = currentTimeoutStr.padLeft(5)
String jobname = job.name.padRight(40)
// Table output
println "$currentTimeoutStr | $defaultTimeoutStr | $jobname | $action "
}
x = ""
This updates all timeout settings and reports this like here:
