Using a shared library class from a custom step with Jenkins pipeline shared libraries - jenkins

I am setting up a shared library for Jenkins pipelines and am trying to figure out how to import a class in the shared library into a custom step that I am writing.
Here's what the directory structure looks like:
src
--jenny
----util
------Versioning.groovy
vars
--calculateVersion.groovy
The Versioning.groovy file defines some static helper methods that do some stuff.
package jenny.util
class Versioner implements Serializable {
static bool checkForValidVersion(version) {
return true
}
}
I would like to call this method from the calculateVersion.groovy something like this:
def call(version) {
return jenny.util.Versioner.checkForValidVersion(version)
}
So that my declarative pipeline can call:
def valid = calculateVersion "1.0.0"
But I receive this error No such property: jenny for class: calculateReleaseVersions
Is it possible to reference the classes in the shared library from files in the vars to define custom steps and how is this done?

Yes it is possible. At least for us:
Just like in plain java (or groovy) we put an import statement into the groovy script in vars. In your case that would be something like:
import jenny.util.Versioner
def call(version) {
return Versioner.checkForValidVersion(version)
}
Another thing I just found: It looks like the file name of the class Versioner doesn't match the class name: Versioning.groovy. Could that be the issue?
If that doesn't work you propably want to upgrade your pipeline plugin version(s).

Related

Do i have to use "call{}" in a shared library when using it in a Jenkins pipeline?

I'm working on transforming a whole Jenkins from normal jobs to DSL/Pipelines. Had to implement a shared library for all the imports. In the said library there is a whole load of scripts.
Currently, all of them are set up like this:
package common
class Foo {
static String bar(String text) { stuff }
static String bar2(String text) { stuff }
static String bar3(String text) { stuff }
}
And in the pipeline:
#!/usr/bin/env groovy
#Library('jenkins-shared-libs') _
import common.*
There are many scripts and many methods. How, where, and can I not use call() to actually, "call" them?
If you want to invoke the bar method in the Foo class you could do any of these:
Option 1:
common.Foo.bar('some argument')
Option 2:
import common.*
Foo.bar('some argument')
Option 3:
import static common.Foo.*
bar('some argument')

Import groovy class in a pipeline Jenkinsfile

I need to be able to create classes and use them within a Jenkins pipeline.
Let's say I have a very simple groovy class, declared in a groovy script, looking as this:
class MyClass {
#Override
public String toString() {
return "toto";
}
}
return MyClass();
This class is located in the folder: Project\Buildfiles\Jenkins\com\external
Then in my Jenkinsfile I would do:
node('mynode') {
toto = load 'Project\Buildfiles\Jenkins\com\external\MyClass.groovy'
echo toto.toString()
}
And this actually works
However this do pose a certain numbers of issues with my IDE which does not understand what is happening. Also, this prevents me to have several constructor in my custom class.
What I have been trying to do, and for which I need help, is the following. In a file named ExternalClasses.groovy:
class Toto{
#Override
public String toString() {
return "toto";
}
}
class Tata{
#Override
public String toString() {
return "tata";
}
}
return this;
In the JenkinsFile:
node('mynode') {
external= load 'Project\Buildfiles\Jenkins\com\external\ExternalClasses.groovy'
toto = new Toto();
tata = new Tata();
}
And this fails
I have tried several approaches, used packages names, used the Toto.new() syntax, but none worked.
Any ideas ?
Edit about Shared Libraries:
I actually have a Shared library, it is used by several teams and contains very specific data which should be own by the teams and not by the library.
We need to be able to put out of the library things which does not belong to it. The purpose of this work is to alleviate the said library of non generic code.
You could use the Shared Library Feature. Upload your scripts into a VCS like Github/Bitbucket and use Jenkins-Jobs to execute them. They are available for all projects/jobs.

Jenkins+Groovy: Libraries

