Jenkins管道中的XmlSlurper()。如何避免java.io.NotSerializableException:groovy.util.slurpersupport.NodeChild

我正在尝试从pom.xml文件中读取属性。我尝试了以下方法,并且有效:

steps {
    script {
        def xmlfile = readFile "pom.xml"
        def xml = new XmlSlurper().parseText(xmlfile)
        def version = "${xml.version}"
        echo version
    }
}

当我尝试做这样的事情时:

steps {
    script {
        def xmlfile = readFile "pom.xml"
        def xml = new XmlSlurper().parseText(xmlfile)
        def version = "${xml.version}"
        def mystring = "blabhalbhab-${version}"
        echo mystring
    }
}

管道突然失败,并显示以下错误:

Caused: java.io.NotSerializableException: groovy.util.slurpersupport.NodeChild

这里可能是什么问题?

编辑:只是添加给其他使用相同用例的人。我的具体问题是关于如何避免使用XmlSlurper()进行CPS相关的错误。但是对于试图解析POM的其他任何人,却担心PR可能会弃用readMavenPom,这样做最安全,最简单的方法可能是:

def version = sh script: "mvn help:evaluate -f 'pom.xml' -Dexpression=project.version -q -DforceStdout",returnStdout: true trim()

通过这种方式,您可以使用maven本身来告诉您版本是什么,而不是在该死的地方刺探或隐藏。 How to get Maven project version to the bash command line

as97100590 回答:Jenkins管道中的XmlSlurper()。如何避免java.io.NotSerializableException:groovy.util.slurpersupport.NodeChild

通常,在CPS管道中使用groovy.util.slurpersupport.NodeChildxml变量的类型)或groovy.util.slurpersupport.NodeChildrenxml.version的类型)是一个坏主意。这两个类均不可序列化,因此您无法在Groovy CPS中断言它们的行为。例如,我在Jenkins Pipeline中成功运行了您的第二个示例。很有可能是因为您提供的示例不完整或类似的东西。

groovy:000> xml = new XmlSlurper().parseText("<tag></tag>")
===> 
groovy:000> xml instanceof Serializable
===> false
groovy:000> xml.tag instanceof Serializable
===> false
groovy:000> xml.dump()
===> <groovy.util.slurpersupport.NodeChild@0 node=groovy.util.slurpersupport.Node@5b1f29fa parent= name=tag namespacePrefix=* namespaceMap=[xml:http://www.w3.org/XML/1998/namespace] namespaceTagHints=[xml:http://www.w3.org/XML/1998/namespace]>
groovy:000> xml.tag.dump()
===> <groovy.util.slurpersupport.NodeChildren@0 size=-1 parent= name=tag namespacePrefix=* namespaceMap=[xml:http://www.w3.org/XML/1998/namespace] namespaceTagHints=[xml:http://www.w3.org/XML/1998/namespace]>
groovy:000> 

如果要读取pom.xml文件,请使用readMavenPom管道步骤。它专用于读取pom文件以及最重要的内容-无需应用任何变通办法即可安全地进行读取。 pipeline-utility-steps plugin附带了这一步骤。

但是,如果由于某些原因要使用XmlSlurper,则需要在用@NonCPS注释的方法中使用它。这样,您可以访问“纯” Groovy并避免遇到的问题。 (但仍使用readMavenPom是实现您要尝试的操作的最安全方法。)此处的要点是使用@NonCPS范围内的所有不可序列化的对象,因此管道不会尝试序列化它。

下面您可以找到显示两种方法的简单管道示例。

pipeline {
    agent any 

    stages {
        stage("Using readMavenPom") {
            steps {
                script {
                    def xmlfile = readMavenPom file: "pom.xml"
                    def version = xmlfile.version
                    echo "version = ${version}"
                }
            }
        }

        stage("Using XmlSlurper") {
            steps {
                script {
                    def xmlfile = readFile "pom.xml"
                    def version = extractFromXml(xmlfile) { xml -> xml.version }
                    echo "version = ${version}"
                }
            }
        }
    }
}

@NonCPS
String extractFromXml(String xml,Closure closure) {
    def node = new XmlSlurper().parseText(xml)
    return closure.call(node)?.text()
}

PS:更不用说使用XmlSlurper至少需要获得脚本3的批准,然后才能开始使用它。

本文链接:https://www.f2er.com/3135859.html

大家都在问