We have been hitting this for ages on our CI cluster, and were mystified because a rebuild would often (but not always) fix the issue. It turned out that the problematic env-vars were all coming from the GitLab Branch Source plugin, e.g. the git commit message, and a rebuild locally did not have them and so did not reproduce the issue, but a rebuild triggered from GitLab's UI did send the env-vars again and reproduce.
For future reference, I put together a Jenkinsfile to demonstrate/test the issue in a couple of variants:
String baseImage = "mcr.microsoft.com/windows/nanoserver:1809"
String nodeSelector = "docker-windows-lite"
Closure runTest = {
node(nodeSelector) {
stage('test') {
echo "Running on ${env.NODE_NAME}"
bat 'echo TEST: [%TESTENV%]'
docker.image(baseImage).inside() {
timeout(time: 10, unit: 'SECONDS') {
bat 'echo PASS: [%TESTENV%]'
}
}
}
}
}
parallel emptyEnv: {
withEnv(['TESTENV=']) {
runTest()
}
}, envVar: {
withEnv(['TESTENV=SIMPLE_VALUE']) {
runTest()
}
}, envVarWithSpaces: {
withEnv(['TESTENV=VALUE WITH SPACES']) {
runTest()
}
}, envVarWithQuoteAtEnd: {
withEnv(['TESTENV=VALUE_WITH_QUOTE_AT_THE_END"']) {
runTest()
}
}, envVarWithQuoteInTheMiddle: {
withEnv(['TESTENV=VALUE_WITH_QUOTE"IN_THE_MIDDLE']) {
runTest()
}
}, envVarWithSpacesAndQuoteAtEnd: {
withEnv(['TESTENV=VALUE WITH SPACES AND QUOTE AT THE END"']) {
runTest()
}
}, envVarWithSpacesAndQuoteInTheMiddle: {
withEnv(['TESTENV=VALUE WITH QUOTE"IN THE MIDDLE']) {
runTest()
}
}, multilineEnvVar: {
withEnv(['''\
TESTENV=SIMPLE_VALUE
A_SECOND_LINE''']) {
runTest()
}
}, multilineEnvVarWithSpaces: {
withEnv(['''\
TESTENV=VALUE WITH SPACES
A SECOND LINE''']) {
runTest()
}
}, multilineEnvVarWithQuoteAtEnd: {
withEnv(['''\
TESTENV=VALUE_WITH_QUOTE
AT_END_OF_SECOND_LINE"''']) {
runTest()
}
}, multilineEnvVarWithQuoteInTheMiddle: {
withEnv(['''\
TESTENV=VALUE_WITH_QUOTE
IN_THE_MIDDLE"OF_SECOND_LINE''']) {
runTest()
}
}, multilineEnvVarWithSpacesAndQuoteAtEnd: {
withEnv(['''\
TESTENV=VALUE WITH SPACES AND QUOTE
AT END OF SECOND LINE"''']) {
runTest()
}
}, multilineEnvVarWithSpacesAndQuoteInTheMiddle: {
withEnv(['''\
TESTENV=VALUE WITH SPACES AND QUOTE
IN THE MIDDLE"OF SECOND LINE''']) {
runTest()
}
}, failFast: false
In our environment (Docker Pipeline Plugin 1.26, Jenkins 2.303.1), the following stages show the failure:
- envVarWithQuoteAtEnd
- envVarWithQuoteInTheMiddle
- envVarWithSpacesAndQuoteInTheMiddle
- multilineEnvVarWithQuoteAtEnd
- multilineEnvVarWithQuoteInTheMiddle
- multilineEnvVarWithSpacesAndQuoteInTheMiddle
I did check elsewhere that the two examples given by allenbenz gave the same results as originally described, so I suspect that balanced quotes in the middle don't introduce the issue, as my tests here with a single double-quote in the middle all fail. I observe that multiline doesn't actually seem to be relevant; I noticed that at least for the GitLab Branch Source plugin, the commit message env-var always includes the trailing newline so it's always multiline, and it works if there's no quotes there.
It is interesting that spaces inline makes the single-quote-at-the-end pass. The quote definitely comes through to the batch file in the container so I'm not sure why that is, or why it's different to allenbenz's tests. Again, it might be related to having unbalanced quotes changing the result.
Note that PR 220 actually fixed this problem when starting the container (adding WindowsUtil.quoteArgument here), the remaining problem we're seeing is when running commands inside the container, i.e. here.
I suspect the fix is as simple as changing prefix.add(e) to prefix.add(WindowsUtil.quoteArgument(e)) and similar for prefix.addAll(envReduced), except this is not Windows-specific code so it'd have to be conditional on super.IsUnix().
Possibly the same issue as
JENKINS-65933