Solutions Delivery Platform

Create a Class

Library Structure

Classes should be placed in the src directory. It is recommended that a package be used and named after the library contributing the class.

Each loaded library’s src directory contents are synced to a common directory. Colliding file paths will result in an exception being thrown.

Serializability

In order to Jenkins pipelines to resume, a design pattern called Continuation Passing Style (CPS) has been implemented in the Pipeline Plugin. CPS works by continuously serializing the current state of the pipeline to disk such that if the pipeline were to be paused or Jenkins restarted, the pipeline could resume where it left off.

Therefore, every variable that’s persisted in the pipeline’s context must be serializable.

To help ensure that the classes that are contributed by a library are serializable, they should implement the Serializable interface.

For example, a Utility class coming from an example library:

package example

class Utility implements Serializable {}

Accessibility

Classes contributed by loaded libraries can be imported into the pipeline template, steps of the same library, and steps from other libraries.

Jenkins DSL Step Resolution

Library classes can not resolve Jenkins pipeline DSL functions such as sh or echo. A work around for this is to pass the steps variable to the class constructor to store on a field or through a method parameter.

For example, to use the echo pipeline step one could do the following:

package example

class Utility implements Serializable{
  void doThing(steps){
    steps.echo "message from the Utility class"
  }
}

and then from a step or template:

import example.Utility

Utility u = new Utility()
u.doThing(steps)

Accessing the Library Configuration

Unlike with library steps, the config and pipelineConfig variables are not autowired to library classes.

To access these variables, they can be passed to the class through constructor or method parameters.

For example:

package example

class Utility implements Serializable{
  def config
  Utility(config){
    this.config = config
  }

  void doThing(steps){
    steps.echo "library config: ${config}"
  }
}

and then from within a library step:

import example.Utility

void call(){
  Utility u = new Utility(config)
  u.doThing(steps)
}