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.
The TemplateEntryPointVariable is where it all starts, specifically the getValue()
method.
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.
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.
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
Note
|
|
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.
Note
|
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
|
JTE works because the Jenkins pipelines will execute variables stored in the binding that respond to the call
method, a feature introduced here.
JTE uses a custom script binding implementation, the TemplateBinding, to prevent loaded Primitives from being overwritten during intialization or accidentally by library developers.
Everything JTE populates the binding with (various Primitives and steps loaded from libraries) are extensions of the TemplatePrimitive class.
Important
|
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.
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.