Jenkinsfile on multibranch pipeline cron - jenkins

I have a declarative pipeline for multibranch pipeline job, and I am interested in creating a cron trigger to it.
Currently I already have cron trigger on it for master branch using the following cron string:
String cron_string = BRANCH_NAME == "master" ? '30 23 * * *' : ""
I am interested in modifying the cron string so the cron would be triggered when branch name is master or if branch name contains the string release
I Wondered how can I achieve this
would appreciate your help.
Thanks in advance, Alon

def no_cron = ""
def some_cron = "30 23 * * *"
CRON_DATA = no_cron
if (BRANCH_NAME == "master" || BRANCH_NAME.contains("release")) {
CRON_DATA = some_cron
}
pipeline {
agent any
triggers {
cron (CRON_DATA)
}
...
}

Related

Jenkins - How to run a stage/function before pipeline starts?

We are using a Jenkins multibranch pipeline with BitBucket to build pull request branches as part of our code review process.
We wanted to abort any queued or in-progress builds so that we only run and keep the latest build - I created a function for this:
def call(){
def jobName = env.JOB_NAME
def buildNumber = env.BUILD_NUMBER.toInteger()
def currentJob = Jenkins.instance.getItemByFullName(jobName)
for (def build : currentJob.builds){
def exec = build.getExecutor()
if(build.isBuilding() && build.number.toInteger() != buildNumber && exec != null){
exec.interrupt(
Result.ABORTED,
new CauseOfInterruption.UserInterruption("Job aborted by #${currentBuild.number}")
)
println("Job aborted previously running build #${build.number}")
}
}
}
Now in my pipeline, I want to run this function when the build is triggered by the creation or push to a PR branch.
It seems the only way I can do this is to set the agent to none and then set it to the correct node for each of the subsequent stages. This results in missing environment variables etc. since the 'environment' section runs on the master.
If I use agent { label 'mybuildnode' } then it won't run the stage until the agent is free from the currently in-progress/running build.
Is there a way I can get the 'cancelpreviousbuilds()' function to run before the agent is allocated as part of my pipeline?
This is roughly what I have currently but doesn't work because of environment variable issues - I had to do the skipDefaultCheckout so I could do it manually as part of my build:
pipeline {
agent none
environment {
VER = '1.2'
FULLVER = "${VER}.${BUILD_NUMBER}.0"
PROJECTPATH = "<project path>"
TOOLVER = "2017"
}
options {
skipDefaultCheckout true
}
stages {
stage('Check Builds') {
when {
branch 'PR-*'
}
steps {
// abort any queued/in-progress builds for PR branches
cancelpreviousbuilds()
}
}
stage('Checkout') {
agent {
label 'buildnode'
}
steps {
checkout scm
}
}
}
}
It works and aborts the build successfully but I get errors related to missing environment variables because I had to start the pipeline with agent none and then set each stage to agent label 'buildnode' to.
I would prefer that my entire pipeline ran on the correct agent so that workspaces / environment variables were set correctly but I need a way to trigger the cancelpreviousbuilds() function without requiring the buildnode agent to be allocated first.
You can try combining the declarative pipeline and the scripted pipeline, which is possible.
Example (note I haven't tested it):
// this is scripted pipeline
node('master') { // use whatever node name or label you want
stage('Cancel older builds') {
cancel_old_builds()
}
}
// this is declarative pipeline
pipeline {
agent { label 'buildnode' }
...
}
As a small side comment, you seem to use: build.number.toInteger() != buildNumber which would abort not only older builds but also newer ones. In our CI setup, we've decided that it's best to abort the current build if a newer build has already been scheduled.

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.

Repo URL of all jobs through jenkins groovy

Is it possible to get the git scm url for a Jenkins job with groovy in the Jenkins script console?
Yes it's possible:
item = Jenkins.instance.getItemByFullName("JOB_NAME")
println item.getScm().getUserRemoteConfigs()[0].getUrl()
If you want to iterate over all jobs that support Git you can use following script:
Jenkins.instance.getAllItems(hudson.model.AbstractProject.class).each {it ->
scm = it.getScm()
if(scm instanceof hudson.plugins.git.GitSCM)
{
println scm.getUserRemoteConfigs()[0].getUrl()
}
}
println "Done"

"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