For scripted pipelines, this feature is poorly implemented out-of-the-box (as of 2019).
The Ugly
The simplest way to do it (e.g. for the schedule "H 10 * * *"
) is to put the following in your Jenkinsfile
:
node {
properties([
pipelineTriggers([cron("H 10 * * *")])
])
}
In BlueOcean, every branch and every pull request counts as its own job -- so if you follow standard git workflow, the above code will create no less than three cron jobs:
- The feature branch you push, even though it hasn't been merged
- The pull request branch, whether or not you merge it
- The master branch (if/when you merge the feature branch)
There is no way to undo this damage unless you push more commits to the feature branch and keep the pull request open under the same number -- otherwise you will be configuring a different job than the one with the cron script. You can only fix it in the Jenkins console, since (as you noted), the BlueOcean setup will block your access to the job settings like it would in the non-BlueOcean Jenkins UI.
The Bad
A slightly smarter way to do it is to make the schedule depend on what branch is being used.
def mySchedule = BRANCH_NAME == "master" ? "H 10 * * *" : ""
node {
properties([
pipelineTriggers([cron(mySchedule)])
])
}
This can avoid "The Ugly" situation, but it can't undo any previous damage. It certainly can't stop anyone from removing the conditional in their own pull request (i.e. from accidentally or unwittingly going back to "The Ugly").
The Good
The safe way to do this requires accessing the Jenkins API directly:
import hudson.triggers.TimerTrigger
// v-- a Map of jobName to schedule string
def setCron(whitelistedCronSchedules = [:])
// only apply cron settings when running on master -- i.e. on merge to master
if ("${env.BRANCH_NAME}" == MASTER_BRANCH) {
// navigate up to the parent job, then iterate over all its child jobs,
// setting timers from the whitelist as we go
def thisJob = Jenkins.get().getItemByFullName(env.JOB_NAME)
for (Item ajob in thisJob.getParent().getAllJobs()) {
// you could optionally check ajob.getTriggers()[0].spec to see
// if the schedule is already set to what you want it to be
// get job schedule from the whitelist, or null if there is none
def jobName = java.net.URLDecoder.decode(ajob.getName(), "UTF-8")
def mySchedule = whitelistedCronSchedules.get(jobName, null)
// Triggers are set all at once: no triggers, or just one with our schedule
def triggersToSet = mySchedule == null ? [] : [new hudson.triggers.TimerTrigger(mySchedule)]
ajob.setTriggers(triggersToSet)
}
}
}
node {
// example usage:
setCron(["master": "H 10 * * *"]) // turns on cron for just the master branch, off for all others
// alternately,
setCron() // turns off cron for ALL jobs for this repo
}