Jenkins declarative single pipeline if branch condition not working - jenkins

Using a single declarative pipeline (not multibranch pipeline)
Is there a way I can trigger a certain stage only if its the Master Branch ?
I've been unsuccessful with the following:
Stage('Deploy') {
steps {
script {
if (env.BRANCH_ENV == 'master') {
sh "mvn deploy"
} else {
echo 'Ignoring'
}
}
}
}
No matter what branch i'm deploying, everything gets ignored
any help or advice would be great

I had the same issue before and figured that env.BRANCH_ENV does not return what I expected. You can echo env.BRANCH_ENV in your pipeline to confirm.
My solution to this was to get the git branch manually:
scmVars = checkout scm
gitBranch = sh(
script: "echo ${scmVars.GIT_BRANCH} | cut -d '/' -f2",
returnStdout: true
).trim()

Here some approaches:
use return command to finalize prematurely the stage
https://stackoverflow.com/a/51406870/3957754
use when directive
when directive allows the Pipeline to determine whether the stage should be executed depending on the given condition
built-in conditions: branch, expression, allOf, anyOf, not etc.
when {
// Execute the stage when the specified Groovy expression evaluates to true
expression {
return params.ENVIRONMENT ==~ /(?i)(STG|PRD)/
}
}
Complete sample :
https://gist.github.com/HarshadRanganathan/97feed7f91b7ae542c994393447f3db4

Related

Jenkins stage not triggered even if changeset is correct

