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
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
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.
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.
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.