Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-42730

declarative-linter don't work with shared library

      I have a jenkinsfile which call shared library at the beginning

      @Library('gconftools')
      import forjenkins.GetNodes
      

      this jenkinsfile work correctly, but when I want to test with declarative-linter, there is an error.

      java -jar /var/lib/jenkins/home/war/WEB-INF/jenkins-cli.jar -s http://serveur.domainperso:8082 declarative-linter --username=user --password mdp <script.groovy
      
      Errors encountered validating Jenkinsfile:
      WorkflowScript: 7: unable to resolve class forjenkins.GetNodes
       @ line 7, column 1.
         @Library('gconftools')
         ^
      
      WorkflowScript: 26: unable to resolve class forjenkins.GetNodes 
       @ line 26, column 7.
                      z = new forjenkins.GetNodes()
               ^
      

          [JENKINS-42730] declarative-linter don't work with shared library

          Boudoux Etienne created issue -

          Andrew Bayer added a comment -

          First, I'd suggest upgrading to Declarative 1.1 and using the new libraries directive -

          pipeline {
            agent any
            libraries {
              lib('gconftools')
            }
            stages {
              ...
            }
          }

          And then let me know if that works, and if not, what the error is along with (ideally) a copy of the Jenkinsfile having the problem.

          Andrew Bayer added a comment - First, I'd suggest upgrading to Declarative 1.1 and using the new libraries directive - pipeline { agent any libraries { lib( 'gconftools' ) } stages { ... } } And then let me know if that works, and if not, what the error is along with (ideally) a copy of the Jenkinsfile having the problem.

          hi,

          I don't see any doc for this new libraries directive.

          do you have a working example?

           

          thank

           

          Boudoux Etienne added a comment - hi, I don't see any doc for this new libraries directive. do you have a working example?   thank  

          hi,

          I have found the doc (https://jenkins.io/doc/book/pipeline/shared-libraries/#loading-libraries-dynamically ), and resolved my problem . So you can close this bug.

           

          Boudoux Etienne added a comment - hi, I have found the doc ( https://jenkins.io/doc/book/pipeline/shared-libraries/#loading-libraries-dynamically ), and resolved my problem . So you can close this bug.  

          Reinhold Füreder added a comment - - edited

          I stumbled over this issue as well (when using global vars from "vars/" and using classes from the "src/"), but was not able to resolve the problem to my satisfation:

          • either the linter complains about the import (initial/old approach via @Library and import), while the pipeline works
          • or the pipeline fails

           

          I tried many unsuccessful approaches, here are some of them:

          1. Using library directive on top (before pipeline) and a second library for dynamic class usage
            --- old/Jenkinsfile
            +++ new/Jenkinsfile
             
            -@Library('acme-shared-library') _
            -import com.acme.Constants
            +library('acme-shared-library')
             
             pipeline {
            ...
                   steps {
                     script {
                       acme.setBuildDisplayName()
            +          
            +          def lib = library('acme-shared-library').com.acme // preselect the package
            +          echo lib.Constants.DEVOPS_EMAIL
                     }
                   }
                 }
            
            • Interesting log output:
              Only using first definition of library acme-shared-library
              
            • Failure:
              java.lang.IllegalAccessException: com.acme.Constants was defined in file:///var/lib/jenkins/jobs/***/builds/42/libs/acme-shared-library/vars/acme.groovy which was not inside file:///var/lib/jenkins/jobs/***/builds/42/libs/acme-shared-library/src/
              	at org.jenkinsci.plugins.workflow.libs.LibraryStep$LoadedClasses.loadClass(LibraryStep.java:287)
              	at org.jenkinsci.plugins.workflow.libs.LibraryStep$LoadedClasses.getProperty(LibraryStep.java:240)
              	at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:174)
              	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:456)
              	at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:243)
              	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:52)
              	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:308)
              	at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:241)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:238)
              	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:28)
              	at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
              	at WorkflowScript.run(WorkflowScript:28)
              	at ___cps.transform___(Native Method)
                ...
              
          2. Using library directive on top (before pipeline) (without a second library for dynamic class usage) and direct FQ access to class
            --- old/Jenkinsfile
            +++ new/Jenkinsfile
             
            -@Library('acme-shared-library') _
            -import com.acme.Constants
            +library('acme-shared-library')
             
             pipeline {
            ...
                   steps {
                     script {
                       acme.setBuildDisplayName()
            +          
            +          echo "devops email: ${com.acme.Constants.DEVOPS_EMAIL}"
                     }
                   }
                 }
            
            • No interesting log output anymore (cf. "Only using first definition of library acme-shared-library")
            • Failure:
              groovy.lang.MissingPropertyException: No such property: com for class: groovy.lang.Binding
              	at groovy.lang.Binding.getVariable(Binding.java:63)
              	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:224)
              	at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:241)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:238)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221)
              	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:28)
              	at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
              	at WorkflowScript.run(WorkflowScript:27)
              	at ___cps.transform___(Native Method)
                ...
              
          3. Using library directive in pipeline before first global var usage
            --- old/Jenkinsfile
            +++ new/Jenkinsfile
             
            -@Library('acme-shared-library') _
            -import com.acme.Constants
             
             pipeline {
            ...
                   steps {
                     script {
            +          def lib = library('acme-shared-library').com.acme // preselect the package
                       acme.setBuildDisplayName()
            +          echo "devops email: ${lib.Constants.DEVOPS_EMAIL}"         }
                   }
                 }
            
            • Failure:
              java.lang.IllegalAccessException: com.acme.Constants was defined in file:///var/lib/jenkins/jobs/***/builds/45/libs/acme-shared-library/vars/acme.groovy which was not inside file:///var/lib/jenkins/jobs/***/builds/45/libs/acme-shared-library/src/
              	at org.jenkinsci.plugins.workflow.libs.LibraryStep$LoadedClasses.loadClass(LibraryStep.java:287)
              	at org.jenkinsci.plugins.workflow.libs.LibraryStep$LoadedClasses.getProperty(LibraryStep.java:240)
              	at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:174)
              	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:456)
              	at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:243)
              	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:52)
              	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:308)
              	at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:241)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:238)
              	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:28)
              	at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
              	at WorkflowScript.run(WorkflowScript:25)
              	at ___cps.transform___(Native Method)
                ...
              
          4. Same for using library directive in pipeline before first global var usage and FQ access to class instead of preselect package
            --- old/Jenkinsfile
            +++ new/Jenkinsfile
             
            -@Library('acme-shared-library') _
            -import com.acme.Constants
             
             pipeline {
            ...
                   steps {
                     script {
            +          def lib = library('acme-shared-library')
                       acme.setBuildDisplayName()
            +          echo "devops email: ${lib.com.acme.Constants.DEVOPS_EMAIL}"
                   }
                 }
            
          5. Using new libraries section in pipeline
            --- old/Jenkinsfile
            +++ new/Jenkinsfile
             
            -@Library('acme-shared-library') _
            -import com.acme.Constants
             
             pipeline {
            ...
            +  libraries {
            +    lib('acme-shared-library')
            +  }
            +
                   steps {
                     script {
                       acme.setBuildDisplayName()
            +          echo "devops email: ${com.acme.Constants.DEVOPS_EMAIL}"
                   }
                 }
            
            • Failure:
              groovy.lang.MissingPropertyException: No such property: com for class: groovy.lang.Binding
              	at groovy.lang.Binding.getVariable(Binding.java:63)
              	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:224)
              	at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:241)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:238)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221)
              	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221)
              	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:28)
              	at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
              	at WorkflowScript.run(WorkflowScript:29)
              	at ___cps.transform___(Native Method)
                ...
              

          Oh! The following approach seems to work (linter is happy and pipeline works), but is a rather inconvenient/surprising workaround; thus, this is rather interesting for the bug fix, but not a real workaround, let alone a solution, I claim:

          • not using libraries block in pipeline block, but using library including suffix for class in "src/" (as seen above it does not work, if the first library statement is without class usage suffix!)
          --- old/Jenkinsfile
          +++ new/Jenkinsfile
           
          -@Library('acme-shared-library') _
          -import com.acme.Constants
           
           pipeline {
          ...
                 steps {
                   script {
          +          echo "devops email: ${library('acme-shared-library').com.acme.Constants.DEVOPS_EMAIL}"
                     acme.setBuildDisplayName()
          +          
                 }
               }
          

          IMHO this is very confusing and should be addressed in another issue, but presumably not in the linter (unless the initial/old approach via @Library and import will be re-recommended, and the linter accepts it).

          Reinhold Füreder added a comment - - edited I stumbled over this issue as well (when using global vars from "vars/" and using classes from the "src/"), but was not able to resolve the problem to my satisfation: either the linter complains about the import (initial/old approach via @Library and import ), while the pipeline works or the pipeline fails   I tried many unsuccessful approaches, here are some of them: Using library directive on top (before pipeline ) and a second library for dynamic class usage --- old/Jenkinsfile +++ new /Jenkinsfile -@Library( 'acme-shared-library' ) _ - import com.acme.Constants +library( 'acme-shared-library' ) pipeline { ... steps { script { acme.setBuildDisplayName() + + def lib = library( 'acme-shared-library' ).com.acme // preselect the package + echo lib.Constants.DEVOPS_EMAIL } } } Interesting log output: Only using first definition of library acme-shared-library Failure: java.lang.IllegalAccessException: com.acme.Constants was defined in file:///var/lib/jenkins/jobs/***/builds/42/libs/acme-shared-library/vars/acme.groovy which was not inside file:///var/lib/jenkins/jobs/***/builds/42/libs/acme-shared-library/src/ at org.jenkinsci.plugins.workflow.libs.LibraryStep$LoadedClasses.loadClass(LibraryStep.java:287) at org.jenkinsci.plugins.workflow.libs.LibraryStep$LoadedClasses.getProperty(LibraryStep.java:240) at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:174) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:456) at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:243) at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:52) at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:308) at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:241) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:238) at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:28) at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20) at WorkflowScript.run(WorkflowScript:28) at ___cps.transform___(Native Method) ... Using library directive on top (before pipeline ) (without a second library for dynamic class usage) and direct FQ access to class --- old/Jenkinsfile +++ new /Jenkinsfile -@Library( 'acme-shared-library' ) _ - import com.acme.Constants +library( 'acme-shared-library' ) pipeline { ... steps { script { acme.setBuildDisplayName() + + echo "devops email: ${com.acme.Constants.DEVOPS_EMAIL}" } } } No interesting log output anymore (cf. "Only using first definition of library acme-shared-library") Failure: groovy.lang.MissingPropertyException: No such property: com for class: groovy.lang.Binding at groovy.lang.Binding.getVariable(Binding.java:63) at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:224) at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:241) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:238) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221) at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:28) at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20) at WorkflowScript.run(WorkflowScript:27) at ___cps.transform___(Native Method) ... Using library directive in pipeline before first global var usage --- old/Jenkinsfile +++ new /Jenkinsfile -@Library( 'acme-shared-library' ) _ - import com.acme.Constants pipeline { ... steps { script { + def lib = library( 'acme-shared-library' ).com.acme // preselect the package acme.setBuildDisplayName() + echo "devops email: ${lib.Constants.DEVOPS_EMAIL}" } } } Failure: java.lang.IllegalAccessException: com.acme.Constants was defined in file:///var/lib/jenkins/jobs/***/builds/45/libs/acme-shared-library/vars/acme.groovy which was not inside file:///var/lib/jenkins/jobs/***/builds/45/libs/acme-shared-library/src/ at org.jenkinsci.plugins.workflow.libs.LibraryStep$LoadedClasses.loadClass(LibraryStep.java:287) at org.jenkinsci.plugins.workflow.libs.LibraryStep$LoadedClasses.getProperty(LibraryStep.java:240) at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:174) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:456) at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:243) at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:52) at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:308) at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:241) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:238) at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:28) at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20) at WorkflowScript.run(WorkflowScript:25) at ___cps.transform___(Native Method) ... Same for using library directive in pipeline before first global var usage and FQ access to class instead of preselect package --- old/Jenkinsfile +++ new /Jenkinsfile -@Library( 'acme-shared-library' ) _ - import com.acme.Constants pipeline { ... steps { script { + def lib = library( 'acme-shared-library' ) acme.setBuildDisplayName() + echo "devops email: ${lib.com.acme.Constants.DEVOPS_EMAIL}" } } Using new libraries section in pipeline --- old/Jenkinsfile +++ new /Jenkinsfile -@Library( 'acme-shared-library' ) _ - import com.acme.Constants pipeline { ... + libraries { + lib( 'acme-shared-library' ) + } + steps { script { acme.setBuildDisplayName() + echo "devops email: ${com.acme.Constants.DEVOPS_EMAIL}" } } Failure: groovy.lang.MissingPropertyException: No such property: com for class: groovy.lang.Binding at groovy.lang.Binding.getVariable(Binding.java:63) at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:224) at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:241) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:238) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221) at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:28) at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20) at WorkflowScript.run(WorkflowScript:29) at ___cps.transform___(Native Method) ... Oh! The following approach seems to work (linter is happy and pipeline works), but is a rather inconvenient/surprising workaround; thus, this is rather interesting for the bug fix, but not a real workaround, let alone a solution, I claim: not using libraries block in pipeline block, but using library including suffix for class in "src/" (as seen above it does not work, if the first library statement is without class usage suffix!) --- old/Jenkinsfile +++ new /Jenkinsfile -@Library( 'acme-shared-library' ) _ - import com.acme.Constants pipeline { ... steps { script { + echo "devops email: ${library( 'acme-shared-library' ).com.acme.Constants.DEVOPS_EMAIL}" acme.setBuildDisplayName() + } } IMHO this is very confusing and should be addressed in another issue, but presumably not in the linter (unless the initial/old approach via @Library and import will be re-recommended, and the linter accepts it).
          Reinhold Füreder made changes -
          Link New: This issue is related to JENKINS-38110 [ JENKINS-38110 ]

          I've hit the same issue in my scripted pipeline.  Specifically 

          java.lang.IllegalAccessException: com.acme.Constants was defined in file:///var/lib/jenkins/jobs/***/builds/45/libs/acme-shared-library/vars/acme.groovy which was not inside file:///var/lib/jenkins/jobs/***/builds/45/libs/acme-shared-library/src/

          Matthew Mitchell added a comment - I've hit the same issue in my scripted pipeline.  Specifically  java.lang.IllegalAccessException: com.acme.Constants was defined in file:///var/lib/jenkins/jobs/***/builds/45/libs/acme-shared-library/vars/acme.groovy which was not inside file:///var/lib/jenkins/jobs/***/builds/45/libs/acme-shared-library/src/
          Andrew Bayer made changes -
          Link New: This issue depends on JENKINS-46547 [ JENKINS-46547 ]

          I have been able to workaround this by using the following code:

          // JENKINS-42730
          def lib = library("libs")
          def ocathpr = lib.com.package.qe.helpers.Helper.new(this)
          // END JENKINS_42730
          
          pipeline {
          ......
          

          Raul Arabaolaza added a comment - I have been able to workaround this by using the following code: // JENKINS-42730 def lib = library( "libs" ) def ocathpr = lib.com. package .qe.helpers.Helper. new ( this ) // END JENKINS_42730 pipeline { ......
          CloudBees Inc. made changes -
          Remote Link New: This issue links to "CloudBees Internal CJP-6386 (Web Link)" [ 18959 ]

            Unassigned Unassigned
            bdouxx Boudoux Etienne
            Votes:
            15 Vote for this issue
            Watchers:
            25 Start watching this issue

              Created:
              Updated: