jenkins - Jenkinsfile 中奇怪的变量作用域行为
问题描述
当我运行以下 Jenkins 管道脚本时:
def some_var = "some value"
def pr() {
def another_var = "another " + some_var
echo "${another_var}"
}
pipeline {
agent any
stages {
stage ("Run") {
steps {
pr()
}
}
}
}
我收到此错误:
groovy.lang.MissingPropertyException: No such property: some_var for class: groovy.lang.Binding
如果从def
中删除some_var
,它可以正常工作。有人可以解释导致这种行为的范围规则吗?
解决方案
TL;博士
- 不能从其他方法访问主脚本主体中定义的 变量。
def
- 没有 定义的变量
def
可以通过任何方法直接访问,甚至可以从不同的脚本中访问。这是一个不好的做法。 - 使用
def
和 注释定义的变量@Field
可以直接从同一脚本中定义的方法访问。
解释
当 groovy 编译该脚本时,它实际上将所有内容移动到一个大致看起来像这样的类
class Script1 {
def pr() {
def another_var = "another " + some_var
echo "${another_var}"
}
def run() {
def some_var = "some value"
pipeline {
agent any
stages {
stage ("Run") {
steps {
pr()
}
}
}
}
}
}
您可以看到这some_var
显然超出了范围,因为pr()
它是不同方法中的局部变量。
当您定义一个变量时,您实际上没有 def
将该变量放入脚本的绑定中(所谓的绑定变量)。因此,当 groovypr()
首先执行方法时,它会尝试查找具有名称的局部变量,some_var
如果它不存在,则尝试在 Binding 中查找该变量(该变量存在是因为您没有定义它def
)。
绑定变量被认为是不好的做法,因为如果您加载多个脚本(load
步骤),绑定变量将可以在所有这些脚本中访问,因为 Jenkins 为所有脚本共享相同的绑定。一个更好的选择是使用@Field
注释。这样,您可以在一个脚本内的所有方法中使变量可访问,而无需将其暴露给其他脚本。
import groovy.transform.Field
@Field
def some_var = "some value"
def pr() {
def another_var = "another " + some_var
echo "${another_var}"
}
//your pipeline
当 groovy 将此脚本编译成一个类时,它看起来像这样
class Script1 {
def some_var = "some value"
def pr() {
def another_var = "another " + some_var
echo "${another_var}"
}
def run() {
//your pipeline
}
}
推荐阅读
- javascript - 无法通过 Angular 中的路由显示组件
- python - 使用 numpy.save 保存和使用 pickle.load 加载时出错
- c# - 构建 URL 请求的函数
- google-apps-script - 我们可以在气体应用程序中设置电子邮件吗?
- javascript - 如何在 React Hooks 中将两个状态合并为单个状态?
- java - Java HashMap.size() 函数如何在内部工作?
- java - 设置待处理意图/广播接收器的问题
- c# - .NetCore 不引用实体框架错误
- typescript - Mocha/Chai:使用错误消息测试抛出的错误
- python - 使用正则表达式执行分配属性