Jenkins升级后readCSV报ClassCastException问题求助
问题
升级Jenkins到2.375.2(Pipeline Utility Steps版本2.15.0)后,在Jenkinsfile中使用readCSV读取security.csv文件时触发类转换异常,报错信息如下:
java.lang.ClassCastException: class org.jenkinsci.plugins.pipeline.utility.steps.csv.ReadCSVStep.setFormat() expects class org.apache.commons.csv.CSVFormat but received class org.apache.commons.csv.CSVFormat 01:24:57 at org.jenkinsci.plugins.structs.describable.DescribableModel.coerce(DescribableModel.java:492) 01:24:57 at org.jenkinsci.plugins.structs.describable.DescribableModel.injectSetters(DescribableModel.java:429) 01:24:57 at org.jenkinsci.plugins.structs.describable.DescribableModel.instantiate(DescribableModel.java:331) 01:24:57 at org.jenkinsci.plugins.structs.describable.DescribableModel.instantiate(DescribableModel.java:272) 01:24:57 at org.jenkinsci.plugins.workflow.steps.StepDescriptor.newInstance(StepDescriptor.java:204) 01:24:57 at org.jenkinsci.plugins.pipeline.utility.steps.AbstractFileOrTextStepDescriptorImpl.newInstance(AbstractFileOrTextStepDescriptorImpl.java:24) 01:24:57 at org.jenkinsci.plugins.pipeline.utility.steps.AbstractFileOrTextStepDescriptorImpl.newInstance(AbstractFileOrTextStepDescriptorImpl.java:12) 01:24:57 at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:302) 01:24:57 at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:196) 01:24:57 at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:124) 01:24:57 at jdk.internal.reflect.GeneratedMethodAccessor229844.invoke(Unknown Source) 01:24:57 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 01:24:57 at java.base/java.lang.reflect.Method.invoke(Method.java:566) 01:24:57 at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:98) 01:24:57 at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) 01:24:57 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1225) 01:24:57 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) 01:24:57 at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:41) 01:24:57 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) 01:24:57 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) 01:24:57 at org.kohsuke.groovy.sandbox.impl.Checker€0.97.call(Checker.java:180) 01:24:57 at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:23) 01:24:57 at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:162) 01:24:57 at org.kohsuke.groovy.sandbox.impl.Checker€0.97.call(Checker.java:178) 01:24:57 at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:182) 01:24:57 at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:152) 01:24:57 at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:152) 01:24:57 at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17) 01:24:57 Caused: java.lang.IllegalArgumentException: Could not instantiate {file=security.csv, format=Delimiter=<,> QuoteChar="<" RecordSeparator=< 01:24:57 > EmptyLines:ignored SkipHeaderRecord:false Header:[]} for org.jenkinsci.plugins.pipeline.utility.steps.csv.ReadCSVStep
对应的Jenkinsfile代码片段:
stage('Init Artifacts') { steps { checkout(scm); script { if (params.ScanStack != '') { def csv_artifacts = readCSV file: 'security.csv', format: CSVFormat.DEFAULT.withHeader('ARTIFACT_NAME', 'ARTIFACT_VERSION'); for (CSVRecord record : csv_artifacts.iterator()) { artifactsList.add(record.toMap()) } } } } }
该代码在升级前运行正常,已查阅JENKINS-58137未找到有效解决方案。
解决方案
这个异常是由于Jenkins升级后,Pipeline Utility Steps插件的类加载机制变化,直接传递CSVFormat对象会触发类加载冲突。修改方案如下:
方法1:使用readCSV的header参数替代format设置
readCSV本身提供了header参数来指定表头,无需手动构建CSVFormat对象,这是最简洁的解决方式:
stage('Init Artifacts') { steps { checkout(scm); script { if (params.ScanStack != '') { // 直接使用header参数指定表头,无需CSVFormat def csv_artifacts = readCSV file: 'security.csv', header: ['ARTIFACT_NAME', 'ARTIFACT_VERSION']; for (def record : csv_artifacts) { artifactsList.add(record) } } } } }
说明:readCSV返回的每一条记录本身就是Map格式,无需调用toMap()方法,直接遍历添加即可。
方法2:通过字符串描述CSV格式(兼容复杂格式场景)
如果需要自定义更多CSV格式规则(比如分隔符、引号等),可以使用格式字符串而非CSVFormat对象:
def csvFormat = "DEFAULT, header=ARTIFACT_NAME,ARTIFACT_VERSION" def csv_artifacts = readCSV file: 'security.csv', format: csvFormat
格式字符串支持的规则参考插件内置的CSV格式定义,避免直接传递CSVFormat实例。
补充说明
升级后的Pipeline Utility Steps插件(2.15.0+)对format参数的处理方式发生了变化,不再支持直接传入org.apache.commons.csv.CSVFormat对象,改用字符串或内置参数配置,以此避免类加载器导致的类型冲突问题。
内容的提问来源于stack exchange,提问作者Appy
相关产品推荐
相关产品推荐

