我最近在与同事一起进行 Jenkins 构建时遇到了一些难题。他一直交替使用 params.VARIABLE
和 env.VARIABLE
,并且没有任何问题。与此同时,我开始在他通过这行代码的环境对参数对象的调用之一中收到空对象错误:
if(!deploy_environments.contains(env.ENVIRONMENT_NAME.trim()) || params.INVOKE_PARAMETERS ) {
ENVIRONMENT_NAME
这里是一个参数。我开始收到此错误:
java.lang.NullPointerException: Cannot invoke method trim() on null object
此构建作为另一个构建的子版本执行。 ENVIRONMENT_NAME
参数从父版本传递给子版本。
他在不同的 Jenkins master 上根本没有看到这个错误。当我将上面的引用从 env.ENVIRONMENT_NAME
更改为 params.ENVIRONMENT_NAME
时,问题就消失了。
我在 Jenkins 文档中找不到对 params == env
的引用,因此我创建了一个构建来尝试阐明它们的关系。
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
、echo env.PARAM
, echo param.ENV
) 成功,输出如下:
[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
我想,“啊哈!”问题解决了。它们不一样。
但是,那个盒子随后立即卡住在我身上并拒绝再排队构建。我还没调试完,不过怀疑那位大师是不是搞砸了也不算过分。
所以我去我们身边的第三个 Jenkins master 上运行了它。此时,我添加了您在上面的脚本中看到的附加行以进一步澄清。我第一次在该盒子上运行此脚本时,它在“对 $PARAMETER_VARIABLE 行的特定引用”上失败,并显示以下输出:
[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 中引用环境变量,而无需专门引用环境对象,但不能对参数执行相同的操作。一致、合理,我对此很擅长。
然后我删除了执行“非特定引用”的两行,脚本成功并输出以下输出:
[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
现在我完全困惑了。我勒个去?为了确定起见,我运行了几次,并且始终如一地获得了与上面相同的成功输出。
当然,之前的所有将 env.PARAM
显示为 null
的构建都没有在干净的环境中真正成功(成功的构建是在一个立即内爆的环境中)之后就轮到我了)。那么,如果 Jenkins 管道中存在错误,它是否会导致将参数加载到环境中或其他什么情况?我尝试将 echo "$I_SHOULD_FAIL"
添加到脚本中,以强制出现错误,试图重现我所看到的内容。没有骰子:
[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 管道中的环境
和参数
之间有什么关系?这种关系应该是什么?为什么它看起来不一致?
最佳答案
基本上工作原理如下
env
包含所有 environment variables .- Jenkins 管道自动为每个环境变量创建一个全局变量
params
包含所有构建参数。- Jenkins 还会自动为每个构建参数创建一个环境变量(并且作为第二点的结果,创建一个全局变量)。
环境变量可以被覆盖或取消设置,但params
是一个不可变的Map,无法更改。最佳实践是在需要获取构建参数时始终使用 params
。
参见Global Variable Reference有关变量的更多详细信息。
关于jenkins - Jenkinsfile 参数化构建中的环境和参数之间有什么关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50398334/