问题描述
我最近在与同事一起开发一些 Jenkins 构建时遇到了一些难题.他一直在使用 params.VARIABLE
和 env.VARIABLE
并且没有任何问题.同时,我开始在他通过这行代码的环境调用参数对象时收到空对象错误:
I recently ran into something of a puzzler while working on some Jenkins builds with a coworker. He's been using params.VARIABLE
and env.VARIABLE
interchangably and having no issues with it. Meanwhile, I started getting null object errors on one of his calls to a parameter object through the environment on this line of code:
if(!deploy_environments.contains(env.ENVIRONMENT_NAME.trim()) || params.INVOKE_PARAMETERS ) {
ENVIRONMENT_NAME
这里是一个参数.我开始收到此错误:
ENVIRONMENT_NAME
here is a parameter. I started getting this error:
java.lang.NullPointerException: Cannot invoke method trim() on null object
此构建作为另一个构建的子级执行.ENVIRONMENT_NAME
参数从该父构建向下传递给子构建.
This build is executing as a child of another build. The ENVIRONMENT_NAME
parameter is passed down to the child from that parent build.
他在不同的 Jenkins master 上根本没有看到这个错误.当我将上面的参考从 env.ENVIRONMENT_NAME
更改为 params.ENVIRONMENT_NAME
时,问题就消失了.
He was not seeing this error at all on a different Jenkins master. When I changed the reference above from env.ENVIRONMENT_NAME
to params.ENVIRONMENT_NAME
the issue went away.
我在 Jenkins 文档中找不到对 params == env
的引用,因此我创建了一个构建来尝试澄清它们的关系.
I could find no reference to params == env
in the Jenkins documentation, so I created a build to try to clarify their relationship.
pipeline {
agent {
label 'jenkins-ecs-slave'
}
environment {
ENV_VARIABLE = 'Environment'
}
parameters {
string(description: 'Parameter', name: 'PARAMETER_VARIABLE', defaultValue: 'Parameter')
}
stages {
stage('Output Parameters'){
steps {
script {
echo "Environment: ${env.ENV_VARIABLE}"
echo "Parameter: ${params.PARAMETER_VARIABLE}"
echo "Environment from params: ${params.ENV_VARIABLE}"
echo "Parameter from Env: ${env.PARAMETER_VARIABLE}"
echo "Inspecific reference ENV_VARIABLE: $ENV_VARIABLE"
echo "Inspecific reference PARAMETER_VARIABLE: $PARAMETER_VARIABLE"
sh 'echo "Shell environment: $ENV_VARIABLE"'
sh 'echo "Shell parameter: $PARAMETER_VARIABLE"'
}
}
}
}
}
我第一次在我的 Jenkins master 上运行它时,它只包含前四行(echo env.ENV
、echo param.PARAM
、echoenv.PARAM
, echo param.ENV
) 它成功了,输出如下:
The first time I ran this on my Jenkins master, it only included the first four lines (echo env.ENV
, echo param.PARAM
, echo env.PARAM
, echo param.ENV
) it succeeded with the following output:
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Output Parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Environment: Environment
[Pipeline] echo
Parameter: Parameter
[Pipeline] echo
Environment from params: null
[Pipeline] echo
Parameter from Env: null
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
我想,啊哈!"问题解决了.它们不一样.
And I thought, "Aha!" Problem solved. They're not the same.
但是,之后那个盒子很快就冻结了我,并且拒绝再排队构建.还没调试完,不过怀疑那位大师是不是搞砸了也不过分.
However, that box promptly froze up on me afterwards and refused to queue anymore builds. I haven't finished debugging it, but it's not out of line to wonder if that master is just messed up.
所以我在我们一直在闲逛的第三个 Jenkins master 上运行它.正是在这一点上,我添加了您在上面脚本中看到的附加行以进一步澄清.我第一次在那个盒子上运行这个脚本时,它在Inspecific reference to $PARAMETER_VARIABLE line"上失败了,输出如下:
So I went and ran it on a third Jenkins master we have hanging around. It's at this point I added the additional lines you see in the script above to further clarify. The first time I ran this script on that box, it failed on the "Inspecific reference to $PARAMETER_VARIABLE line" with the following output:
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Output Parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Environment: Environment
[Pipeline] echo
Parameter: Parameter
[Pipeline] echo
Environment from params: null
[Pipeline] echo
Parameter from Env: null
[Pipeline] echo
Inspecific reference ENV_VARIABLE: Environment
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
groovy.lang.MissingPropertyException: No such property: PARAMETER_VARIABLE for class: groovy.lang.Binding
好的,到目前为止一切顺利.这是有道理的.他们不一样.您可以在不专门引用环境对象的情况下在 echo 和 shell 中引用环境变量,但不能对参数执行相同的操作.一致的,合理的,我很擅长这个.
Okay, so far so good. This makes sense. They aren't the same. You can reference Environment variables in echos and shells with out specifically referencing the environment object, but can't do the same with parameters. Consistent, reasonable, I'm good with this.
然后我删除了执行非特定引用"的两行,脚本成功,输出如下:
So then I removed the two lines doing the "inspecific reference" and the script succeeded with the following output:
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Output Parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Environment: Environment
[Pipeline] echo
Parameter: Parameter
[Pipeline] echo
Environment from params: null
[Pipeline] echo
Parameter from Env: Parameter
[Pipeline] sh
[Environment Testing] Running shell script
+ echo 'Shell environment: Environment'
Shell environment: Environment
[Pipeline] sh
[Environment Testing] Running shell script
+ echo 'Shell parameter: Parameter'
Shell parameter: Parameter
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
现在我完全糊涂了.我勒个去?为了确定,我运行了几次,并且始终如一地获得了与上述相同的成功输出.
And now I'm completely confuddled. What the hell? I ran it a couple of times just to be sure, and got the same successful output as above, consistently.
当然,之前将 env.PARAM
显示为 null
的构建都没有真正在干净的环境中成功(成功的是在迅速内爆的环境中)之后在我身上).因此,也许如果 Jenkins 管道中出现错误,它会将参数加载到环境中或其他什么短路?我尝试将 echo "$I_SHOULD_FAIL"
添加到脚本中以强制出错,以尝试重现我所看到的内容.没有骰子:
Granted, none of the previous builds that showed env.PARAM
as null
had really succeeded in a clean environment (the one that succeeded was in an environment the promptly imploded on me afterwards). So maybe if there's an error in the Jenkins pipeline, it short circuits the loading of parameters into the environment or something? I tried adding echo "$I_SHOULD_FAIL"
to the script to force an error in an attempt to reproduce what was I seeing. No dice:
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Output Parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Environment: Environment
[Pipeline] echo
Parameter: Parameter
[Pipeline] echo
Environment from params: null
[Pipeline] echo
Parameter from Env: Parameter
[Pipeline] sh
[Environment Testing] Running shell script
+ echo 'Shell environment: Environment'
Shell environment: Environment
[Pipeline] sh
[Environment Testing] Running shell script
+ echo 'Shell parameter: Parameter'
Shell parameter: Parameter
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
groovy.lang.MissingPropertyException: No such property: I_SHOULD_FAIL for class: groovy.lang.Binding
那么这里发生了什么?Jenkins流水线中的environment
和parameters
有什么关系?这种关系应该是什么?为什么它似乎不一致?
So what's going on here? What's the relationship between environment
and parameters
in Jenkins pipelines? What is that relationship supposed to be and why does it seem to be inconsistent?
推荐答案
基本上是这样工作的
env
包含所有环境变量.- Jenkins 流水线自动为每个环境变量创建一个全局变量
params
包含所有构建参数.- Jenkins 还会自动为每个构建参数创建一个环境变量(并且作为第二点的结果是一个全局变量).
env
contains all environment variables.- Jenkins pipeline automatically creates a global variable for each environment variable
params
contains all build parameters.- Jenkins also automatically creates an environment variable for each build parameter (and as a consequence of the second point a global variable).
环境变量可以被覆盖或取消设置,但 params
是不可变的 Map,不能更改.最佳做法是在需要获取构建参数时始终使用 params
.
Environment variables can be overridden or unset, but params
is an immutable Map and cannot be changed. Best practice is to always use params
when you need to get a build parameter.
请参阅 全局变量参考有关变量的更多详细信息.
See Global Variable Reference for more details regarding the variables.
这篇关于Jenkinsfile Parameterized Builds 中的 Environment 和 Parameters 有什么关系?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!