5

I am trying to writing a Jenkins Shared Library for my CI process. I'd like to reference a class that is in the \src folder inside a global function defined in the \vars folder, since it would allow me to put most of the logic in classes instead of in the global functions. I am following the repository structure documented on the official Jenkins documentation: Jenkins Shared Library structure

Here's a simplified example of what I have:


/src/com/example/SrcClass.groovy

package com.example

class SrcClass {
  def aFunction() {
    return "Hello from src folder!"
  }
}

/vars/classFromVars.groovy

import com.example.SrcClass

def call(args) {
  def sc = new SrcClass()
  return sc.aFunction()
}

Jenkinsfile

@Library('<lib-name>') _
pipeline {
  ...
  post {
    always {
      classFromVars()
    }
  }
}

My goal was for the global classes in the /vars folder to act as a sort of public facade and to use it in my Jenkinsfile as a custom step without having to instantiate a class in a script block (making it compatible with declarative pipelines). It all seems pretty straightforward to me, but I am getting this error when running the classFromVars file:

<root>\vars\classFromVars.groovy: 1: unable to resolve class com.example.SrcClass
 @ line 1, column 1.
   import com.example.SrcClass
   ^

1 error

I tried running the classFromVars class directly with the groovy CLI locally and on the Jenkins server and I have the same error on both environments. I also tried specifying the classpath when running the /vars script, getting the same error, with the following command:

<root>>groovy -cp <root>\src\com\example vars\classFromVars.groovy

Is what I'm trying to achieve possible? Or should I simply put all of my logic in the /vars class and avoid using the /src folder?

I have found several repositories on GitHub that seem to indicate this is possible, for example this one: https://github.com/fabric8io/fabric8-pipeline-library, which uses the classes in the /src folder in many of the classes in the /vars folder.

ModoNoob
  • 51
  • 1
  • 4
  • Assuming you're running `groovy` from the root folder of your shared library, the correct classpath is the following: `groovy -cp src/ vars/classFromVars.groovy`. Your example is fine; I cannot see anything wrong in it. Try to commit changes, check if the global shared library configuration in Jenkins configuration page is set correctly, and test your library with the exemplary pipeline. It should work, or at least you should get a more detailed error message. – Szymon Stepniak Oct 23 '19 at 18:12
  • You're right about the `-cp` parameter! It works now when I run it locally. I hate to be one of those people, but it is now working both locally and on the server and I don't really know why it wasn't working in the Jenkins environment. Thank you very much! – ModoNoob Oct 23 '19 at 19:01

2 Answers2

1

I found that when I wanted to import a class from the shared library I have, to add a script step in the /vars I needed to do it like this:

//thanks to '_', the classes are imported automatically.
// MUST have the '@' at the beginning, other wise it will not work.
// when not using "@BRANCH" it will use default branch from git repo.
@Library('my-shared-library@BRANCH') _ 

// only by calling them you can tell if they exist or not.
def exampleObject = new example.GlobalVars() 

// then call methods or attributes from the class.
exampleObject.runExample()

Dor
  • 11
  • 3
0

As @Szymon Stepniak pointed out, the -cp parameter in my groovy command was incorrect. It now works locally and on the Jenkins server. I have yet to explain why it wasn't working on the Jenkins server though.

ModoNoob
  • 51
  • 1
  • 4