Jenkins:将插件 DSL 函数添加到共享库函数时没有此类 DSL 方法

Jenkins: No Such DSL Method when adding a plugin DSL function to a shared library function

我们正在使用 JCasC 定义如下的 jenkins 共享库:

controller:
  JCasC:
    configScripts:
      jenkins-casc-unclassified: |
        unclassified:
          globalLibraries:
            libraries:
            - defaultVersion: "master"
              implicit: true
              name: "com.company.jenkins"
              retriever:
                modernSCM:
                  scm:
                    github:
                      configuredByUrl: true
                      credentialsId: "..."
                      id: "..."
                      repoOwner: "Company"
                      repository: "Company_CICD"
                      repositoryUrl: "https://github.com/company/Company_CICD.git"
                      traits:
                      - gitHubBranchDiscovery:
                          strategyId: 1
                      - gitHubPullRequestDiscovery:
                          strategyId: 1
                      - gitHubForkDiscovery:
                          strategyId: 1
                          trust: "gitHubTrustPermissions"

我们为 Kubernetes Plugin 制作了一个方便的功能,使我们能够大大缩短代码。然而,在尝试消除 2 行时,我们遇到了一个我们想澄清的奇怪错误:

java.lang.NoSuchMethodError: No such DSL method 'getPodTemplate'

奇怪的是,在不更改导入或函数名称的情况下,它就出现了。

例如,这个有效:

// src/com/company/jenkins/Util.groovy
package com.onscale.jenkins

def getPodTemplate(String label, List<String> containers, List<String> volumes, String yaml) {
    containers = containers.collect {
        value -> return getContainerTemplate(value)
    }
    volumes = volumes.collect {
        value -> return getVolume(value)
    }
    return [
      label: label,
      yaml: yaml,
      containers: containers,
      volumes: volumes
    ]
}
// Jenkinsfile
def util = new com.onscale.jenkins.Util()
podTemplate (
  util.getPodTemplate(
    'jenkinsbuild', // Label
    ['jnlp', 'docker', 'kubectl'], // Containers
    ['host-path'], // Volumes
    podSpec
  )
)

但事实并非如此:

// src/com/company/jenkins/Util.groovy
package com.onscale.jenkins

def getPodTemplate(String label, List<String> containers, List<String> volumes, String yaml) {
    containers = containers.collect {
        value -> return getContainerTemplate(value)
    }
    volumes = volumes.collect {
        value -> return getVolume(value)
    }
    return podTemplate(
      label: label,
      yaml: yaml,
      containers: containers,
      volumes: volumes
    )
}
// Jenkinsfile
def util = new com.onscale.jenkins.Util()
util.getPodTemplate(
  'jenkinsbuild', // Label
  ['jnlp', 'docker', 'kubectl'], // Containers
  ['host-path'], // Volumes
  podSpec
)

两者之间的变化是if getPodTemplate returns podTemplate.

我们四处寻找。 堆栈溢出让我们感到困惑,因为我们没有使用 var/function.groovy 制作共享库的方法(我不太确定每种“种类”的共享库被称为什么),我们正在导入使用“ new" 和一个 globalLibrary.

有什么想法吗?

此作业 DSL 错误似乎是在函数未编译时发生的。在这种情况下,该函数不会编译,因为 groovy 执行此操作,您可以在不带括号的情况下调用函数。

示例:

def foo(name, closure) {println name; println closure()}

可以通过以下方式调用。

foo(“asdf”,{return “asdf”})
foo “asdf” {return “asdf”}
foo(“asdf”) {return “asdf”}

带括号和不带括号

但是这样:

foo(“asdf”)

将抛出错误 MissingMethodException 因为 foo 需要 2 个参数。而我最初认为它会 return 部分。

所以当我们 return podTemplate 没有闭包作为最后一个参数时,我们实际上破坏了该方法的编译,因此我们得到一个 DSL 错误,因为共享库无法编译。

解决方案是添加一个闭包最终参数,并将其作为最后一个参数传递给 podTemplate