向Jenkins共享库提供参数

问题描述

我有一个用于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')
  ]
}

ListArrayList实现的更通用的接口。

现在,您的第一个jenkinsfile示例应该可以工作:

jenkinsPipeline.examFun(['Name 1','Name 2'])

即使您已经拥有call方法,实际上您也可以具有其他命名方法。我一直在用这个。