Here's my Jenkins pipeline where I'm trying to to run a conditional statement on the basis of previous command's exit code.
pipeline{
agent any
stages{
stage('Test exitcode'){
steps{
script{
EX_CODE = sh(
script: 'echo hello-world',
returnStatus: true
)
if( env.EX_CODE == 0 ){
echo "Code is good with $EX_CODE"
}else{
echo "Code is Bad with $EX_CODE"
}
}
}
}
}
}
Here's its output
Started by user Yatharth Sharma
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/devops/syntax-testing-pipeline
[Pipeline] { (hide)
[Pipeline] stage
[Pipeline] { (Test exitcode)
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ echo hello-world
hello-world
[Pipeline] echo
Code is Bad with 0
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
I was expecting this to return Code is good but this prints out Code is Bad. Can someone help me here with a why?
You are assigning the int return of the exit code from the shell interpreter command from the sh step method to a variable EX_CODE. You then attempt to access the value from the env object member in the conditional as if it were an environment variable instead of a variable. You can either modify the variable to be an environment variable, or access the variable directly (simpler).
EX_CODE = sh(script: 'echo hello-world', returnStatus: true)
if (EX_CODE == 0) {
echo "Code is good with ${EX_CODE}"
}
else{
echo "Code is Bad with ${EX_CODE}"
}
Related
I am New to Jenkins. Trying to create one basic Pipeline which is using choicebased parameters. Following is my script.
Code ----
pipeline{
agent {
label 'agent'
}
parameters {
choice choices: ['John', 'Stacy'], description: 'Choose one', name: 'Person'
}
stages {
stage('Print') {
steps {
echo "Hello ${params.Person}"
sh """if (${params.Person} = "John")
then
echo "Person is male."
else
echo "Person is female."
fi"""
}
}
}
}
Now my build complete successfully regardless of whatever option I choose. It always display result "Person is female.
Following is result of one of my build.
Started by user ****
[Pipeline] Start of Pipeline
[Pipeline] node
Running on agent in
/home/temp/jenkins_agent/workspace/ChoiceBased PL
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Print)
[Pipeline] echo
Hello John
[Pipeline] sh
+ John = John
/home/temp/jenkins_agent/workspace/ChoiceBased PL#tmp/durable-
b7e98c46/script.sh: 1: John: not found
+ echo Person is female.
Person is female.
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: Success
Please suggest what I am missing ?
I would change this just to be in Groovy rather than doing the compare in sh
stage('Print') {
steps {
echo "Hello ${params.Person}"
script {
if (params.Person == "John") {
echo "Person is male."
} else {
echo "Person is female."
}
}
}
}
Then when you choose Stacey you will get
[Pipeline] echo
Hello Stacy
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Person is female.
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
Trying to assign user input from 1 stage to use in another stage , thought to do it with env variables but cant figure it out
code so far :
environment {
access_key =''
}
stages {
stage('User input for Auth'){
input {
message 'enter access_key'
parameters {
string 'access_key_input'
string 'secret_key_input'
}
}
environment {
access_key = sh(script:"echo ${access_key_input}", returnStdout: true).trim()
}
steps{
sh "echo ${env.access_key}"
}
}
stage("Build") {
steps {
sh "echo ${env.access_key}"
}
}
}
logs :
+ echo XXX
+ echo XXX
XXX
+ echo null
null
You can assign the input to a global variable and then access that wherever you want.
def INPUT_PARAMS = null
pipeline {
agent {
node {
label 'any'
}
}
options {
timestamps()
}
stages {
stage('User input for Auth') {
steps{
script {
INPUT_PARAMS = input message: "enter access_key", parameters: [
string(description: 'Access key', defaultValue: '', name: 'access_key_input'),
string(description: 'Secret access key', defaultValue: '', name: 'secret_key_input')
]
}
sh "echo ${INPUT_PARAMS.access_key_input}"
}
}
stage("Build") {
steps {
sh "echo ${INPUT_PARAMS.access_key_input}"
}
}
}
}
Input request
Output
Started by user Praveen Premaratne
Replayed #152
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on devops-jenkins in /home/jenkins/workspace/Test
[Pipeline] {
[Pipeline] timestamps
[Pipeline] {
[Pipeline] stage
[Pipeline] { (User input for Auth)
[Pipeline] script
[Pipeline] {
[Pipeline] input
[2021-07-15T22:35:33.625Z] Input requested
[2021-07-15T22:35:43.540Z] Approved by Praveen Premaratne
[Pipeline] }
[Pipeline] // script
[Pipeline] sh
[2021-07-15T22:35:43.886Z] + echo a
[2021-07-15T22:35:43.886Z] a
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Build)
[Pipeline] sh
[2021-07-15T22:35:44.230Z] + echo a
[2021-07-15T22:35:44.230Z] a
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // timestamps
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
I'm new to Groovy. I'm not able to figure out what's wrong here.
Depends on the choice of input, I expect the script to execute either Step 'Hello' or 'Bye' but it skips both. I mostly orientated to this Jenkins pipeline conditional stage using "When" for choice parameters, but still can't figure it out.
How can I use those choice parameters correctly?
pipeline {
agent any
stages {
stage('Init') {
steps('Log-in'){
echo 'Log-in'
}
}
stage('Manual Step') {
input {
message "Hello or Goodbye?"
ok "Say!"
parameters{choice(choices:['Hello','Bye'], description: 'Users Choice', name: 'CHOICE')}
}
steps('Input'){
echo "choice: ${CHOICE}"
echo "choice params.: " + params.CHOICE //null
echo "choice env: " + env.CHOICE //Hello
}
}
stage('Hello') {
when{ expression {env.CHOICE == 'Hello'}}
steps('Execute'){
echo 'Say Hello'
}
}
stage('Bye') {
when{ expression {env.CHOICE == 'Bye'}}
steps('Execute'){
echo 'Say Bye'
}
}
}
}
Output:
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Init)
[Pipeline] echo
Log-in
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Manual Step)
[Pipeline] input
Input requested
Approved by Admin
[Pipeline] withEnv
[Pipeline] {
[Pipeline] echo
choice: Hello
[Pipeline] echo
choice params.: null
[Pipeline] echo
choice env: Hello
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Hello)
Stage "Hello" skipped due to when conditional
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Bye)
Stage "Bye" skipped due to when conditional
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
From the docs:
Any parameters provided as part of the input submission will be available in the environment for the rest of the stage.
This means that your parameter CHOICE does not exist in the other stages. If you want to have a parameter that's available on all the stages, you can define a parameter outside of the stage, i.e.:
pipeline {
agent any
parameters {
choice(choices:['Hello','Bye'], description: 'Users Choice', name: 'CHOICE')
}
stages {
stage('Init') {
steps('Log-in') {
echo 'Log-in'
}
}
stage('Manual Step') {
steps('Input') {
echo "choice: ${CHOICE}"
echo "choice params.: " + params.CHOICE
echo "choice env: " + env.CHOICE
}
}
stage('Hello') {
when {
expression { env.CHOICE == 'Hello' }
}
steps('Execute') {
echo 'Say Hello'
}
}
stage('Bye') {
when {
expression {env.CHOICE == 'Bye'}
}
steps('Execute'){
echo 'Say Bye'
}
}
}
}
This will behave as expected. The difference is that the job won't ask you for input, instead, you will provide the wanted parameters before pressing build.
may I ask if it is do-able if I can get the user input and run a script based on what was chosen by the user? the logic whould be
IF User choose Proceed THEN run a script (in my case promote or Blue/Green deployment)
IF User choose Abort THEN don't terminate the jenkins job, run a script (in my case rollback)
This is the script I'm using however I have no idea how to apply after validate stage
pipeline {
agent any
stages {
stage('Deploy') {
steps {
sh """#!/bin/bash +x
echo "performing sts assume role"
//SCRIPT-HERE//
echo "performing ansible deploy"
//SCRIPT-HERE//
"""
}
}
stage('validate') {
steps {
timeout(30) {
script {
input(message: 'Please validate, this job will automatically ABORTED after 30 minutes even if no user input provided', ok: 'Proceed')
}
}
}
}
}
}
One more issue I'm seeing is, although this pipeline script is running, The Proceed / Abort is not clickable on the jenkins job Console output, is it a bug? I'm referring to the image shown below
I was able to add nandilov's suggestion however it seems that the logic is still not applying, please advise on what is missed here
pipeline {
agent any
stages {
stage('Deploy') {
steps {
sh """#!/bin/bash +x
echo "performing sts assume role"
echo "performing ansible deploy"
"""
}
}
stage('validate') {
steps {
script {
env.flagError = "false"
try {
input(message: 'Please validate, this job will automatically ABORTED after 30 minutes even if no user input provided', ok: 'Proceed')
}catch(e){
println "input aborted or timeout expired, will try to rollback."
env.flagError = "true"
}
}
}
}
stage("If user selects Proceed"){
when{
expression { env.inputValue == "value1" }
}
steps{
sh """#!/bin/bash +x
echo "User selected proceed"
"""
}
}
stage("rollback if flag error true"){
when{
expression { env.inputValue == "value2" }
}
steps{
sh """#!/bin/bash +x
echo "User selected Abort"
"""
}
}
}
}
from the pipeline view it never triggered either one of the last two stages when choosing "Abort" or "Proceed"
These are the logs when choosing Abort or Proceed
ABORT
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/test-job-lagot
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Deploy)
[Pipeline] sh
performing sts assume role
performing ansible deploy
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (validate)
[Pipeline] script
[Pipeline] {
[Pipeline] input
Please validate, this job will automatically ABORTED after 30 minutes even if no user input provided
Proceed or Abort
[Pipeline] echo
input aborted or timeout expired, will try to rollback.
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (If user selects Proceed)
Stage "If user selects Proceed" skipped due to when conditional
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (rollback if flag error true)
Stage "rollback if flag error true" skipped due to when conditional
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
PROCEED
Started by user lagot
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/test-job-lagot
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Deploy)
[Pipeline] sh
performing sts assume role
performing ansible deploy
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (validate)
[Pipeline] script
[Pipeline] {
[Pipeline] input
Please validate, this job will automatically ABORTED after 30 minutes even if no user input provided
Proceed or Abort
Approved by lagot
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (If user selects Proceed)
Stage "If user selects Proceed" skipped due to when conditional
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (rollback if flag error true)
Stage "rollback if flag error true" skipped due to when conditional
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
If you want to have the job aborted and do something, you can try/catch it:
try{
input(message: 'Please validate, this job will automatically ABORTED after 30 minutes even if no user input provided', ok: 'Proceed')
}catch(e){
println "input aborted or timeout expired, will try to rollback."
// execute rollback
}
You also can do it in another stage:
pipeline {
agent any
stages {
stage('Deploy') {
steps {
sh """#!/bin/bash +x
echo "performing sts assume role"
echo "performing ansible deploy"
"""
}
}
stage('validate') {
steps {
script {
env.flagError = "false"
try {
input(message: 'Please validate, this job will automatically ABORTED after 30 minutes even if no user input provided', ok: 'Proceed')
}catch(e){
println "input aborted or timeout expired, will try to rollback."
env.flagError = "true"
}
}
}
}
stage("If user selects Proceed"){
when{
expression { env.flagError == "false" }
}
steps{
sh """#!/bin/bash +x
echo "User selected proceed"
"""
}
}
stage("rollback if flag error true"){
when{
expression { env.flagError == "true" }
}
steps{
sh """#!/bin/bash +x
echo "User selected Abort"
"""
}
}
}
Try with this, you will need to click on Proceed and then to choose between "deploy" and "rollback". The result we'll be store in an environment variable and you can use it as a condition on the next stages
stage('validate') {
steps {
timeout(30) {
script {
CHOICES = ["deploy", "rollback"];
env.yourChoice = input message: 'Please validate, this job will automatically ABORTED after 30 minutes even if no user input provided', ok : 'Proceed',id :'choice_id',
parameters: [choice(choices: CHOICES, description: 'Do you want to deploy or to rollback?', name: 'CHOICE'),
string(defaultValue: 'rollback', description: '', name: 'rollback value')]
}
}
}
}
}
stage('Deploy') {
when {
expression { env.yourChoice == 'deploy' }
}
steps {
...
}
}
stage('Rollback') {
when {
expression { env.yourChoice == 'rollback' }
}
steps {
...
}
}
I am trying to set environment variable in Jenkinsfile following way,
pipeline {
agent { label 'slave1' }
stages {
stage ('Build') {
steps {
script {
BUILD_VERSION = sh (
script: 'python get_firmware_version.py',
returnStdout: true
).trim()
}
echo "${BUILD_VERSION}"
withCredentials([file(credentialsId: 'image-sign', variable: 'IMAGE_SIGN')]) {
dir('firmware/') {
echo "${BUILD_VERSION}"
sh '''
echo "Building"
echo "${BUILD_VERSION}"
echo "${env.BUILD_VERSION}"
'''
}
}
}
}
}
post {
failure {
script {
echo "Pipeline Failed"
}
}
}
}
But its failing with following error Bad substitution
[Pipeline] echo
0_2_0
[Pipeline] sh
+ echo Building
Building
/home/jenkins/jenkins_slave/workspace/Firmware/Branch/firmware#tmp/durable-54e04481/script.sh: 3: /home/jenkins/jenkins_slave/workspace/Firmware/Branch/firmware#tmp/durable-54e04481/script.sh: Bad substitution
Why I can't set ENV Var and use it in sh step ?
This is Jenkins thing I think. When you use the sh block with '; it will not have access to things like environment variables. Try using the " instead. That should work
sh """
echo "Building"
echo "${env.BUILD_VERSION}"
echo "${env}"
"""
Jenkins should recognise the shell block and escape the " within the """ automatically.
pipeline {
agent { label 'slave1' }
stages {
stage ('Build') {
steps {
script {
BUILD_VERSION = sh (
script: 'python get_firmware_version.py',
returnStdout: true
).trim()
}
echo "${BUILD_VERSION}"
withCredentials([file(credentialsId: 'image-sign', variable: 'IMAGE_SIGN')]) {
dir('firmware/') {
echo "${BUILD_VERSION}"
sh """
echo "Building"
echo "${BUILD_VERSION}"
echo "${env.BUILD_VERSION}"
"""
}
}
}
}
}
post {
failure {
script {
echo "Pipeline Failed"
}
}
}
}
My test case
pipeline {
agent {
node {
label 'devops-jenkins-slave'
}
}
options {
timestamps()
}
stages {
stage('Setup'){
steps {
dir("${WORKSPACE}/"){
script {
BUILD_VERSION = "1"
}
sh """
echo "${BUILD_VERSION}"
"""
}
}
}
}
post {
always {
dir("${WORKSPACE}/"){
deleteDir()
}
}
}
}
Result
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] node
Running on devops-jenkins-slave in /home/jenkins/workspace/Samples/Test
[Pipeline] {
[Pipeline] timestamps
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Setup)
[Pipeline] dir
22:09:55 Running in /home/jenkins/workspace/Samples/Test
[Pipeline] {
[Pipeline] script
[Pipeline] {
[Pipeline] }
[Pipeline] // script
[Pipeline] sh
22:09:56 [Test] Running shell script
22:09:56 + echo 1
22:09:56 1
[Pipeline] }
[Pipeline] // dir
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Declarative: Post Actions)
[Pipeline] dir
22:09:56 Running in /home/jenkins/workspace/Samples/Test
[Pipeline] {
[Pipeline] deleteDir
[Pipeline] }
[Pipeline] // dir
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // timestamps
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS