Home > Net >  Jenkins throwing an error when writing back an xml File
Jenkins throwing an error when writing back an xml File

Time:01-29

I have a stage on my Jenkins pipeline where I search for a .xml File, open it, change a node and write the changes back to the .xml File. It works fine when I do it on my local machine but it does not work when it is done on Jenkins.

This is the code I'm using:

def inFile = new File('myFile.xml')
def xml = new XmlSlurper(false,false).parse( inFile )


if(xml.repositories.repository.url.toString().contains("string to match") {

    xml.repositories.repository.replaceNode { 
        repository{
            id("id")
            name("name")
            url("url")
        }
    }

    inFile.withWriter { outWriter ->
        XmlUtil.serialize(xml, outWriter )
    }
}

And Jenkins is showing this error:

java.lang.NoSuchMethodError: No such DSL method 'repository' found among steps[]
    at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:176)
    at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
    at groovy.lang.MetaClassImpl.invokeMethodOnGroovyObject(MetaClassImpl.java:1278)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1172)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:20)
    at ___cps.transform___(Native Method)
    at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:82)
    at sun.reflect.GeneratedMethodAccessor204.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.ClosureBlock.eval(ClosureBlock.java:46)
    at com.cloudbees.groovy.cps.Next.step(Next.java:83)
    at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
    at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
    at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122)
    at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261)
    at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$101(SandboxContinuable.java:34)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.lambda$run0$0(SandboxContinuable.java:59)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:58)
    at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:174)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:332)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:83)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:244)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:232)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131)
    at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

My xml file looks like this:

...

<repositories>
    <repository>
        <id>id old</id>
        <url>url old</url>
    </repository>
</repositories>

...

I have check the imports and have them all correct. I moved the write part to a function and added @NonCPS annotation and nothing changed. I think I'm having a problem with the BufferedWriter but I don't know how to continue on this. Any help is welcome, thank you so much!

CodePudding user response:

I think your problem may not be a BufferedWriter, but more the reading part. The error message No such DSL method 'repository' found among steps points in that direction.

Line four of your code tries to access the XML object repository from your parsed myFile.xml:

if(xml.repositories.repository.url.toString().contains("string to match") {

Dereferencing xml.respositories.repository fails, maybe because the file can not be read or parsed. Can you check in your Groovy code, whether the file exists and is readable?

CodePudding user response:

I'm following up on my comment with an actual solution advice:

No such DSL method 'repository' found among steps points to the fact that Jenkins is trying to interpret your repository as its own method. That could be happening actually on line 8 of your code as everywhere else it's explicitly defined what you're referencing.

So - in order to fix this ambiguity in your code, try this:

  • Define your repository node variable and then use it within the replaceNode so it's crystal clear to Jenkins what it should do.

Something likes this (you'll probably need it import groovy.util.Node probably too (but I don't know the rest of you pipeline code) adjust your node attributes according to your needs):

import groovy.util.*
def repository = new Node(null, 'repository', [id:'3'])

xml.repositories.repository.replaceNode { 
    repository
}

To provide some references and further inspiration (as myself I'm not a groovy master at all):

  • Related