Solutions Delivery Platform

Initialization Process

Understanding the Initialization Process is the key to understanding the Jenkins Templating Engine.

So what exactly do I mean by "Initialization Process"? The Initialization Process is what happens between a pipeline run beginning and the user-defined pipeline template being executed.

Start at the Beginning: TemplateEntryPointVariable

The TemplateEntryPointVariable is where it all starts, specifically the getValue() method.

Aggregate the Pipeline Configuration Files

The first thing JTE does is gather all of the Pipeline Configuration Files and merge them together to produce an aggregated pipeline configuration file.

That process is as follows.

Create a New PipelineConfig Object

The PipelineConfig class is responsible for storing the aggregated pipeline configuration (represented as a PipelineConfigurationObject). It also contains the business logic related to merging multiple pipeline configurations. Upon creation, the default pipeline configuration is read from the resources directory.

Aggregate the Pipeline Configurations

In JTE, a Governance Tier stores a hierarchical pipeline configuration and a list of Library Sources that pipelines under this tier inherit. The Global Governance Tier is configured under Manage Jenkins > Configure System. Subsequent tiers are defined on folders.

Therefore, you create governance hierarchies in JTE by creating folder hierarchies and when appropriate, configuring the folder’s Governance Tier with a pipeline configuration file. JTE will aggregate all the pipeline job’s parent pipeline configuration files to produce an aggregated pipeline configuration that will subsequently be used to configure the pipeline for this run.

JTE fetches the configured Governance Tiers in order via the static GovernanceTier.getHierarchy(). For each tier, we call tier.getConfig() which returns the parsed result of a pipeline configuration file, a PipelineConfigurationObject.

We then pass this PipelineConfigurationObject to the PipelineConfig’s join method, which merges the current pipeline configuration with the incoming pipeline configuration and logs the modifications using the TemplateLogger

TemplateConfigDSL.parse(String file) is used to translate JTE’s custom configuration DSL into a PipelineConfigurationObject.

Prepare the Binding

The trick to the Jenkins Templating Engine is that pipeline templates get executed just like Jenkinsfiles. It’s just that this initialization process prepares the script environment by populating some variables (called Primitives in JTE) in the script binding before executing the template.

In groovy, the script binding is where undeclared variables are stored. It can be thought of as a global key-value store.

def x = 1 // variable is declared, and therefore not stored in the binding
y = 2 // variable is not declared and stored in the binding

y = 2 is the same as saying getBinding().setVariable("y", 2)

JTE works because the Jenkins pipelines will execute variables stored in the binding that respond to the call method, a feature introduced here.

Custom Binding Implementation

JTE uses a custom script binding implementation, the TemplateBinding, to prevent loaded Primitives from being overwritten during intialization or accidentally by library developers.

Calling All Injectors

Everything JTE populates the binding with (various Primitives and steps loaded from libraries) are extensions of the TemplatePrimitive class.

Extending the TemplatePrimitive class is what marks the object as "protected" in the TemplateBinding, preventing it from being overridden inadvertently.

Each primitive has an associated TemplatePrimitiveInjector that takes the aggregated pipeline configuration, parses it, and creates instances of the primitive to inject it into the binding.

Execute the Template

At this point, the pipeline’s runtime environment has been appropriately hydrated based upon the aggregated pipeline configuration. We can now execute the TemplateEntryPoint, which optionally checks out the branch source associated with the pipeline, determines the pipeline template, and executes it.