Jenkins multiple cron triggers with different build parameters - jenkins

I am using a parameterized cron in my Jenkins script to run with 2 different sets of build param - one would run every 5 mins in production, and every 15 minutes in staging. The production one is running every 5 mins, but the staging one is not running. Can someone please tell me what I might be missing?
properties([
pipelineTriggers([parameterizedCron(env.BRANCH_NAME != 'master' ? '''
H/5 * * * * % environment=production
H/15 * * * * % environment=staging''' : '')]),
parameters([
choice(name: 'environment', defaultValue: 'sandbox', choices: ['sandbox', 'staging', 'production'], description: "etc")
])
])
A made a slight modification as follows and surprisingly this time only the staging one is running
properties([
pipelineTriggers([parameterizedCron('''H/2 * * * * % environment=production'''), parameterizedCron('''H/4 * * * * % environment=staging''')]),
parameters([
choice(name: 'environment', defaultValue: 'sandbox', choices: ['sandbox', 'staging', 'production'], description: "etc")
])
])
I can't find the reason why either is working half-way only.
Can someone please tell me what can be changed to fix the issue?

It's possible that H/5 schedule overwrites the H/15 schedule because there is a conflict between them, so it's unclear what parameters should be used e.g. at 15th minute. (You probably want two runs with different parameters, but not clear if the plugin understands that.)
You can try specifying that exactly:
pipelineTriggers([parameterizedCron(env.BRANCH_NAME != 'master' ? '''
0,5,10,15,20,25,30,35,40,45,50,55 * * * * % environment=production
0,15,30,45 * * * * % environment=staging''' : '')]),

Looks like there is a known bug that's open https://issues.jenkins-ci.org/browse/JENKINS-49921. It's possible to space out the runs as suggested in the bug itself as a workaround.
This worked for me
pipelineTriggers([parameterizedCron('''
# Every 10 mins in production
*/10 * * * * %environment=production
# Every 22 minutes in staging
*/22 * * * * %environment=staging
''' : '')])

Related

How to trigger build periodically in pipeline with different environment varaiables in jenkinsfile?

i have here one pipeline that running test against app with specific environment variable and triggers at specific time.
what i want to do is to use the same pipeline to be executed periodically at different times but each build is with different environment variable.
here is sample of my jenkinsfile the run against only set of environment available at certain one time
pipeline {
environment {
mvnHome = tool name: 'myMvn', type: 'maven'
mvnCMD = "${mvnHome}/bin/mvn"
APP_NAME = 'test'
APP_PACKAGE = 'test1'
APP_ACTIVITY = 'test2'
}
agent {
node {
label 'master'
}
}
triggers {
cron('15 20 * * *')
}
stages {
stage('SCM Checkout') {
steps {
git(branch: 'APP', url: 'https://gitlab.test.ba/amrka/framework.git', poll: true, credentialsId: 'GitlabCred')
}
}
stage('Testing') {
steps {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh(label: 'Test Process', script: "${mvnCMD} test")
}
}
}
}
}
You can use parameterized-scheduler plugin. In Jenkins dashboard, goto
Manage Jenkins -> Manage Plugins -> Parameterized Scheduler.
To schedule a job at different times that needs to use different environments, you have to use the parameterized-scheduler plugin.
Parameter1
H/20 * * * * %Parameter1 where Parameter1 is your environment variable for a specific time you want.
Parameter2
H/30 * * * * %Parameter2 where Parameter2 is your a different environment variable for a specific time you want.
The parameters should be setup already for the parameterized-scheduler plugin to work. It can be used only for jobs with parameters.
Remember you have to have your parameters already setup because the plugin is visible only for jobs with parameters. See more documentation including usage examples in the README.

Run the Jenkins pipeline nightly and after every commit

