-
Bug
-
Resolution: Unresolved
-
Major
-
None
-
last jenkins.
all plugins up-to-date
-
Powered by SuggestiMate
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() ^
- depends on
-
JENKINS-46547 Add support for defining Declarative pipelines in shared libraries
-
- Closed
-
- is related to
-
JENKINS-38110 Library section within declarative syntax to explicitly load shared libraries
-
- Closed
-
- links to
[JENKINS-42730] declarative-linter don't work with shared library
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) ...
- Interesting log output:
- 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) ...
- Failure:
- 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) ...
- Failure:
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).
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/
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 { ......
rarabaolaza Did you try that code ? because it returns the same error as mmitche !
Did someone figured out this error ?
The workaround of rarabaolaza is working for me. Instantiating the object before it is used inside the shared library itself.
So something like
def lib = library("libs") def o = lib.com.package.classA.new() customStep() // step which is defined in "lib" and also instantiates classA o.method()
works, while something like
def lib = library("libs") customStep() // step which is defined in "lib" and instantiates classA lib.com.package.classA.new().method() // java.lang.IllegalAccessException
does not
I am seeing this IllegalAccessException too. In my case, I have a util function that takes the library object and the name of the class. It navigates the package and accesses the class using Groovy dynamic attribute name syntax (obj."$attr") and then call new() on it. This works fine when the class is in the same sharedlib as the util function, but if I pass another sharedlib, then I get the exception.
To be specific, I am hitting the issue reported by mmitche which comes from here:
if (!actual.startsWith(srcUrlC)) { throw new IllegalAccessException(name + " was defined in " + actual + " which was not inside " + srcUrlC); }
This looks like a different issue than the one reported by OP, so not sure why this was classified as a linter issue.
FWIW, I was able to solve my above mentioned issue. The issue in my case was that I was indeed making use of a wrong lib object. My logic resolved the package path and assumed that a non-null object implies that the package existed in the lib, but after going through the code, I realized that it will never return null and it is only valid if the class can be resolved, so after I adjusted the logic, it is using the right lib object to resolve and works as expected.
What is strange is that the code is able to resolve classes from any lib, so it is really a responsibility of the user to make use of the right lib.
Trying to convert pipelines from @Library notation to dynamic library step (so we can use branch names as parameter, or same branchname of shared lib as the branchname of pipeline/component source, etc.) I've also stumbled upon this issue.
Like for posters above, it seems that when I use just sort-of-qualified names of classes (with static methods and data fields), I get the "was defined in ... which was not inside" error:
def libmpci = library("com.myproduct.ci@${BRANCH_NAME}").com.myproduct.ci // preselect the package // use helper class (with static properties to init it) - ok before a JSL step: libmpci.Utils.indentLinesSpacenum = 3 // use step from "vars" initDebugSettings(true, false) // use helper class (with static properties to init it) - fails after a JSL step: libmpci.Utils.indentLinesPrepend = '|' // => java.lang.IllegalAccessException: com.myproduct.ci.Utils was defined in file:///var/lib/jenkins/jobs/SUTLockable-test/builds/488/libs/4a46ae3db26fbcc99db4b40afd24409503b2223922e231a06af47b826ec7a04b/vars/initDebugSettings.groovy which was not inside file:///var/lib/jenkins/jobs/SUTLockable-test/builds/488/libs/4a46ae3db26fbcc99db4b40afd24409503b2223922e231a06af47b826ec7a04b/src/
And notably, the step source under vars/ is the last step called in the pipeline before the "offending" call into src/ class (I did waste some time to track down where such step's source might reference the class - some do, some don't).
As I found (thanks to posters above), it seems like the trick is to replace "import" lines for classes we want to use with same-named new() calls, e.g.:
// Obsoleted "Static library" call: //@Library('com.myproduct.ci@wip-123456') _ //import com.myproduct.ci.Utils; // New dynamically-loaded library call: def libmpci = library("com.myproduct.ci@${BRANCH_NAME}").com.myproduct.ci // preselect the package def Utils = libmpci.Utils.new()
...and on the upside this seems (so far) to not require further changes to convert the code (e.g. no need to replace Utils => libmpci.Utils all over the place), so code like this works for both, I hope (gotta test over time):
initDebugSettings(true) Utils.indentLinesSpacenum = 3 Utils.indentLinesPrepend = '|'
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.