Jenkins出现java.lang.NoSuchMethodError:找不到DSL方法action2如何修复?
Jenkins Pipeline自定义Groovy库调用方法报错修复
问题场景
在Jenkins Pipeline中引用自定义Groovy库my-lib,调用tools.findErrors(currentBuild.rawBuild)方法时触发NoSuchMethodError,提示找不到action2方法。
Pipeline代码
// ./vars/tools.groovy @Library('my-lib') _ pipeline { ... post { failure { script { tools.findErrors(currentBuild.rawBuild) } } } }
自定义库tools.groovy代码
def action1(rawBuild) { println("-- action1 --") def res = [] ... res.each{ println(it) } return res } def action2(List res, String line) { println("-- action2 --") ... } def findErrors(rawBuild) { def errors = action1(rawBuild) def res = [] errors.each{ action2(res, it) } }
执行报错输出
-- action1 -- error: ... error: ... Error when executing failure post condition: Also: org.jenkinsci.plugins.workflow.actions.ErrorAction$ErrorId: some_guid java.lang.NoSuchMethodError: No such DSL method 'action2' found among steps [archive, bat, build ....] at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:219) at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:124) at groovy.lang.MetaClassImpl.invokeMethodOnGroovyObject(MetaClassImpl.java:1295) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1184) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:41) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:20) at org.jenkinsci.plugins.workflow.cps.LoggingInvoker.methodCall(LoggingInvoker.java:105) at tools.findErrors(tools.groovy:1111)
修复方案
报错的核心原因是:Jenkins Pipeline的CPS沙箱环境中,each闭包内的方法调用默认会查找Jenkins DSL步骤,而非当前Groovy库类中的方法。需明确指定调用当前对象的action2方法,两种可行修复方式:
方式一:用this关键字指定上下文
修改findErrors方法的each循环,调用action2时添加this.前缀:
def findErrors(rawBuild) { def errors = action1(rawBuild) def res = [] errors.each{ this.action2(res, it) } }
方式二:使用方法引用变量
先将action2赋值为当前对象的方法引用,再在闭包中调用:
def findErrors(rawBuild) { def errors = action1(rawBuild) def res = [] def localAction2 = this.&action2 errors.each{ localAction2(res, it) } }
关键说明
在Jenkins Pipeline的Groovy库中,闭包(如each、with)内部调用自定义方法时,必须明确指定方法所属的上下文。否则CPS解释器会误将其识别为Jenkins DSL步骤,进而抛出方法未找到的异常。
内容的提问来源于stack exchange,提问作者Dmitry Sokolov
相关产品推荐
相关产品推荐

