I've trouble setting an environment variable for a container in an Jenkins pipeline.
It seems, that "withEnv" does not work nicely with machines without bash.
Can you confirm that? I cannot find an official statement ;-)
When I run the following snippet on the Jenkins slave it works.
But when it is executed in a docker container without BASH "$test" isn't set.
withEnv(["test='asd'"]){
sh 'echo $test'
}
https://jenkins.io/doc/pipeline/steps/workflow-basic-steps/#code-withenv-code-set-environment-variables
If I'm not mistaken, I believe the variable is not set correctly.
Try this:
withEnv(["test=asd"]){
sh "echo \$test"
}
Within a Jenkins pipeline:
$var = Groovy parameter
\$var (within a sh closure) = Bash parameter
${var} = also refers to Groovy parameter
In order to insert a groovy variable into a bash variable:
sh ("VAR=${GROOVY_VAR}")
Using a bash variable inside a sh closure:
sh (" echo \$BASH_VAR")
We have to use single quote when using withEnv in Jenkins.
withEnv(['test=asd']){
sh "echo \$test"
}
Because, the variable expansion is being done by the Bourne shell, not Jenkins.
(Quoting from documentation)
Find more info here: https://jenkins.io/doc/pipeline/steps/workflow-basic-steps/
Related
I'm running a declarative Jenkins pipeline on Ubuntu 18.04 slave. My issue is that whenever I'm trying to provide arguments from a sh step to a bash script, the arguments are not there. When running the exact same commands from either a terminal directly or another script file (similarly how Jenkins does it via temp file) the arguments work fine.
The Jenkinsfile looks something like
pipeline {
agent { label "ubuntu" }
options { timeout(time: 1, unit: 'HOURS') }
stages {
stage('Build') {
steps {
sh """
#!/bin/bash
...
. ./Scripts/install_tools.sh "force"
"""
}
}
}
}
The pipeline itself runs smooth and does what I need it to do. The problem is that when calling install_tools.sh no arguments are found. The script looks something like
#!/bin/bash
echo "Running $0"
echo "Args: $#"
...
The line echo "Args: $#" I have tried also with $* and $1 - Each time the arguments are returned as empty, but only when running from the pipeline. It seems to me that this is related to some Groovy stuff, but I have no clue what.
How do I call a bash script during the pipeline and get the arguments passed properly?
put #!/bin/bash into the first line
sh """#!/bin/bash
. ./Scripts/install_tools.sh "force"
"""
otherwise . (dot) command could have different meaning
Im exploring a bit on shell scripts and wrote this script. When the build command fails, it has to provide an error message and exit.
I know that exit 1 would close the current shell its running on. And the exit statement is within a curly braces (meaning that its executed on the same shell). But when this script is run as ./testScript.sh it stops executing test(), testTwo() is not called, and the terminal remains open.
While this is exactly the functionality i'm looking for, my question is why doesn't it close the terminal due to the exit 1; command? Does git bash creates a subshell by default when running a script?
I know its not because its been called within a function. I did try running the exit statement in script without a function, and it still doesnt close the terminal.
Any insights on the actual working of git bash and exit command would be highly useful.
Thanks!
# testScript.sh
function test() {
dotnet build -c Debug sample.csproj || { echo -e "${RED}=== Build Failed"; exit 1; }
}
function testTwo() {
echo "== executing test two function."
}
function all()
{
pushd .
test
testTwo
popd
}
all "$#"
Does git bash creates a subshell by default when running a script?
It's not a "subshell" as in ( ). The shell spawns a separate process that executes the command. The process does not inherit bash variables and functions, only inherits exported variables, i.e. it's not a subshell.
Do not use function name(), just name(). See https://wiki.bash-hackers.org/scripting/obsolete . Check scripts with shellcheck.net .
The following conditional works as expected when run from the bash command line on my Jenkins server:
if (($BRANCH_COUNT > 0)); then .....
But when running in the context of a Jenkins pipeline step (calling sh ''' .... '''), it writes an error and always evaluates to false. The error message (below) suggests maybe it's interpreting the value of $BRANCH_COUNT (in this case it is 1) as a command, which is then not found?
/var/jenkins/workspace/deploy-config-db-update#tmp/durable-baa54bb3/script.sh: 16:
/var/jenkins/workspace/deploy-config-db-update#tmp/durable-baa54bb3/script.sh: 1: not found
Is there something different about the bash environment when run by the Jenkins sh command? Some special escaping or quoting needed?
if you use sh'''...''', the pipeline script variable will not be expanded in your shell script. You need to use sh """..."""
Moving William Pursell's comment into an answer, because it solved the problem.
Using (()) is a bashism. Try if test "$BRANCH_COUNT" -gt 0; then ...
Following is a screenshot of how I am setting an environment variable in Jenkins.
I am trying to access it in a shell script, but it is not echoing its value.
echo "Starting ..."
echo ${BUILD_NUMBER}
echo ${DATABASE}
${BUILD_NUMBER} is a global env variable.
The correct use of variables in Jenkins is the following:
echo "The current build number is: ${BUILD_NUMBER}"
The important part is to use ". If you would use ' Jenkins would not notice that you want to access the variable and simply print your variable as string.
Source: Jenkins String Interpolation
I am using the BUILD STEP "Execute shell script on remote host" and I'm injecting a password to my project:
The jenkins call a script.sh, but the script does not print variable PASS passed by jenkins.
As a step variable issued by Jenkins to my external script?
PASS=${PASSWORD}
echo PASSWORD=$PASS
sh /root/script.sh
You need to export your variable in order to make it available to subshells:
export PASS=${PASSWORD}
If you don't want other programs you invoke in the same script to see your password, consider this safer way:
PASS=${PASSWORD} /root/script.sh