问题描述
我有一个用于Jenkins文件的Jenkins共享库。我的库有一个完整的管道,并且它具有一个在管道中使用的函数(简称为examFun()
)。
我的Jenkins文件:
@Library('some-shared-lib') _
jenkinsPipeline{
exampleArg = "yes"
}
我的共享库文件(称为 jenkinsPipeline.groovy ):
def examFun(){
return [
new randClass(name: 'Creative name no 1',place: 'London')
new randClass(name: 'Creating name no 2',place: 'Berlin')
]
}
def call(body) {
def params= [:]
body.resolveStrategy = Closure.DELEGATE_FirsT
body.delegate = params
body()
pipeline {
// My entire pipeline is here
// Demo stage
stage("Something"){
steps{
script{
projectName = params.exampleArg
}
}
}
}
}
class randClass {
String name
String place
}
它工作正常,但是examFun()
的值是经过硬编码的,将来可能需要更改。因此,我希望能够从我的Jenkinsfile中更改它们(就像我可以更改exampleArg
一样)。在this文章之后,我尝试了以下操作:
我将examFun()
更改为
def examFun(String[] val){
return [
new randClass(name: val[0],place: 'London')
new randClass(name: val[1],place: 'Berlin')
]
}
然后从我的Jenkinsfile中调用它
@Library('some-shared-lib') _
jenkinsPipeline.examFun(['Name 1','Name 2'])
jenkinsPipeline{
exampleArg = "yes"
}
但是那没有用(可能是因为我的图书馆是通过 def call(body){}
构建的)。之后,我尝试将jenkinsPipeline.groovy拆分为2个文件:第一个文件包含管道部分,第二个文件包含examFun()
,其中包含randClass
。我将我的Jenkinsfile修改如下:
@Library('some-shared-lib') _
def config = new projectConfig() // New groovy filed is called 'projectConfig.groovy'
config.examFun(["Name 1","Name 2"])
jenkinsPipeline{
exampleArg = "yes"
}
No such DSL method 'examFun()' found among steps
更新-新错误
感谢zett42,我已经成功解决了此错误。但是,我遇到了下面提到的另一个错误:
java.lang.NullPointerException: Cannot invoke method getAt() on null object
要解决此问题,在我的情况下,我需要为Jenkinsfile中的变量分配examFun()
并将其作为参数传递到jenkinsPipeline{}
中。功能代码如下:
Jenkinsfile :
@Library('some-shared-lib') _
def list = jenkinsPipeline.examFun(['Name 1','Name 2'])
def names = jenkinsPipeline.someFoo(list)
jenkinsPipeline{
exampleArg = "yes"
choiceArg = names
}
jenkinsPipeline.groovy :
def examFun(List<String> val){
return [
new randClass(name: val[0],place: 'Berlin')
]
}
def call(body) {
def params= [:]
body.resolveStrategy = Closure.DELEGATE_FirsT
body.delegate = params
body()
pipeline {
// My entire pipeline is here
parameters{
choice(name: "Some name",choices: params.choiceArg,description:"Something")
}
// Demo stage
stage("Something"){
steps{
script{
projectName = params.exampleArg
}
}
}
}
}
def someFoo(list) {
def result = []
list.each{
result.add(it.name)
}
return result
}
class randClass {
String name
String place
}
解决方法
当您收到错误消息“没有这种DSL方法...”时,通常仅表示参数类型和实际传递的参数不兼容,在这种情况下。
函数examFun()
需要一个数组,但是实际上您正在传递ArrayList
。正如this answer中所述,在Groovy中底层数组并不是真正的习惯用法。
尝试以下方法:
def examFun(List<String> val){
return [
new randClass(name: val[0],place: 'London')
new randClass(name: val[1],place: 'Berlin')
]
}
List
是ArrayList
实现的更通用的接口。
现在,您的第一个jenkinsfile示例应该可以工作:
jenkinsPipeline.examFun(['Name 1','Name 2'])
即使您已经拥有call
方法,实际上您也可以具有其他命名方法。我一直在用这个。