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

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'))

Related

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.

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

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).

Executing scripts in a grails Job

I am working on two parts of a program. One that creates small groovy scripts and another that executes them in a Job. Each script is used to convert information from a map to a Domain object. The job will then save the domain object for future use.
Here is a small example.
Domain
class Report {
Date date
Country country
}
Map
Map<String, String> map = new HashMap<String, String>();
map.put("date", "2015-04-21 11:31:11");
map.put("country", "United States");
Date Script
String script = "x.date = Date.parse('y-M-d h:m:s', y['date'])"
The script is currently executed using Eval.
Eval(report, map, script)
There are other more complicated scripts that need to look up information and make decisions based on values.
The date script works fine but when the country script executes I get an error.
Country Script
String script = "import app.Country\nx.country = Country.findByName(y['country'])"
Error
Script1.groovy: 1: unable to resolve class app.Country
It seems like the Country class is not getting loaded in the call to Eval. How can I do an import in Eval? Should I use Eval or GroovyShell?
You need to instantiate a GroovyShell passing as argument the grailsApplication class loader, see the example below:
Bootstrap.groovy
Map bindingValues = new HashMap()
bindingValues.sessionFactory = sessionFactory
bindingValues.propertyInstanceMap = propertyInstanceMap
bindingValues.dataSource = dataSource
bindingValues.ctx = grailsApplication.mainContext
GroovyShell gs = new GroovyShell(grailsApplication.classLoader, new Binding(bindingValues))
gs.evaluate new File("docs/CargaAvaliacoes.groovy")
CargaAvaliacoes.groovy
import avaliacao.Colaborador
import modelo.ModeloAvaliacao
import programa.Programa
def programa = Programa.get(1)
def modelo = ModeloAvaliacao.get(1)
def avaliadores = ["02270789332":"1020016","11388449681":"1010002","02231772331":"1010004","04247774332":"1020002"]
def avaliacaoService = ctx.getBean("avaliacaoService")
avaliadores.each {
def avaliador = Colaborador.findByCpf(it.key)
def avaliados = Colaborador.findAllBySetorAndCpfNotEqual(it.value,it.key)
avaliados.each {
avaliacaoService.cadastrar(programa, modelo, avaliador, it)
}
}
** You need to specify the grailsApplication.classLoader because this class loader is used to load the Grails domain classes.

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

Using new Groovy Grape capability results in "unable to resolve class" error

I've tried to use the new Groovy Grape capability in Groovy 1.6-beta-2 but I get an error message;
unable to resolve class com.jidesoft.swing.JideSplitButton
from the Groovy Console (/opt/groovy/groovy-1.6-beta-2/bin/groovyConsole) when running the stock example;
import com.jidesoft.swing.JideSplitButton
#Grab(group='com.jidesoft', module='jide-oss', version='[2.2.1,)')
public class TestClassAnnotation {
public static String testMethod () {
return JideSplitButton.class.name
}
}
I even tried running the grape command line tool to ensure the library is imported. Like this;
$ /opt/groovy/groovy-1.6-beta-2/bin/grape install com.jidesoft jide-oss
which does install the library just fine. How do I get the code to run/compile correctly from the groovyConsole?
There is still some kinks in working out the startup/kill switch routine. For Beta-2 do this in it's own script first:
groovy.grape.Grape.initGrape()
Another issue you will run into deals with the joys of using an unbounded upper range. Jide-oss from 2.3.0 onward has been compiling their code to Java 6 bytecodes, so you will need to either run the console in Java 6 (which is what you would want to do for Swing anyway) or set an upper limit on the ranges, like so
import com.jidesoft.swing.JideSplitButton
#Grab(group='com.jidesoft', module='jide-oss', version='[2.2.1,2.3.0)')
public class TestClassAnnotation {
public static String testMethod () {
return JideSplitButton.class.name
}
}
new TestClassAnnotation().testMethod()
I finally got it working for Groovy Shell (1.6.5, JVM: 1.6.0_13). This should be documented better.
First at the command line...
grape install org.codehaus.groovy.modules.http-builder http-builder 0.5.0-RC2
Then in groovysh...
groovy:000> import groovy.grape.Grape
groovy:000> Grape.grab(group:'org.codehaus.groovy.modules.http-builder', module:'http-builder', version:'0.5.0-RC2')
groovy:000> def http= new groovyx.net.http.HTTPBuilder('http://rovio')
===> groovyx.net.http.HTTPBuilder#91520
The #grab is better used in a file than the shell.
Ok. Seems like this a short working demo (running from the groovyConsole)
groovy.grape.Grape.initGrape()
#Grab(group='com.jidesoft', module='jide-oss', version='[2.2.1,2.3.0)')
public class UsedToExposeAnnotationToComplier {}
com.jidesoft.swing.JideSplitButton.class.name
When run it produces
Result: "com.jidesoft.swing.JideSplitButton"
Very cool!!
The import statement must appear after the grabs.
Ps. At least one import statement must exists after the grabs
#Grab(group='com.jidesoft', module='jide-oss', version='[2.2.1,)')
import com.jidesoft.swing.JideSplitButton
public class TestClassAnnotation {
public static String testMethod () {
return JideSplitButton.class.name
}
}
Different example using latest RC-2 (note: Grab annotates createEmptyInts):
// create and use a primitive array
import org.apache.commons.collections.primitives.ArrayIntList
#Grab(group='commons-primitives', module='commons-primitives', version='1.0')
def createEmptyInts() { new ArrayIntList() }
def ints = createEmptyInts()
ints.add(0, 42)
assert ints.size() == 1
assert ints.get(0) == 42
Another example (note: Grab annotates getHtml):
// find the PDF links in the Java 1.5.0 documentation
#Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='0.9.7')
def getHtml() {
def parser = new XmlParser(new org.ccil.cowan.tagsoup.Parser())
parser.parse("http://java.sun.com/j2se/1.5.0/download-pdf.html")
}
html.body.'**'.a.#href.grep(~/.*\.pdf/).each{ println it }
Another example (note: Grab annotates getFruit):
// Google Collections example
import com.google.common.collect.HashBiMap
#Grab(group='com.google.code.google-collections', module='google-collect', version='snapshot-20080530')
def getFruit() { [grape:'purple', lemon:'yellow', orange:'orange'] as HashBiMap }
assert fruit.inverse().yellow == 'lemon'

Resources