| Dzizes dzizes I am using a workaround, but you may not like it. The workaround:
- You need to bottleneck all of your properties setting into a single call in the pipeline - you need set all of them always, not piecemeal. You can do it any way you like, the above is just one approach.
- In this call to the properties closure, you need to duplicate all the settings you've set when you initially created the job (any that you omit will be lost).
My example:
- All my jobs are generated via the Job DSL plugin, and the initial values for job properties (including parameters) are set there. (The resuls is the same as creating the job by hand)
- In addition to the normal pipeline code, I insert a block that sets properties{} at the top, this block duplicates all initially configured options.
- I make sure that the rest of the code never calls properties{} again.
Since I'm using the Job DSL plugin, I have it prepend the pipeline code with an extra chunk that takes care of all that. Here is a utility method I use in pipeline code. It covers all the properties that I ever set, and parameters (I only use string parameters) are supplied as an array in this format: ['NAME:DEFAULTVALUE:DESCRIPTION', etc]
/**
* This exists primarily because of a bug in Jenkins pipeline that causes
* any call to the "properties" closure to overwrite all job property settings,
* not just the ones being set. Therefore, we set all properties that
* the generator may have set when it generated this job (or a human).
*
* @param settingsOverrides a map, see defaults below.
* @return
*/
def setJobProperties(Map settingsOverrides = [:]) {
def settings = [discarder_builds_to_keep:'10', discarder_days_to_keep: '', cron: null, paramsList: [], upstreamTriggers: null, disableConcurrentBuilds: false] + settingsOverrides
// echo "Setting job properties. discarder is '${settings.discarder_builds_to_keep}' and cron is '${settings.cron}' (${settings.cron?.getClass()})"
def jobProperties = [
//these have to be strings:
buildDiscarder(logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: "${settings.discarder_days_to_keep}", numToKeepStr: "${settings.discarder_builds_to_keep}"))
]
if (settings.cron) {
jobProperties << pipelineTriggers([cron(settings.cron)])
}
if (settings.upstreamTriggers) {
jobProperties << pipelineTriggers([upstream(settings.upstreamTriggers)])
}
if (settings.disableConcurrentBuilds) {
jobProperties << disableConcurrentBuilds()
}
if (settings.paramsList?.size() > 0) {
def generatedParams = []
settings.paramsList.each { //params are specified as name:default:description
def parts = it.split(':', 3).toList() //I need to honor all delimiters but I want a list
generatedParams << string(name: "${parts[0]}", defaultValue: "${parts[1] ?: ''}", description: "${parts[2] ?: ''}", trim: true)
}
jobProperties << parameters(generatedParams)
}
echo "Setting job properties: ${jobProperties}"
properties(jobProperties)
}
So my job's pipeline definition looks like this:
setJobProperties(
//each of these is optional, you may simply need the paramsList and that's it.
discarder_builds_to_keep: "30",
//cron: "",
paramsList: ['SAMPLE_PARAM:apple:Some description'],
//upstreamTriggers: 'some-job',
//disableConcurrentBuilds: true
)
//now regular pipeline code...
If this doesn't fit your situation, there are plenty of other ways, just make sure to follow the two rules at the top. |