Situation is simple - IN A GLOBAL LIBRARY (OUTSIDE THE SANDBOX):
in src - a.b.c.Utils.groovy
in vars - Defaults.groovy
How do I call Defaults.groovy from within Utils.groovy?
In src:
#!groovy
package a.b.c
public class Utils implements Serializable {
def script
public def run() {
println(Defaults.text)
//groovy.lang.MissingPropertyException: No such property: Defaults for class: a.b.c.Utils
}
}
in vars:
#!groovy
public class Defaults {
public static def text = "hello world"
}
in Jenkinsfile:
#Library("ItLoads")
utils = new a.b.c.Utils(script:this)
...
utils.run()
so I tried to load the library explicitly
#!groovy
package a.b.c
public class Utils implements Serializable {
def script
public def run() {
println(script.library("ItLoads").Defaults.text)
//Only using first definition of library ItLoads
//java.lang.IllegalAccessException: Defaults was defined in file:///apps/opt/.../vars/Ansible.groovy which was not inside file:///apps/opt/.../src/
}
}
So, Defaults is defined somewhere, but I have no idea how to get to it...
If I try to use Defaults in the Jenkinsfile, it works.
HELP
Looking at your code I can see that you're not using the script object to access Defaults:
Instead of Defaults.text you should use something like script.Defaults.text.
Adding some links as a reference for future readers:
https://jenkins.io/doc/book/pipeline/shared-libraries/
How to access pipeline DSL in groovy classes(and not in Jenkinsfile)?

Using class from another groovy file as a type in a Jenkins pipeline script

I'm a groovy novice, so not sure if this is possible. I need something like an import, but not quite. Here is the simplified code example of what I'm trying to do:
in file FileToProcess.groovy I have
class FileToProcess implements Serializable {
String FileName
FileToProcess(fileName) {
this.FileName = fileName;
}
}
and then in a JenkinsFile I want to do something like
F1 = new FileToProcess('A');
List<FileToProcess> allFiles = new ArrayList<FileToProcess>();
allFiles.add(F1);
​for (FileToProcess file : allFiles) {
System.out.println(file.FileName);
}
Now, on StackOverflow I've found examples of how to instantiate a class from another file, for example here or here, and that solves the line
F1 = new FileToProcess('A');
but it does not show how to use that class as a type in a declaration, for example
List<FileToProcess> allFiles = new ArrayList<FileToProcess>();
gives me "unable to resolve class FileToProcess". I also know that using a class as a type like this should work, because it does when I put the class in the same JenkinsFile, so the problem seems to be just that the class is not visible in the JenkinsFile.
Is there a way to do this?
I'm not sure how you tried to setup your class libraries but I attempted the same while using a class from a pipeline shared library and it worked as intended
https://jenkins.io/doc/book/pipeline/shared-libraries/
I did do it a little differently:
assuming you places the file under src/org/Foo.groovy
import org.Foo
def list = new ArrayList<Foo>
list.add(new Foo('str1'))
list.add(new Foo('str2'))

access configuration/property files from src/groovy

I have a file under src/groovy and I have some properties that are in my Config.groovy and in external property file too. Normally if one want access properties its possible to use grailsApplication .configuration.property.name expression. I want to be able to access all those properties from this file that is under src/groovy directory. What I've tried so far
import grails.util.Holders
class ForkedTomcatCustomizer {
def application
void customize(Tomcat tomcat) {
println Holders.grailsApplication.config.property.name
}
}
gave me NPE saying that grailsAppliction is null
import org.codehaus.groovy.grails.web.context.ServletContextHolder as SCH
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes as GA
class ForkedTomcatCustomizer {
def application
void customize(Tomcat tomcat) {
def ctx = SCH.servletContext.getAttribute(GA.APPLICATION_CONTEXT)
def grailsAppliction = ctx.grailsApplication.getObject()
println grailsAppliction.config.property.name
}
}
the same - NPE because grailsAppliction is null
Is it possible to handle this situation somehow? Thank you!
Use the below and see if it works
println Holders.config.property.name
You don't need grailsApplication when using Holders.
The examples below are probably a little more complex than what you need, but they show how to get a configuration property at build time. I use them to merge two configuration files, but you might not need to do that.
This method returns a config property when called here at the CompileEnd event.
You could define a similar method in your app's _Events.groovy file that calls your own configuration holder class.
import org.codehaus.groovy.grails.commons.ConfigurationHolder;
class KeyAndSecret{
public static String consumerKey = ConfigurationHolder.config.consumerKey;
public static String consumerSecret = ConfigurationHolder.config.consumerSecret;
}
Try like this

Resources