web-dev-qa-db-ja.com

Jenkinsパイプライン内のXMLファイルの解析

パイプラインスクリプトの入力として使用したいXMLファイルがあります。問題は、XMLParserがシリアル化できないため、NonCPS関数に入れましたが、そのためにNodeオブジェクトを失いました。

これはパイプラインスクリプトです:

def buildPlanPath = 'C:\\buildPlan_test.xml'

@NonCPS
groovy.util.Node getBuildPlan(path) {
    new XmlParser().parseText(readFile(path))
}

node {
    //def buildPlan = new XmlParser().parseText(readFile(buildPlanPath))
    groovy.util.Node buildPlan = getBuildPlan(buildPlanPath)

    println buildPlan.getClass()
    println buildPlan
    println buildPlan.branch
}

これは入力サンプルです:

<branch name='mybranch'>
    <stage>
        <job name='job11' />
        <job name='job12' />
    </stage>
    <stage>
        <job name='job21' />
        <job name='job22' />
        <job name='job23' />
    </stage>
    <stage>
        <job name='job31' />
    </stage>
</branch>

結果は次のとおりです。

Started by user admin
[Pipeline] node
Running on master in C:\Jenkins\workspace\pipeline-develop
[Pipeline] {
[Pipeline] readFile
[Pipeline] echo
class Java.lang.String
[Pipeline] echo
<branch name='mybranch'>
  <stage>
    <job name='job11' />
    <job name='job12' />
  </stage>
  <stage>
    <job name='job21' />
    <job name='job22' />
    <job name='job23' />
  </stage>
  <stage>
    <job name='job31' />
  </stage>
</branch>
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
groovy.lang.MissingPropertyException: No such property: branch for class: Java.lang.String
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.Java:53)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.Java:458)
    at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.getProperty(DefaultInvoker.Java:25)
    at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.Java:17)
    at WorkflowScript.run(WorkflowScript:16)
    at ___cps.transform___(Native Method)
    at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.Java:62)
    at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.Java:30)
    at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.Java:54)
    at Sun.reflect.GeneratedMethodAccessor327.invoke(Unknown Source)
    at Sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at Java.lang.reflect.Method.invoke(Unknown Source)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.Java:72)
    at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.Java:21)
    at com.cloudbees.groovy.cps.Next.step(Next.Java:58)
    at com.cloudbees.groovy.cps.Continuable.run0(Continuable.Java:154)
    at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.Java:164)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.Java:276)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$000(CpsThreadGroup.Java:78)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.Java:185)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.Java:183)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.Java:47)
    at Java.util.concurrent.FutureTask.run(Unknown Source)
    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(Unknown Source)
    at Java.util.concurrent.FutureTask.run(Unknown Source)
    at Java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at Java.lang.Thread.run(Unknown Source)
Finished: FAILURE

現在最新のパイプライン2.1でJenkins2.7を使用しています。

5
towel

あなたはXmlSlurperを使うことができます、それは私のために働きます。

def xmlText = new XmlSlurper().parse(MyURL)
xmlText.data.artifact.each {******
3
Kirill

@NonCPSメソッドは、Serializableタイプのみを受け入れるか返す必要があります。メソッドから.branchを返してみてください。

0
Jesse Glick

結局、私のアプローチは間違っていたと思います。XMLファイルを別のGroovyスクリプトに変換し、パイプライン内にロードすることにしました。

更新:最近、わかりやすくするために回答の編集を始めましたが、実際には、構成をXMLファイルに保存するのをやめ、Groovyスクリプトを選択したため、柔軟性が向上しました。それは一般的な習慣ではないかもしれませんが、私のニーズには合っています。

例-代わりに:

config.xml:
<settings>
  <floopi>2</floopi>
</settings>

私が使用した:

config.groovy:
def call() {[
  floopi: 2
]}
return this

そしてパイプラインスクリプトでは:

stage('init') {
    def settings = load('config.groovy')()
    echo "floopi: ${settings.floopi}"
}

私はそれがより良い答えであることを願っています:)

0
towel

ブランチはルート要素であるため、解析されたノードにアクセスするときに明示的に指定する必要はありません。

変更してみてください

println buildPlan.branch

println buildPlan.stage

ステージノードを印刷するには

0
tim_yates