Jenkins conditional step for string contains - jenkins

I am trying to do a conditional step on Jenkins to see if the String Parameter contains a certain word.
I have a string for PLATFORM. The values in it can be Windows, Mac, Linux
I want to run a certain step if the value of the parameter contains Linux.
How can I do that? I downloaded the Jenkins plugin for conditional step but it doesn't have a contains clause.

You can use when directive of Jenkins to achieve the conditional steps.
Example:
pipeline {
agent any
stages {
stage ('Windows RUN') {
when {
expression { params.PLATFORM == 'Windows' }
}
steps {
echo "Hello, Windows"
}
}
stage ('Mac RUN') {
when {
expression { params.PLATFORM == 'Mac' }
}
steps {
echo "Hello, Mac"
}
}
stage ('Linux RUN') {
when {
expression { params.PLATFORM == 'Linux' }
}
steps {
echo "Hello, Linux"
}
}
}
}
Output:

Related

Specify agent in Jenkins Pipeline Shared Library

I am trying to customize a shared Library which run a stage in a specify agent by adding the possibility to specify the agent.
def call(String agentLabel) {
pipeline {
agent { label "$agentLabel" }
stages {
stage('Hello') { steps { echo 'Hello World' } }
}
}
}
This is OK but now I want to customize the type of agent (IE. either use label or docker agent) ?
This don't work :
def call(String agentLabel, String agentDockerImage = null) {
Closure agentRunner = null
if (agentDockerImage) {
agentRunner = {
docker {
label "$agentLabel"
image "$agentDockerImage"
}
}
} else {
agentRunner = {
label "$agentLabel"
}
}
pipeline {
agent { agentRunner.call() }
stages {
stage('Hello') { steps { echo 'Hello World' } }
}
}
}
WorkflowScript: 15: Invalid agent type "call" specified. Must be one of [any, docker, dockerfile, label, none] # line 15, column 29.
agent { agentRunner.call() }
^

Jenkins declarative pipeline expression with boolean environment variable

I'm using Jenkins declarative pipeline and I want to make a conditional step depending on an environment variable, which is set according the existence of a file.
So I just want to make something like that : if Dockerfile exist, perform next stage, else don't.
To perform this I tried :
pipeline {
// ...
stage {
stage('Docker') {
environment {
IS_DOCKERFILE = fileExists 'Dockerfile'
}
when {
environment name: 'IS_DOCKERFILE', value: true
}
stage('Build') {
// ...
}
}
}
}
Or :
pipeline {
// ...
stage {
stage('Docker') {
environment {
IS_DOCKERFILE = fileExists 'Dockerfile'
}
when {
expression {
env.IS_DOCKERFILE == true
}
}
stage('Build') {
// ...
}
}
}
}
In both cases, the Dockerfile exist and it is in the workspace. I also tried with strings ("true") but everytime, the pipeline continue without executing the stage 'Build'.
Any suggestions ?
This is because the exprsssion:
IS_DOCKERFILE = fileExists 'Dockerfile'
Creates the environment variable with boolean value as string:
$ set
IS_DOCKERFILE='false'
So the solution would be to use .toBoolean() like this:
environment {
IS_DOCKERFILE = fileExists 'Dockerfile'
}
stages {
stage("build docker image") {
when {
expression {
env.IS_DOCKERFILE.toBoolean()
}
}
steps {
echo 'fileExists'
}
}
stage("build libraries") {
when {
expression {
!env.IS_DOCKERFILE.toBoolean()
}
}
steps {
echo 'fileNotExists'
}
}
}
As #Sergey already posted, the problem is that you're comparing a string to a boolean. See fileExists: Verify if file exists in workspace.
Besides his answer, you can compare directly to a string:
environment {
IS_DOCKERFILE = fileExists 'Dockerfile'
}
stages {
stage("build docker image") {
when {
expression {IS_DOCKERFILE == 'true'}
}
steps {
echo 'fileExists'
}
}
stage("build libraries") {
when {
expression {IS_DOCKERFILE == 'false'}
}
steps {
echo 'fileNotExists'
}
}
}

How can I have one pipeline executed even if the other has failed in jenkins

I have the following (part of a) pipeline
stages {
stage('bootstrap') {
parallel {
stage("Linux") {
agent { label 'linux' }
steps {
sh 'bootstrap.sh'
}
}
stage("Windows") {
agent { label 'Windows' }
steps {
bat 'bootstrap.bat'
}
}
}
}
stage('devenv') {
parallel {
stage('Linux') {
agent { label 'linux' }
steps {
sh 'devenv.sh'
}
}
stage('Windows') {
agent { label 'Windows' }
steps {
bat 'devenv.bat'
}
}
}
}
}
post {
always {
echo "Done"
}
}
The problem is that when bootstrap.bat fails on windows, the devenv step is now considered failed, and the linux devenv won't continue. I would like to have the results of the linux pipeline even if the windows one fails early.
An option would be to separate the stages so that linux full pipeline is on one branch of the parallel execution, and windows is on the other, but maybe there's a trick I am not aware of, because I tried it and it does not seem to be acceptable syntax.
Edit
Suggested fix does not work. This is the pipeline
pipeline {
agent none
parallel {
stage('Linux') {
agent { label 'linux' }
stages {
stage('bootstrap') {
sh "ls"
}
stage('devenv') {
sh "ls"
}
}
}
stage('windows') {
agent { label 'Windows' }
stages {
stage('bootstrap') {
bat 'dir'
}
stage('devenv') {
bat 'dir'
}
}
}
}
}
This is the error message
WorkflowScript: 8: Undefined section "parallel" # line 8, column 5.
parallel {
^
WorkflowScript: 1: Missing required section "stages" # line 1, column 1.
pipeline {
^

Value returned from a script does not assigned to a variable declared in jenkins declarative pipeline stage

I am working on adding a jenkins Declarative pipeline for automation testing. In the test run stage i want to extract the failed tests from the log. i am using a groovy function for extracting the test result. this function is not a part of the jenkins pipeline. It is another script file. The function works fine and it build a string containing the failure details. Inside a pipeline stage i am calling this function and assinging the returned string to another variable. But when i echo the variable value it prints empty string.
pipeline {
agent {
kubernetes {
yamlFile 'kubernetesPod.yml'
}
}
environment{
failure_msg = ""
}
stages {
stage('Run Test') {
steps {
container('ansible') {
script {
def notify = load('src/TestResult.groovy')
def result = notify.extractTestResult("${WORKSPACE}/testreport.xml")
sh "${result}"
if (result != "") {
failure_msg = failure_msg + result
}
}
}
}
}
post {
always {
script {
sh 'echo Failure message.............${failure_msg}'
}
}
}
}
here 'sh 'echo ${result}'' print empty string. But 'extractTestResult()' returns a non-empty string.
Also i am not able to use the environment variable 'failure_msg' in post section it return an error 'groovy.lang.MissingPropertyException: No such property: failure_msg for class: groovy.lang.Binding'
can anyone please help me with this ?
EDIT:
Even after i fixed the string interpolation, i was getting the same
error. That was because jenkins does not allow using 'sh' inside
docker container. there is an open bug ticket in jenkins issue
board
I would suggest to use a global variable for holding the error message. My guess is that the variable is not existing in your scope.
def FAILURE_MSG // Global Variable
pipeline {
...
stages {
stage(...
steps {
container('ansible') {
script {
...
if (result != "") {
FAILURE_MSG = FAILURE_MSG + result
}
}
}
}
}
post {
always {
script {
sh "${FAILURE_MSG}" // Hint: Use correct String Interpolation
}
}
}
}
(Similar SO question can be found here)

Need Condition based Input Step in Jenkins pipeline script

I have three stages in jenkins pipeline script viz (1) precheck, (2) build-prod & (3) build-dr.
I have stated the input step for manual trigger at stage "build-dr"
My pipeline is condition based i.e based on user parameter in precheck stage .
Condition1: "precheck" -> "build-prod" and then "build-dr" is executed.
Condition2: "precheck" and then "build-dr" is executed (skips build-prod).
I need the input step in Condition1 and is working fine however the input step should not be executed for Condition2 i.e no popup msg with input step. Please let me know how can we put a condition around input step in stage 3 build-dr so it does not execute input step when the pipleline skips (2) build-prod.
Jenkins pipeline Script Code:
agent any
stages {
stage ("Pre-Check Parameters") {
steps {
echo "Pre-Check called in pipeline"
}
}
stage ("build-prod") {
when {
expression { params.region == 'prod_only' || params.region == 'prod_and_dr' }
}
steps {
build 'job4'
}
}
stage ("build-dr") {
input{
message "Proceed or Abort"
submitter "user1,admin"
parameters {
string(name:'username', defaultValue: 'user1', description: 'Username of the user pressing Ok')
}
}
when {
expression { params.region == 'dr_only' || params.region == 'prod_and_dr'}
}
steps {
build 'job5'
}
}
}
}
Kindly suggest.
You are currently using the input directive as described here but this prevents you to make this input conditional. You actually have to use the Input Step. Instead of adding the input field directly below the stage directive you move this into the steps block of your stage and add a script block around it to use if/else conditionals.
And take care to remove the curly brackets around you input step and to add a colon after each property.
What you have to do now is to adapt this line to your requirements:
if(Condition1 == true) Depenending on the value of your parameter.
stage("build-dr") {
when {
expression { params.region == 'dr_only' || params.region == 'prod_and_dr'}
}
steps {
script {
if(Condition1 == true) {
input message: "Proceed or Abort", submitter: "user1,admin",
parameters: [string(name:'username', defaultValue: 'user1', description: 'Username of the user pressing Ok')]
}
}
build 'job5'
}
}
Alternatively you can use an environment declaration block to declare a variable and assign a specific value to it if your second stage will be executed. But any environment value will always be typed as a String this is important for the if/else conditional. A good way to assign a value to the variable would be to add a post section to your second stage.
pipeline {
agent any
environment {
STAGE_2_EXECUTED = "0"
}
stages{
stage("....") {
steps {
....
}
}
stage("Second stage") {
when {
expression { /* Your condition */ }
}
steps {
....
}
post {
always {
script {
STAGE_2_EXECUTED = "1";
}
}
}
}
stage("Third Stage") {
steps {
script {
if(STAGE_2_EXECUTED == "1") {
input message: "Proceed or Abort", submitter: "user1,admin",
parameters: [string(name:'username', defaultValue: 'user1', description: 'Username of the user pressing Ok')]
}
}
build 'job5'
}
}
}
}

Resources