为什么此 groovy 代码在 jenkins 管道脚本中的工作方式不同
Why does this groovy code work differently in jenkins pipeline script
我有一段代码可以在我所知道的所有 groovy 解释器中完美运行,包括 Jenkins 脚本控制台。然而,当涉及到管道脚本时,它有一个奇怪的行为。
def kvs = ['key1': 'value1', 'key2': 'value2']
println kvs
println kvs.inject(''){ s,k,v -> s+= "{'$k': '$v' } "}
首先,地图打印方式不同:
- 预期:
[key1:value1, key2:value2]
- 得到:
{key1=value1, key2=value2}
然后,更多的问题是,产生的结果大不相同:
- 预期:
{'key1': 'value1' } {'key2': 'value2' }
- 得到:
null
这两个结果都是通过以下 groovy 版本获得的:2.4.12
。
(虽然,在管道脚本之外,我也尝试了 2.4.6
和 2.4.15
版本并且总是得到预期的结果)
请注意,我对解决方法不感兴趣。我只想了解为什么行为从正常 groovy 变为管道脚本。
它的发生是因为 Jenkins 管道代码实际上并不是 运行 这个 Groovy 代码,它直接用解析器解释它以应用脚本安全性来保持 Jenkins 系统的安全等。引用 "Pipeline code is written as Groovy but the execution model is radically transformed at compile-time to Continuation Passing Style (CPS)." - 请参阅最佳实践 https://jenkins.io/blog/2017/02/01/pipeline-scalability-best-practice/。简而言之,不要在管道中编写复杂的 Groovy 代码 - 尝试使用管道 DSL 或插件提供的标准步骤。然而,在某些情况下,脚本部分中的简单 Groovy 代码可能很有用。现在我将一些更复杂的东西放在提供自定义步骤的插件中。
我有一段代码可以在我所知道的所有 groovy 解释器中完美运行,包括 Jenkins 脚本控制台。然而,当涉及到管道脚本时,它有一个奇怪的行为。
def kvs = ['key1': 'value1', 'key2': 'value2']
println kvs
println kvs.inject(''){ s,k,v -> s+= "{'$k': '$v' } "}
首先,地图打印方式不同:
- 预期:
[key1:value1, key2:value2]
- 得到:
{key1=value1, key2=value2}
然后,更多的问题是,产生的结果大不相同:
- 预期:
{'key1': 'value1' } {'key2': 'value2' }
- 得到:
null
这两个结果都是通过以下 groovy 版本获得的:2.4.12
。
(虽然,在管道脚本之外,我也尝试了 2.4.6
和 2.4.15
版本并且总是得到预期的结果)
请注意,我对解决方法不感兴趣。我只想了解为什么行为从正常 groovy 变为管道脚本。
它的发生是因为 Jenkins 管道代码实际上并不是 运行 这个 Groovy 代码,它直接用解析器解释它以应用脚本安全性来保持 Jenkins 系统的安全等。引用 "Pipeline code is written as Groovy but the execution model is radically transformed at compile-time to Continuation Passing Style (CPS)." - 请参阅最佳实践 https://jenkins.io/blog/2017/02/01/pipeline-scalability-best-practice/。简而言之,不要在管道中编写复杂的 Groovy 代码 - 尝试使用管道 DSL 或插件提供的标准步骤。然而,在某些情况下,脚本部分中的简单 Groovy 代码可能很有用。现在我将一些更复杂的东西放在提供自定义步骤的插件中。