Jenkins 带有自定义步骤和库的管道Groovy错误

Jenkins 带有自定义步骤和库的管道Groovy错误,jenkins,groovy,jenkins-pipeline,Jenkins,Groovy,Jenkins Pipeline,我的Jenkins 2.0管道库和自定义步骤有以下问题 来自repo X的My Jenkins文件包含: @Library('acme-pipelines@dev') import acme.jenkins.* node { runGradle { version = '3.3' cmd = '--version' } } 在repo Y管道库repo i中,vars/runGradle.groovy包含: import acme.jenki

我的Jenkins 2.0管道库和自定义步骤有以下问题

来自repo X的My Jenkins文件包含:

@Library('acme-pipelines@dev')

import acme.jenkins.*

node {
    runGradle {
        version = '3.3'
        cmd = '--version'
    }
}
在repo Y管道库repo i中,vars/runGradle.groovy包含:

import acme.jenkins.*

def call(body) {
    def config = [:]
    def utils = new Utils()

    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config
    body()

    sh "${utils.getGradleBinPath(config.version)} ${config.cmd}"
}
package acme.jenkins

static String getGradleBinPath(String version = null) {
    if (!version) {
        throw new IllegalArgumentException('No Gradle version supplied')
    }
    tool(version).concat('/bin/gradle')
}
同样在repo Y中,我有src/acme/jenkins/Utils.groovy,其中包含:

import acme.jenkins.*

def call(body) {
    def config = [:]
    def utils = new Utils()

    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config
    body()

    sh "${utils.getGradleBinPath(config.version)} ${config.cmd}"
}
package acme.jenkins

static String getGradleBinPath(String version = null) {
    if (!version) {
        throw new IllegalArgumentException('No Gradle version supplied')
    }
    tool(version).concat('/bin/gradle')
}
当我运行管道时,出现以下错误:

Running on master in /var/lib/jenkins/workspace/Jenkins Library Development
[Pipeline] {
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: static softvision.jenkins.Utils.tool() is applicable for argument types: (java.lang.String) values: [3.3]
Possible solutions: wait(), run(), run(), find(), grep(), any()
    at groovy.lang.MetaClassImpl.invokeStaticMissingMethod(MetaClassImpl.java:1506)
    at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1492)
    at org.codehaus.groovy.runtime.callsite.StaticMetaClassSite.call(StaticMetaClassSite.java:53)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:18)
    at softvision.jenkins.Utils.getGradleBinPath(file:/var/lib/jenkins/jobs/Jenkins%20Library%20Development/builds/89/libs/softvision-pipelines/src/softvision/jenkins/Utils.groovy:7)
    at runGradle.call(/var/lib/jenkins/jobs/Jenkins Library Development/builds/89/libs/softvision-pipelines/vars/runGradle.groovy:11)
    at WorkflowScript.run(WorkflowScript:6)
    at ___cps.transform___(Native Method)
    at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:82)
    at sun.reflect.GeneratedMethodAccessor273.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.LocalVariableBlock$LocalVariable.get(LocalVariableBlock.java:39)
    at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
    at com.cloudbees.groovy.cps.impl.LocalVariableBlock.evalLValue(LocalVariableBlock.java:28)
    at com.cloudbees.groovy.cps.LValueBlock$BlockImpl.eval(LValueBlock.java:55)
    at com.cloudbees.groovy.cps.LValueBlock.eval(LValueBlock.java:16)
    at com.cloudbees.groovy.cps.Next.step(Next.java:74)
    at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:154)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:18)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable$1.call(SandboxContinuable.java:33)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable$1.call(SandboxContinuable.java:30)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:30)
    at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:165)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:330)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$100(CpsThreadGroup.java:82)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:242)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:230)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:112)
    at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Finished: FAILURE
如果我将getGradleBinPath方法包装在名为Utils的类中,无论是否使用该方法的静态关键字前缀,这都是相同的错误,我在使用该类版本时也尝试实现Serializable,但我得到了相同的错误

如果我删除脚本版本中的static关键字,它就可以正常工作,所有示例代码场景和上面提到的都会产生相同的错误


我是Groovy的新手,所以如果这与Jenkins无关,或者非常琐碎,请原谅。

您不能直接在src目录下的classes\scripts中访问管道标准步骤。您应该将这些步骤传递给构造函数/设置器或作为方法参数。 这样的办法应该行得通 src/acme/jenkins/Utils.groovy

然后在vars/runGradle.groovy中


请注意,步骤是一个标准的全局变量,用于保存管道步骤。

不知何故,我在文档中忽略了这一点。您的实现工作正常,但需要进行一次小的编辑,我还需要实现可序列化接口,否则我会在acme.jenkins.Utils上得到一个java.io.NotSerializableException异常,请您编辑您的答案,以便我将其标记为例外?作为旁注,如果有人能够介入并解释为什么不实现Serializable接口它就无法工作,这将是非常有帮助的。值得一提的是,如果您不需要暂停和恢复使用runGradle自定义步骤的Jenkins管道,您可以将@NonCPS decorator添加到vars/runGradle.groovy中的调用方法中,在这种情况下,您不需要在Utils类上实现可序列化接口。@Nicolae这是因为Jenkins管道使用CPS转换。你可以多读一些。我想应该是新的。这是吗?