Разбор XML-файла в конвейере Jenkins

У меня есть файл 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

Я использую Jenkins 2.7 с конвейером 2.1, который в настоящее время является последним.

5 ответов

Решение

В конце концов я думаю, что мой подход был неправильным: я решил преобразовать файл XML в отдельный скрипт Groovy и загрузить его в конвейер.

Обновление: недавно люди начали редактировать мой ответ для ясности, но факт в том, что я просто отказался от сохранения своей конфигурации в файлах XML и выбрал отличные скрипты, что дало мне больше гибкости. Я понимаю, что это не может быть обычной практикой, но это соответствует моим потребностям.

Например - вместо:

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}"
}

Я надеюсь, что это лучший ответ:)

Вы можете использовать XmlSlurper, он работает для меня.

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

Так как ветвь является корневым элементом, вам не нужно явно указывать его при доступе к вашим проанализированным узлам

Попробуйте изменить

println buildPlan.branch

к

println buildPlan.stage

Распечатать узлы сцены

@NonCPS метод должен только принять или вернуть Serializable типы. Попробуй вернуться .branch из метода.

Могу я порекомендовать общую библиотеку . Это позволит вам

  • централизовать логику
  • писать модульные тесты - через модуль конвейера jenkins и, возможно, Spock
  • используйте такой подход

Src dir

      class PipelineSupport {
    PipelineSupport(def env, def jenkinsStepAccess) {
        this.env = env
        this.jenkinsStepAccess = jenkinsStepAccess

    }
    def readXml(def path) {
        def text = jenkinsStepAccess.readFile(path)
        def parser = new XmlParser()
        def xml = parser.parseText(text.toString())
        return xml
    }
}

vars dir var / foo.groovy

      import ...PipelineSupport

Map readXml(def path) {
    // pass env and "this" access point to jenkins DSL to calls
    return new PipelineSupport(env, this).readXml(path)
}

использовать в сборке

      library "mylib"
def xmlData = foo.readXml('path/to/bar.xml')
Другие вопросы по тегам