Access a Groovy variable from within shell step in Jenkins pipeline - jenkins

Using the Pipeline plugin in Jenkins 2.x, how can I access a Groovy variable that is defined somewhere at stage- or node-level from within a sh step?
Simple example:
node {
stage('Test Stage') {
some_var = 'Hello World' // this is Groovy
echo some_var // printing via Groovy works
sh 'echo $some_var' // printing in shell does not work
}
}
gives the following on the Jenkins output page:
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Test Stage)
[Pipeline] echo
Hello World
[Pipeline] sh
[test] Running shell script
+ echo
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
As one can see, echo in the sh step prints an empty string.
A work-around would be to define the variable in the environment scope via
env.some_var = 'Hello World'
and print it via
sh 'echo ${env.some_var}'
However, this kind of abuses the environmental scope for this task.

To use a templatable string, where variables are substituted into a string, use double quotes.
sh "echo $some_var"

I am adding the comment from #Pedro as an answer because I think it is important.
For sh env vars we must use
sh "echo \$some_var"

You need to do something like below if a bash script is required :
Set this variable at global or local(function) level where from these can be accessible to sh script:
def stageOneWorkSpace = "/path/test1"
def stageTwoWorkSpace = "/path/test2"
In shell script call them like below
sh '''
echo ''' +stageOneWorkSpace+ '''
echo ''' +stageTwoWorkSpace+ '''
cp -r ''' +stageOneWorkSpace+'''/qa/folder1/* ''' +stageOneWorkSpace+'''/qa/folder2
'''
Make sure you start and end sh with three quotes like '''

I would like to add another scenario to this discussion.
I was using shell environment variables and groovy variables in the same script.
format='html'
for file in *.txt;
do mv -- "\$file" "\${file%.txt}.$format";
done
So here, What I have done is use \$ only for shell environment variables and use $ for groovy variables.

This is extension to #Dave Bacher's answer. I'm running multiple shell command in Groovy file & want to use output of one shell command to the next command as groovy variable. Using double quotes in shell command, groovy passes variable from one to another command but using single quotes it does not work, it returns null.
So use shell command like this in double quotes: sh "echo ${FOLDER_NAME}"
FOLDER_NAME = sh(script: $/
awk -F '=' '/CODE_COVERAGE_FOLDER/ {gsub("\"","");print$2}' ${WORKSPACE}/test.cfg
/$, returnStdout: true).trim()
echo "Folder: ${FOLDER_NAME}" // print folder name in groovy console
sh "mkdir -p ${WORKSPACE}/${FOLDER_NAME} && chmod 777 ${WORKSPACE}/${FOLDER_NAME}"

Related

Accessing jenkins shell variables within a k8s container

stages
{
stage('test')
{
steps
{
withCredentials([string(credentialsId: 'kubeconfigfile', variable: 'KUBECONFIG' )])
{
container('deploycontainer')
{
sh 'TEMPFILE=$(mktemp -p "${PWD}" kubeconfig.XXXXX)'
sh 'echo "${TEMPFILE}"'
}
}
}
}
}
I'm new to creating pipelines and am trying to covert a freestyle job over to a pipeline.
I'm trying to create a temp file for a kubeconfig file within the container.
I've tried everyway I could think of to access the vars for the shell and not a groovy var.
even trying the below prints nothing on echo:
sh 'TEMPFILE="foo"'
sh 'echo ${TEMPFILE}'
I've tried escaping and using double quotes as well as single and triple quote blocks.
How do you access the shell vars from within the container block/how do you make a temp file and echo it back out within that container block?
With Jenkinsfiles, each sh step runs its own shell. When each shell terminates, all of its state is lost.
If you want to run multiple shell commands in order, you can do one of two things.
You can have a long string of commands separated by semi-colons:
sh 'cmd1; cmd2; cmd3; ...'
Or you can use ''' or """ to extend the commands over multiple lines (note of course that if you use """ then groovy will perform string interpolation):
sh """
cmd1
cmd2
cmd3
...
"""
In your specific case, if you choose option 2, it will look like this:
sh '''
TEMPFILE=$(mktemp -p "${PWD}" kubeconfig.XXXXX)
echo "${TEMPFILE}"
'''
Caveat
If you are specifying a particular shebang, and you are using a multiline string, you MUST put the shebang immediately after the quotes, and not on the next line:
sh """#!/usr/bin/env zsh
cmd1
cmd2
cmd3
...
"""

how to create global variable inside a stage So that i can use it into the other stage as well in pipeline script

In the below code I am fetching the version inside the script block, but I can not use it in the sh block and even not in the post block. Can someone please help. I am able to print the value in the println function. Variable is generating at the run time so I can not define inside the global environment block of Jenkinsfile. Can someone please help and tell me what am missing here?
stage('test build') {
steps {
script{
version = sh (
script: "cat ${WORKSPACE}/version.txt | grep var | awk -F ':' '{print \$2}'",
returnStdout: true
).trim()
}
println(version)
sh '''
echo "${version}"
'''
}
post {
success {
sh '''
echo "${version}"
'''
}
}
}

setting environment variable in scripted pipeline

Im trying to create a virtualenv(stage) in Jenkins and setting the needed environment variables before the virtualenv can be created.
stage('create virtualenvironment') {
sh 'export PATH=/usr/local/bin/virtualenv:$PATH'
sh 'export VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python'
sh 'export VIRTUALENVWRAPPER_VIRTUALENV=/usr/local/bin/virtualenv'
sh 'source /usr/local/bin/virtualenvwrapper.sh'
echo 'createvirtualenvwrapper'
sh 'mkvirtualenv testproject'
}
When I execute this script - I get this message -
mkvirtualenv: command not found
When I print all the above env variables nothing is set? Not sure if the sh command is working as expected in scripted pipeline.
I'm not 100% sure but my guess is that, when you do a sh 'Some command' it executes a shell script and it is done.
So what is happening is that, each of your sh commands is being treated as a separate shell script which is executing the commands and is alive only for that session and closes once the script is done.
So try to combine all of the above commands to a single sh command along with the mkvirtualenv testproject and it should work.
For readability create a new Shell script like runProject.sh and the above commands in this shell script and then you can just call
sh runProject.sh
Hope it helps :)

How to configure Jenkins pipeline so that if there are multiple shell scripts and if one fails the jenkins jobs still runs instead of exiting

I want to configure a Jenkins pipeline job so that it should be able to run multiple shell script jobs. Even if one shell script fails the job should run the other two before failing the job.
You need to tweak your shell script, not Jenkins pipeline to achieve what you want!
Try this in your shell script
shell script command > /dev/null 2>&1 || true
so fail/pass it will execute and go to next shell script
You can always try catch the potentially failing sh execution
node {
sh "echo test"
try {
sh "/dev/null 2>&1"
} catch (error) {
echo "$error"
}
sh "echo test1"
}
Above runs successfully and produces
Started by user Blazej Checinski
[Pipeline] node
Running on agent2 in /home/build/workspace/test
[Pipeline] {
[Pipeline] sh
[test] Running shell script
+ echo test
test
[Pipeline] sh
[test] Running shell script
+ /dev/null
/home/build/workspace/test#tmp/durable-b4fc2854/script.sh: line 2: /dev/null: Permission denied
[Pipeline] echo
hudson.AbortException: script returned exit code 1
[Pipeline] sh
[test] Running shell script
+ echo test1
test1
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

How to set variables in a multi-line shell script within Jenkins Groovy?

Suppose I have a Groovy script in Jenkins that contains a multi-line shell script. How can I set and use a variable within that script? The normal way produces an error:
sh """
foo='bar'
echo $foo
"""
Caught: groovy.lang.MissingPropertyException: No such property: foo for class: groovy.lang.Binding
You need to change to triple single quotes ''' or escape the dollar \$
Then you'll skip the groovy templating which is what's giving you this issue
I'm just putting a '\' on the end of line
sh script: """\
foo='bar' \
echo $foo \
""", returnStdout: true
This statement works on my script.

Resources