Reputation: 13046
When using env
object in shared library, env.HOME
value doesn't shift with a dockerized stage. When a shell step executes, its HOME
points to the correct value.
In the case below, I'd expect env.HOME == sh(script:'echo $HOME', returnStdout: true).trim()
and it does on the agent stage but not in the dockerized stage.
This is trivial to work around (use withEnv to set, use ~
or $HOME
in shell commands to pull home from shell not groovy layer)
I'd just like to know the why behind it.
def info() {
println "Stage: ${env.STAGE_NAME}, env.HOME: ${env.HOME}
sh 'echo HOME=$HOME'
}
# Jenkinsfile
...
stages {
stage('agent') {
steps {
script { foo.info() }
}
}
stage('dockerized') {
agent {
docker {
image runnerImage
reuseNode true
}
}
steps {
script { foo.info() }
}
Stage: agent, HOME: /home/ec2-user
echo HOME=/home/ec2-user
HOME=/home/ec2-user
Stage: agent, HOME: /home/ec2-user
echo HOME=/home/jenkins
HOME=/home/jenkins
Upvotes: 0
Views: 69
Reputation: 13046
Silly me, the answer appear during some insomnia. The HOME environment variable was set by the contain's operating system itself and therefore Jenkins and its shared library could not know what it was.
The /etc/passwd and setting of USER
in the image's Dockerfile determines HOME. Any profile or rc files in HOME would add additional env variables.
The ways to limit the damage of this class from a library designer point of view are:
sh "ls ${env.HOME}" // bad idea, the HOME may not match container's idea
sh 'ls $HOME' // better, resolution from shell not Gstring
sh "ls ~" // ~ auto resolves to $HOME within shell
-e ${HOME}:HOME
I'd also recommend using images what follow suit aligned with the agent OS structure when possible but if your shared library is used by 100s or 1000s of build jobs, you cannot know this will be the case and it is better to reduce the risk.
Upvotes: 0