Issue
I have a shared library repo with this structure:
(root)
+- src
| +- com
| +- company
| +- DeploySteps.groovy
+- vars
| +- MainDeploySteps.groovy
This library importing to job via Jenkinsfile as follows:
library identifier: 'jenkinslib@master', retriever: modernSCM(
[$class : 'GitSCMSource',
remote : '[email protected]:jenkinslib.git',
credentialsId: 'jenkins-credentials'])
Class in repo in src/com/company/DeploySteps.groovy has a method (for example CheckoutSCM) which I want include in Jenkinsfile.
DeploySteps.groovy:
def CheckoutSCM() {
useful steps here
}
Is there a possible include this particular method in Jenkinsfile like
import com.company.DeploySteps
And then use it like:
CheckoutSCM('repo-here')
In Jenkinsfile later? I read documentation many times but no found answer is there possible import something from src
folder, not only from vars
.
Why I am asking because now when import: import com.company.DeployUtils
and then try invoke method CheckoutSCM()
see the error in Jenkins console output:
java.lang.NoSuchMethodError: No such DSL method 'CheckoutSCM' found among steps
with list of available methods below, where no mine CheckoutSCM
for sure)
So, is there possible import class from src
folder to Jenkinsfile?
P.S. I can access in Jenkinsfile MainDeploySteps as
MainDeploySteps {}
with no problems however.
Solution
I just wanted to add an answer to address a couple of questions from the OP and the subsequent comments.
am I understand you correctly that shared library expose ONLY global vars from 'vars' directory, to include that vars to Jenkinsfile? While trying include anything else to Jenkinsfile directly from 'src' folder is not how it was designed, because 'src' classes intended to be include to vars from 'vars' directory.
First let me give some background on shared libraries. There are 2 types referred to as dynamic shared library (defined using library
step) and global shared library (defined in Jenkins global config and accessed using @Library
annotation). Two important differences between these two are:
- Sandboxing restrictions do not apply to code in global shared library as the code in such libraries is treated as trusted (after all, it is configured globally by the administrator). This is not the case for dynamic shared libraries, as these are defined by users and so are not trustable.
- Classes from global shared libraries can be statically referenced in
Jenkinsfile
and get resolved as part of the compilation ofJenkinsfile
, but this is not possible for dynamic shared libraries as these libraries get defined at runtime and classes can't be cross checked at the time of compilation.
Coming to the OP, it is using the dynamic shared library concept, which means, classes can't be referenced statically. However there are some features put into dynamic shared library that can be taken advantage of. These details can be found in the documentation, but here is a summary:
library
step returns a representation of the library that can be assigned to a variable for further use, something likedef myLib = library identifier: ...
- Classes can be referenced using their fully qualified name on the library object, something like
def myCls = myLib.com.mycom.mypkg.MyClass
- What you receive is not the actual Groovy class, but a proxy like object that only permits limited operations on the underlying class.
- You can instantiate a new instance using
new
function and it works very similar to thenew
operator. You pass the same arguments that you would pass to a constructor, e.g.,myCls.new(arg1, arg2)
- You can get a static variable (though you can't set it) or call a static method using the proxy object just like it is the real class. If you are instantiating an object using
new
anyway, then you can access static members through the instance as well (normal Groovy semantics apply).
In both types of libraries, var files are exposed using the same mechanism (referred to also as global vars and custom steps), so there is no difference in usage. Also, the var file executes in the context of the library so with in the var file, you do not need the special syntax to access the classes, whether they are in global or dynamic shared libraries.
Now to answer the real question in the OP, it is possible to call CheckoutSCM
from the dynamic shared library. If it is defined as a static function, it can be invoked using myLib.com.company.DeploySteps.CheckoutSCM('repo-here')
and if it is defined as a non-static method, it can be invoked using myLib.com.company.DeploySteps.new(...).CheckoutSCM('repo-here')
. However in both cases the DeploySteps
class will not be able to access the steps API so even a simple echo
will not work. One traditional workaround is to provide the this
instance of Jenkinsfile
as a parameter (e.g., CheckoutSCM(this, 'repo-here')
) which then gets assigned to a steps
parameter (can be named anything) inside the function. You would then invoke all step calls on the steps
parameter, e.g., steps.echo '...'
.
Answered By - haridsv
Answer Checked By - Mary Flores (JavaFixing Volunteer)