jenkinsgroovyjenkins-shared-libraries

Jenkins Groovy error groovy.lang.MissingMethodException when trying to use readFile()


I've been getting an odd error in Jenkins when trying to run readFile() within a shared library, so that I can determine if a Dockerfile is pulling from ECR or docker hub. The error is :-

hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: org.myorg.DockerManager.readFile() is applicable for argument types: (java.lang.String) values: [DockerServiceDescription/Dockerfile]
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54)
    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 org.proj.DockerManager.login(/tmp/persistence/jobs/PROJ/jobs/builds/jobs/proj-subproj/branches/PROJ-4190/builds/47/libs/Global/src/org/me/DockerManager.groovy:26)

The method that's triggering the error is :-

    /**
        Login to docker
     */
    void login() {
        dockerfileHandle = readFile(dockerfile)
        dockerfileLines = dockerfileHandle.readLines()
        def dockerfileFROM = dockerfileLines.find{ dockerfileLine-> dockerfileLine =~ /^FROM / }

        println("FROM: " + dockerfileFROM)
        if (dockerfileFROM =~ /\.ecr\./ ) {
            println("Using ECR")
            ecrlogin()
        } else {
            println("Using DOCKER HUB")
            dockerhublogin()
        }
    }

however that same code worked perfectly well within the pipeline code, it just breaks when moved into a shared library.

Any ideas?


Solution

  • Access to pipeline steps is done via an instance of CPSScript that represents the running pipeline. To use it in a class of shared library, you have to pass this into your library, either as constructor or method argument:

        /**
            Login to docker
         */
        void login(def script) { // actually CPSScript, but that way, no import is needed
            dockerfileHandle = script.readFile(dockerfile)
            //...
        }
    
    

    This from your actual Jenkins file, you then call it like:

    myInstance.login(this)
    

    Also note that you println calls would result in output in the Jenkins logs, not the build logs, what you are aiming for is script.echo()