We would like to run the Jenkins pipeline:
nightly, but only if there was any commit in the chosen branches (dev or master)
and after every commit
With the caveat that nightly build should also tigger additional step (long-running integration tests).
Is it possible? How can we configure this in Jenkinsfile?
So, your question boils down to several:
How can I run a nightly build?
How can I stop a build if no commits were made in the last 24 hours?
How can I run a "long-running" stage, but not always?
Let's address these one by one.
You can have a nightly build by using cron or parameterizedCron, if you install the ParameterizedCron plugin. As you seem to want to run your job in all the branches, this may look like e.g.
pipeline {
agent any
triggers {
// schedule a nightly build at random time after 0am on dev branch, 1am on master
cron(env.BRANCH_NAME == 'dev' ? '0 * * * *' : '')
cron(env.BRANCH_NAME == 'master' ? '1 * * * *' : '')
To address the other points, you need to know why your build is running. It may be triggered by a person, or cron, or a commit. Once you make sure it's cron that triggered the build, you may want to explore git log for the time of the latest commit.
def currentBuildReason() {
def timerCause = currentBuild.rawBuild.getCause(hudson.triggers.TimerTrigger.TimerTriggerCause)
if (timerCause) { echo "Build reason: Build was started by timer"; return "TIMER" }
timerCause = currentBuild.rawBuild.getCause(org.jenkinsci.plugins.parameterizedscheduler.ParameterizedTimerTriggerCause)
if (timerCause) { echo "Build reason: Build was started by parameterized timer"; return "TIMER" }
def userCause = currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause)
if (userCause) { echo "Build reason: Build was started by user"; return "USER" }
println "here are the causes"
echo "${currentBuild.buildCauses}"
return "UNKNOWN"
}
and later:
if ( currentBuildReason() == "TIMER" and env.BRANCH == "master" ) {
def gitLog = sh script: "git log", returnStdout: true
// look for the date, and stop the build
Finally, you can run steps on condition. One way to do it is to define a parameter for your job, indicating whether the integration tests should run. This will allow a person to run them even if not nightly, when they select the box. E.g.
pipeline {
parameters {
booleanParam(name: 'RUN_LONG_TEST', defaultValue: false,
description: "Should long-running tests execute?")
}
and later
stage('Integration tests') {
agent { node { label "integration_test_slave" }}
when {
beforeAgent true
expression {params.RUN_LONG_TEST}
}
steps {
// run integration test
}
}
To schedule the nightly with the param selected, you need the parameterizedCron plugin:
pipeline {
agent any
triggers {
// schedule a nightly build at random time after 0am on dev branch, 1am on master
parameterizedCron(env.BRANCH_NAME == 'dev' ? '0 * * * * % RUN_LONG_TEST=true' : '')
parameterizedCron(env.BRANCH_NAME == 'master' ? '1 * * * * % RUN_LONG_TEST=true'' : '')
Alternatively, you may disregard the parameter if only the nightlies should run it, and analyze the value of currentBuildReason(). When it equals to TIMER, these tests should run.

Jenkins Scripted Pipeline: different operations depending on which cron triggers

I have a scripted pipeline and I'd like to execute different operations:
every day: run tests
every weekend: run very long static analysis task
I know I can define multiple triggers with
properties(
pipelineTriggers([cron("0 12 * * *"), cron("* * * * 6")])
)
But I don't know how I can then define the job later
if (???) {
sh "run complex task"
} else if (???) {
sh "run tests"
}
How can I find out which of the cron rules triggered my task?
I believe you can't get to the cron information during the build. TimerTriggerCause contains only information that the build was triggered by timer.
node {
properties([
pipelineTriggers([cron("* * * * *")])
])
def timeTriggerCause = currentBuild.rawBuild.getCause(hudson.triggers.TimerTrigger.TimerTriggerCause)
println timeTriggerCause?.getShortDescription()
}
Couple of solutions:
Check date during the build
Use multiple pipelines. You can separate all the logic into one pipeline with boolean parameter (i.e. RunComplexTask). Other pipelines (triggered by timer) would call this pipeline and pass proper value for boolean parameter.
EDIT: I've added example of multiple pipeline setup
PIPELINE_RUN_COMPLEX_TASK:
node {
properties([pipelineTriggers([cron('* * * * 6')])])
build job: 'PIPELINE_MAIN', parameters: [booleanParam(name: 'RunComplexTask', value: true)]
}
PIPELINE_RUN_TESTS:
node {
properties([pipelineTriggers([cron('0 12 * * *')])])
build job: 'PIPELINE_MAIN', parameters: [booleanParam(name: 'RunComplexTask', value: false)]
}
PIPELINE_MAIN:
if(RunComplexTask.toBoolean())
{
echo "Running complex task"
}
else
{
echo "Running tests"
}
Pipeline main has this boolean parameter I've mentioned.

how to configure 2 jenkins pipeline trigger with environment variable

I have to pass parameter to a timeTrigger function in jenkins pipelineTrigger, but it's not taking that parameter. I have to schedule 2 builds, one for Dev every 8 hours, other for staging every 12 hours.
Question1: Can I trigger 2 builds this way?
Question2: How to pass parameter to specify environment?
See Code below
environmentParam = ['dev', 'qa', 'stg']
originParam = ['Automatic', 'Manual']
if (env.BRANCH_NAME == "master") {
properties([
[$class : 'ParametersDefinitionProperty',
parameterDefinitions:
[
[$class : 'ChoiceParameterDefinition',
choices : environmentParam.join('\n'),
description: 'Environment to run the Integration tests',
name : 'environment'
],
[$class : 'ChoiceParameterDefinition',
choices : originParam.join('\n'),
description: 'The execution of this job was Automatic or Manual',
name : 'origin'
]
]
],
pipelineTriggers(
[
[
$class: 'TimerTrigger', spec: 'H */12 * * *', environment: 'stg'
],
[
$class: 'TimerTrigger', spec: 'H */8 * * *', environment: 'dev'
]
]
),
disableConcurrentBuilds()
])
}
above code is not taking up environment, it is only triggering second entry in pipelineTriggers, not both. :-(
Answer for Questions 1: No, you cannot do it now.
The properties will be set to the jenkins job (config.xml) when pipeline script is executed. Therefore if multiple time trigger is not supported in normal jenkins job, your script will no work as expected as well.
Please execute it and check the jenkins job configuraion and config.xml to understand the result.
Suggestion
Change your solution in another logic (if it is still 8 & 12 hours)
trigger your job to run every 4 hours
keep both choice parameters.
try to have some logical check in steps to run the different stage in different time.
i think you'll have a better time if you create either two or three build plans instead of one.
if you created two, there would be one for dev and one for staging, and they would each have their own trigger and do the appropriate deployment.
if you had three, there would be one (let's call it the "deployment" build plan) that did deployments and that took an TARGET_ENVIRONMENT parameter or similar (with value dev or stg). The other two would have the triggers and they would each call the deployment build plan to do the actual work. you can call another build plan from a Jenkinsfile like this:
build job: 'deployment', parameters: [string(name: 'TARGET_ENVIRONMENT', value: 'dev')]

"Build Periodically" with a Multi-branch Pipeline in Jenkins

I'm running Jenkins 2 with the Pipeline plugin. I have setup a Multi-branch Pipeline project where each branch (master, develop, etc.) has a Jenkinsfile in the root. Setting this up was simple. However, I'm at a loss for how to have each branch run periodically (not the branch indexing), even when the code does not change. What do I need to put in my Jenkinsfile to enable periodic builds?
If you use a declarative style Pipeline and only want to trigger the build on a specific branch you can do something like this:
String cron_string = BRANCH_NAME == "master" ? "#hourly" : ""
pipeline {
agent none
triggers { cron(cron_string) }
stages {
// do something
}
}
Found on Jenkins Jira
If you are using a declarative style Jenkinsfile then you use the triggers directive.
pipeline {
agent any
triggers {
cron('H 4/* 0 0 1-5')
}
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
This is working for me:
triggers {
cron(env.BRANCH_NAME == 'development' ? 'H */12 * * *' : '')
}
See more in this article
I was able to find an example illustrating this an discarding old builds, which is also something I wanted.
Jenkinsfile in jenkins-infra/jenkins.io:
properties(
[
[
$class: 'BuildDiscarderProperty',
strategy: [$class: 'LogRotator', numToKeepStr: '10']
],
pipelineTriggers([cron('H/30 * * * *')]),
]
)
For Paramertized periodic runs or scheduled triggers, one could use as follows.
triggers{
parameterizedCron env.BRANCH_NAME == "develop" ? '''H 03 * * * % buildSlave=vm1;testSlave=vm2;HYPERVISOR=vbox;VERSION=10.5.0.0
H 03 * * * % buildSlave=vm1;testSlave=vm2;HYPERVISOR=workstation;VERSION=10.5.0.0''' : ""
}
I hit issues with the above solutions.
I'm not a Jenkins wizard so not sure if I am using an old format/syntax or something, but the following is working for me.
#!/usr/bin/env groovy
properties(
[
pipelineTriggers([
[
$class: 'TimerTrigger',
spec: 'H 7,19 * * *'
]
])
]
)
Determined from: https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/triggers/TimerTrigger.java

Resources