Solutions Delivery Platform

Parameterizing Libraries

One of the major benefits of organizing your pipeline code into libraries is the ability to reuse these libraries across different teams.

In order to achieve this level of reusability, it’s best to externalize hard coded values as parameters that can be set from the pipeline configuration repository.

Pass Parameters Through the Pipeline Configuration

When specifying a library to be loaded, users can also pass arbitrary configurations to the library:

libraries{
  example{ (1)
    someField = "my value" (2)
    nested{ (3)
      someOtherField = 11 (4)
    }
  }
}
1 The name of the library to be loaded
2 A root level library configuration option
3 A block name to pass nested configuration
4 A nested library configuration
  1. Library parameters can take an arbitrary structure. All parameters can be at the root level or a nested structure can be created to group related configurations together.

  2. Library parameter values can be any serializable Groovy primitive. Typically, parameters are boolean, numeric, String, or array.

Accessing Library Configurations Within Steps

The Jenkins Templating Engine injects a config variable into each step. This config variable is a map whose keys are the library parameters that have been provided through the pipeline configuration.

The config variable is only resolvable within a library step and only contains the configuration for the step’s library.

If you need to access the entire aggregated pipeline configuration, JTE injects a pipelineConfig variable that can be accessed anywhere.

Validating Library Configurations

The pipeline configuration file is a custom DSL "builder" syntax that takes arbitrary parameters. This design has simplified the implementation of the Jenkins Templating Engine while increasing its extensibility.

The downside of this approach is that users can define whatever fields they want to. For library developers, this means that a mechanism is needed to validate user configurations passed to libraries.

The Library Configuration File

The root of a library can contain an optional library_config.groovy file. Through the library configuration, library developers are able to perform basic types of validation against the library configuration.

The library configuration file follows the following format:

fields{ (1)
  required{} (2)
  optional{} (3)
}
1 the fields block is used to specify expected library configurations
2 library configurations that are required are listed in the required block
3 library configurations that are optional (meaning they likely have a default value) are listed in the optional block

Within the required and optional blocks, list the parameters the library supports in a parameterName = <Validation Type> format.

If a libary does not include a library configuration file, then users can supply arbitrary parameters to the library from the pipeline configuration.

If a library does include a library configuration file, then users will only be able to supply parameters thare are listed within the required and optional blocks. The presence of extraneous parameters will fail the build.

The library configuration supports several different validation types for library parameters.

Type Validation

Type validation confirms that a library parameter is an instance of a particular type.

The supported types for comparison are:

The current options for data types to test for are:

  • boolean / Boolean

  • String

  • Integer / int

  • Double

  • BigDecimal

  • Float

  • Number

For example,

library_config.groovy
fields{
  required{
    parameterA = String (1)
    parameterB = Number (2)
    parameterC = Boolean (3)
  }
  optional{
    parameterD = String (4)
    parameterE = Boolean (5)
  }
}
1 ensures that parameterA was configured and is an instance of a String
2 ensures that parameterB was configured and is an instance of a Number
3 ensures that parameterC was configured and is an instance of a Boolean
4 if parameterD was configured, ensures it is a String
5 if parameterE was configured, ensures it is a Boolean

Enum Validation

The enum validation ensures that a library parameter value is one of the options defined by a list in the library configuration.

For example,

library_config.groovy
fields{
  required{
    parameterA = [ "a", "b", 11 ] (1)
  }
}
1 ensures that parameterA was configured and is set to either "a", "b", or 11

Regular Expression Validation

Regular expression validation uses Groovy’s match operator to determine if the parameter value is matched by the regular expression.

For example

library_config.groovy
fields{
  required{
    parameterA = ~/^s.*/ (1)
  }
}
1 ensures that parameterA starts with s

Nested Parameters

Library parameters can be arbitrarily nested within the pipeline configuration.

For example, the following pipeline configuration would be valid to pass the example.nestedParameter parameter to a library named testing.

Pipeline Configuration
libraries{
  testing{
    example{
      nestedParameter = 11
    }
  }
}

To validate that example.nestedParameter is a configured and is a number, the library configuration would be:

Library Configuration
fields{
  required{
    example{
      nestedParameter = Number
    }
  }
}

To validate nested library parameters in the library configuration, nest their validation in the same structure within the required or optional blocks.

Advanced Library Validations

For library parameter validations that more complex than what can be accomplished through the library configuration functionality, library developers can alternatively create a step annotated with the @Validate Lifecycle Hook.

Methods within steps annotated with @Validate will execute prior to the pipeline template.

For example, if a library wanted to validate a more complex use case such as ensuring a library parameter named threshold was greater than or equal to zero but less than or equal to 100 the following could be implemetned:

Example Groovy Validation
@Validate (1)
void call(context){ (2)
  if(config.threshold < 0 || config.threshold > 100){ (3)
    error "Library parameter 'threshold' must be within the range of: 0 <= threshold <= 100" (4)
  }
}
1 The @Validate annotation marks a method defined within a step to be invoked prior to template execution.
2 This example defines a call() method, but the method name can be any valid Groovy method name.
3 Here, a Groovy if statement is used to validate that the threshold parameter fall within a certain range.
4 If the threshold variable does not meet the criteria, the Jenkins pipeline error step is used to fail the build. The warning step could also be used if the pipeline user should be notified but the build should continue.

This approach allows library developers to use Groovy to validate arbitrarily complex library parameter constraints. The method annotated with @Validate can be in its own step file or added as an additional method within an existing step file.

The example above assumes that the threshold library parameter has been configured as part of the pipeline configuration. This could be also be validated using Groovy or by combining the functionality of the library configuration file to set the threshold parameter as a required field that must be a Number.