Logging DSL
A small set of helpers in vars/utils.groovy gives every *Step.groovy a uniform, scannable log format. The goal: a dense "thread of the process" on the Jenkins console, with verbose details routed to a file that is archived only when the build fails.
Why there is a DSL
Ad-hoc echo + sh calls produce noisy, inconsistent logs that are hard to read, hard to diff, and hard to follow when three stages fail in a row. The DSL enforces a single visual shape across every step, so users can skim the status column (› ✓ ⚠ ✗ ▸) without reading every line.
Cheat sheet
| Helper | Purpose |
|---|---|
|
Normalise |
|
60-char |
|
Sub-step marker |
|
Status lines |
|
Verbose-only; silent unless |
|
|
|
Same as |
|
Collapsible block. Quiet mode: prints the header, suppresses body console output. Verbose mode: prints both. |
|
Archives |
|
Master-side file check; do not use inside |
Step integration pattern
Every *Step.groovy main body follows this shape:
def call(Map config = [:]) {
ansiColor('xterm') {
utils.logInit()
try {
utils.stage(1, 4, 'Resolve parameters')
utils.step('Loading dependencies.yaml')
utils.ok('Dependencies resolved')
utils.stage(2, 4, 'Render compose bundle')
utils.silentSh('yq filter', "yq '...' compose-mysql.yml > target.yml")
utils.detail('Service variables overlaid') // verbose-only
utils.stage(3, 4, 'Write meta.json')
utils.atomicWriteMeta(metaPath, metaData)
utils.ok("Env ${envName} configured")
utils.stage(4, 4, 'Done')
// ...
} catch (err) {
utils.archiveLogOnFailure()
utils.failureHints(err.message, hints, context)
throw err
}
}
}
The try / catch around the body is not optional — it is what ensures .qa-build.log survives a failure as a build artifact.
Visual style
-
Single-char prefixes (
› ✓ ⚠ ✗ ▸) line up into a readable column. Users read the column, not the sentence. -
Emojis are reserved for the stage-7 summary box in
createEnvStepand the image-override listings — do not sprinkle them elsewhere. -
Stage headers are
═-padded to 60 chars for consistent width across stages.
QA_LOG_VERBOSE — runtime switch
Global Jenkins env var that toggles verbose mode for every pipeline step at runtime. No restart required; the next build picks up the change.
| Value | Effect |
|---|---|
(unset) or anything but |
Quiet mode (default). |
|
Verbose mode. |
How to enable:
-
Manage Jenkins → System → Global properties → Environment variables.
-
Add
QA_LOG_VERBOSE = true. Save. -
Next build runs verbose.
|
|
| Switch | Scope | What it does |
|---|---|---|
|
global env var |
Verbose log output. |
|
Create-Environment parameter |
Preserve the env directory on failure for investigation. |
.qa-build.log
The logging DSL always writes the full verbose trace to .qa-build.log in the job workspace, regardless of QA_LOG_VERBOSE. The file is:
-
Created at the top of every step via
silentSh/silentShOut. -
Appended to as stages progress.
-
Archived only on failure by
utils.archiveLogOnFailure()so the build’s Artifacts panel holds the post-mortem trace. -
Removed by the next successful workspace cleanup — it is not a permanent log.
Download it from the build page’s Artifacts link to see the full trace when QA_LOG_VERBOSE is off.
Master-side vs runner-side
utils.exists is master-side only (@NonCPS + new File(…)). For runner-side paths (/opt/qa-envs/<env>/…) use fileExists inside the node(runner) { … } block. Getting this wrong typically looks like an ok("File present") followed by a compose up that says "no such file".
Failure hints
utils.failureHints(errorMessage, baseHints, context) prints a diagnostic block right before the exception propagates. Keep the hints list short and actionable ("check Harbor credential", "run with `QA_LOG_VERBOSE=true`", "verify port availability") — operators are usually scanning it in a rush.