qaUiScripts — Build-time Active Choices Factory
Large Active Choices parameter scripts (DEP_GRAPH, SERVICE_VARIABLES, RESOURCE_ESTIMATE, FINAL_PREVIEW, ALLOW_MISSING_DEPS, GLOBAL_VARIABLES, OWNERS_LIST, OWNERS_PREVIEW, plus shared CSS+JS) are produced by vars/qaUiScripts.groovy and reused across the Create / Update / Delete / Manage jobs.
Build-time composition, not runtime dispatch
Every method on qaUiScripts returns a String. That String is consumed at pipeline build time — inside setupParameters() on the master, while the shared library is loaded — and embedded into an Active Choices parameter:
script: [
sandbox: false,
script: qaUiScripts.depGraphScript() // build-time composition
]
The returned body then runs later, every time Jenkins re-renders the parameter form, inside the Active Choices sandbox. The shared library is not available there.
|
Do not reference |
For mode-parameterised methods (create vs update), the mode resolves at build time too — no runtime branching inside the sandbox body.
Available methods
| Method | Mode-parameter | Purpose |
|---|---|---|
|
no |
The CSS+JS superset injected via the hidden |
|
no |
Wrap a panel body in the "pick an env name first" gate used by |
|
no |
Same gate for CascadeChoice parameters (radio / dropdown / checkbox sources). |
|
no |
SVG dependency-graph renderer driven by |
|
|
Per-service |
|
no |
CPU / RAM / disk estimate summed from |
|
|
Validation banner + summary. |
|
no |
Opt-in checkbox surfaced when |
|
|
Rich |
|
no |
Multi-checkbox picker of Jenkins logins for |
|
no |
Live HTML diff of proposed vs saved |
|
Build-time vs runtime
These methods run on the Jenkins master during |
Cross-job communication via _UI_STATE
sharedCssJs() injects a hidden parameter named _UI_STATE that every reactive panel reads and writes. It carries an aggregate JSON snapshot of the current form so derived parameters (SERVICE_VARIABLES, FINAL_PREVIEW, DEP_GRAPH) can render without chaining through the referencedParameters cascade. This matters because DynamicReferenceParameter cannot drive another parameter (see DRP vs CascadeChoice).
Escaping contract
The strings returned by qaUiScripts. methods live inside Groovy triple-quoted literals ('''…'''). When the outer parser reads the source file, it processes *one level of escape sequences. What reaches the Active Choices sandbox is what is left over.
Consequence: anything that must survive to the sandbox has to be double-escaped at source.
| In the Groovy source file | Inside the sandbox body | Intended regex |
|---|---|---|
|
|
whitespace class |
|
|
newline |
|
|
literal double quote |
|
|
GString interpolation at build time — captures the value of |
A single-backslash regex like /\s+/ written inside '''…''' gets compiled by the outer parser, which reads \s as an unknown escape and silently emits s. That is why the symptom is often a fallback rendered at runtime with no stack trace — the script compiled to something that is not a regex.
String-multiply + GString concat trap
Groovy’s CPS interpreter swallows the inner text when you chain String * int + GString in a single expression:
// BAD — CPS drops the '${envName}' substring
echo ('=' * 40) + "Env: ${envName}" + ('=' * 40)
// GOOD — build explicit String locals first
def bar = '=' * 40
def title = "Env: ${envName}"
echo bar + title + bar
This trap is not specific to qaUiScripts.groovy, but the "build each String part as a local first" rule shows up most often in the banner / summary renderers.
DRP trailing-comma trap
DynamicReferenceParameter submits values with a trailing comma ("value,"). Anything that compares a DRP value to a string literal must strip leading / trailing commas and whitespace first:
def raw = (binding.variables[paramName] ?: '').toString()
def clean = raw.replaceAll(/^[\s,]+|[\s,]+$/, '')
if (clean == 'manage-owners') { ... }
Inside a triple-quoted qaUiScripts body, that regex needs to be written as /^|[\\s,]$/.
Summary
-
qaUiScripts.*— returns aString, called duringsetupParameters(). -
Inside that String: no shared library, double-escape slashy regex, mind the
_UI_STATEhidden parameter, and strip DRP trailing commas before comparing. -
Anything structured that multiple panels need should travel through
_UI_STATE, not throughreferencedParameters.