My jenkins file looks something like this:
options {
skipDefaultCheckout()
}
stages{
stage("Unit Test"){
when {
allOf{
expression {params.REPOSITORY_CREDENTIALS != null && params.TRG_BRANCH != null}
anyOf {
changeset pattern: "([a-zA-Z]*_cli|clarity_xml_tools)\\/.*", comparator: "REGEX"
changeset pattern: "jenkins\\/pipeline_scripts\\/.*", comparator: "REGEX"
}
}
}
steps{
container('omics-build-agent'){
echo "Stage triggered.."
}
}
post{
always{
echo "Stage completed.."
}
success{
echo "Unit Test completed successfully.."
}
failure{
echo "Unit Test Failed!!"
}
}
}
I checked the Changes in my jenkins build info:
jenkins/pipeline_scripts/build-Build_Python-clarity_xml_tools.sh
But my stage is still not getting triggered. What am I missing?
Note: I cannot remove skipDefaultCheckout() because I have 2 different repos who should be triggering my job when changes are pushed and they should be checked out to 2 different sub folders.
So my pipeline gets triggered by the Generic Webhook Plugin (which is working fine) from either of the 2 repo. So I had to force stop the default checkout and then use the checkout plugin for gitSCM to get my repos inside the stage.
Could it be because of this?

Jenkins: Schedule Particular Stage with single pipeline

I have a single pipeline where it' declarative and I've several stages such as below triggers via webhook.
I would like to execute and scheduled Stage B at a certain time which can also run without trigger via webhook. Clearly it needs to run when triggers via webhook and also run when it will be schedule. Can I handle this without creating seperate job or pipeline in Jenkins ?
stage('A'){
when{
beforeAgent true
expression{return env.GIT_BRANCH == "origin/development"}
}
steps{
script{
//Do something
}
stage ('B'){
when {
beforeAgent true
expression{return env.GIT_BRANCH == "origin/development"}
steps {
script {
//Run Tests
}
}
}
stage('C'){
when{
beforeAgent true
expression{return env.GIT_BRANCH == "origin/development"}
}
steps{
script{
//Do something
}
You can discover what caused your pipeline to run. This may be cron trigger, manual trigger, code commit trigger, webhook trigger, comment on GitHub, upstream job, etc. (depending on plugins installed, the list may be long.)
Here's and example of code to understand what the trigger was. This example sets the environment variable TRIGGERED_BY.
def checkForTrigger() {
def timerCause = currentBuild.rawBuild.getCause(hudson.triggers.TimerTrigger.TimerTriggerCause)
if (timerCause) {
echo "Build reason: Build was started by timer"
env.TRIGGERED_BY = 'timer'
return
}
def userCause = currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause)
if (userCause) {
echo "Build reason: Build was started by user"
env.TRIGGERED_BY = 'user'
return
}
def remoteCause = currentBuild.rawBuild.getCause(hudson.model.Cause$RemoteCause)
if (remoteCause) {
echo "Build reason: Build was started by remote script"
env.TRIGGERED_BY = 'webhook'
return
}
// etc.
println "We haven't caught any of triggers, might be a new one, here is the dump"
def causes = currentBuild.rawBuild.getCauses()
println causes.dump()
}
I think that a build might have more than one trigger, if so the order of your clauses is important.
Once you have this figured out, you can run your stages only when the trigger fits your definition.
stage ('B'){
when {
beforeAgent true
anyOf {
expression{return env.GIT_BRANCH == "origin/development"}
environment name: 'TRIGGERED_BY', value: 'timer'
environment name: 'TRIGGERED_BY', value: 'webhook'
}
Not in a clean or first-class manner, but yes you can do it effectively.
For any job which has been run at least once, you can click "replay" for the previous run.
You will then be presented with the Jenkinsfile in a text edit box. At this point you can perform any edit you want to the Jenkinsfile (including pasting in a completely unrelated Jenkinsfile if you wanted) and Jenkins will execute the modified version. For your specific case, you can delete all the stages you don't want to re-run and just leave behind the one (or two, etc) you want.

Despite skipDefaultCheckout true Jenkins still clones repository

Despite using skipDefaultCheckout true it still CLONES the git repo.
My goal is just to look for changes and then execute certain scripts.
I've run out of ideas. I tried this How to use SkipDefaultCheckout in a scripted pipeline, but I quess it doesn't work?
pipeline {
agent any
options {
skipDefaultCheckout true
}
environment {
branch = 'test'
}
stages {
stage('commit_stage') {
steps {
script {
properties([pipelineTriggers([pollSCM('*/5 * * * *')])])
git branch: "${branch}", credentialsId: 'test', url: 'https://gitlab.test.net/core/test.git'
sh '''
branch=${branch}
ssh bamboo#app-test.synchr.net "cd /opt/${branch}-8*/ && ./startup.sh status"
'''
}
//define scm connection for polling
}
}
}
}
Looks like you've just got the syntax wrong for the option. You've got:
options {
skipDefaultCheckout true
}
It should be
options {
skipDefaultCheckout()
}
Pipeline Syntax
The syntax is correct: https://groovy-lang.org/style-guide.html#_omitting_parentheses
Groovy allows this and Jenkinsfile is written in groovy.
I just stumble around this post and it didn't help me. My guess is that the checkout needs to be outside the script.

How to mark Jenkins' job stage as skipped, for scripted pipeline

How do I mark a stage as skipped when using scripted pipeline.
I have no problem skipping a stage in declarative pipeline. I just set
when {
expression {<some boolean expression>}
}
And if the expression is evaluate to false that stage is skipped.
The problem is that if you try to do this with scrippted pipeline you get:
java.lang.NoSuchMethodError: No such DSL method 'when' found among steps
error message. This is because the DSL of declarative pipeline is not the same as scripted pipeline
So, how can it be done?
Solving this issue takes a little bit of hacking... (don't worry, nothing fancy)
The way to do this is by using Jenkins' module that can be found here.
So to mark a stage as skipped you need to call static method markStageSkippedForConditional passing the name of the stage you are skipping.
Lets say you have a stage named "mystage". and you want to skip it and mark it as "skipped".
Your code should look something like:
import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
node() {
stage('a'){
echo 'stage 1'
}
stage('mystage'){
if(true){
echo 'skipping stage...'
Utils.markStageSkippedForConditional('mystage')
}else{
echo 'This stage may be skipped'
}
}
stage('b'){
echo 'stage 2'
}
}
If you're using a version of Jenkins older than mid 2019, you must uncheck Use Groovy Sandbox checkbox, since the Utils method was not yet whitelisted for external use.
You can find an implementation (in the form of a shared pipeline step) in comquent/imperative-when on GitHub.
This allows to access the method Utils.markStageSkippedForConditional that you found yourself in a nice way, like the following:
stage('Zero') {
when(BRANCH_NAME != 'master') {
echo 'Performing steps of stage Zero'
}
}
In declarative pipeline you can use:
stage('deploy') {
when { <some boolean expression> }
......
}
In Scripted pipeline you can use:
if(<some boolean expression>) {
stage('deploy') {
......
}
}
both above works fine. i tested

Using Jenkins to deploy to staging and production based on condition

My project has a Jenkinsfile that runs smoothly. The problem is that I need to run some commands only on certain occasions. I'm using the Github plugin. I need to run the deploy only when it is in the master or a new tag, one will be for staging and the other will be production.
pipeline {
agent any
stages {
stage('Test') {
steps {
sh 'node -v'
sh 'yarn install'
sh 'yarn test -- --coverage'
}
}
stage('Build') {
steps {
sh 'yarn build'
}
}
stage('Deploy') {
steps {
sh 'aws s3 sync ./build s3://my.bucket --only-show-errors'
}
}
}
}
I need the master to deploy to a bucket and when it is new tag to another. How can I create this conditional?
How about the following working as two conditionals for two separate deployment scenarios? I think it's better to work with this using variables to indicate deployment scenarios instead of splitting this to two distinctly different steps though. You could for example write a shell script that would handle everything inside depending on tags/branches/whatever you need instead of forcing yourself to control this on pipeline level.
Each stage will have it's steps executed only when when part is satisfied. Stage Deploy will only work for master branch, while stage Deploy_NonMaster will only work any non master branch. Using the method written in when conditionals you can check for anything, including tags or whatnot.
stage ('Deploy') {
when {
expression {
GIT_BRANCH = sh(returnStdout: true, script: 'git rev-parse --abbrev-ref HEAD').trim()
return (GIT_BRANCH == 'master')
}
}
steps {
echo 'Do stuff/deploy.'
}
}
stage ('Deploy_NonMaster') {
when {
expression {
GIT_BRANCH = sh(returnStdout: true, script: 'git rev-parse --abbrev-ref HEAD').trim()
return !(GIT_BRANCH == 'master')
}
}
steps {
echo 'Do stuff/deploy.'
}
}

Resources