Declarative Pipeline Syntax, agent, stages, steps, options, parameters, environment, tools, and post: Configuration, Design Choices, and Tradeoffs
Make deliberate Declarative design choices about agent scope, environment scope, timeouts/retries, script escape hatches, tool placement, evidence, and rollback.
Learning objectives
- Compare top-level and stage-level agents using queue time, isolation, workspace continuity, and cost.
- Choose pipeline- versus stage-scoped environment values based on ownership and least exposure.
- Distinguish Declarative options from step wrappers such as timeout/retry.
-
Use
scriptonly when Declarative/steps cannot express the required bounded logic clearly. - Document prerequisites, affected state, rollback, and evidence for each Pipeline design choice.
1. Declarative design is resource and state design
Two Jenkinsfiles can perform the same commands and still have very
different operational properties. Where you place
agent changes executor occupancy and workspace
continuity. Where you place environment changes value
exposure. Whether you use a stage option or a step wrapper changes
what lifecycle interval is bounded. Whether you use
script changes how much logic escapes Declarative's
structured model.
Choose syntax by the state and failure boundary you need—not by which form is shortest.
2. Top-level agent versus stage-level agents
| Question | Top-level agent | agent none + stage agents |
|---|---|---|
| Executor occupancy | Potentially held across all stages and waits inside steps. | Allocated only for stages that request one. |
| Workspace continuity | Simple; stages normally see one workspace context. | Do not assume files transfer between stages/nodes. |
| Toolchain variation | Best when stages share one compatible agent. | Strong when build/test stages need different labels/toolchains. |
| Failure isolation | Agent loss can affect more of the run. | Each stage can reacquire an appropriate agent. |
| Human waits |
Easy to accidentally hold capacity with an
input step.
|
Stage-level input can wait before allocation.
|
If stage agents differ, treat data movement explicitly with SCM
checkout, deterministic recreation, stash/unstash, or
archived/external artifacts. Workspace coincidence is not a dataflow
contract.
3. Pipeline versus stage environment
Pipeline-level environment is appropriate for non-secret values truly shared by every stage, such as a synthetic application identifier. Stage-level environment narrows exposure and makes ownership clearer for values used only in one stage.
environment {
APP_NAME = 'catalog-lab'
}
stages {
stage('Package') {
environment {
FORMAT = 'tar'
}
steps {
sh 'printf "%s %s\\n" "$APP_NAME" "$FORMAT"'
}
}
}
For credentials, prefer the smallest practical scope. Secret masking is a defense-in-depth feature, not permission isolation. A process running under the same agent/user context may be able to inspect environment/process data depending on the platform and design.
4. options versus step wrappers
A top-level or stage options block expresses policy
around the Pipeline/stage. A timeout or
retry step inside steps wraps a specific
body of execution. These are not always equivalent.
| Need | Prefer | Reason |
|---|---|---|
| Bound an entire stage including stage lifecycle | Stage options { timeout(...) } |
Policy is visible at stage boundary; allocation timing follows documented stage-option semantics. |
| Retry one flaky read-only network operation | retry(n) { ... } around that step/body |
Avoids repeating unrelated work or side effects. |
| Global maximum run duration | Top-level timeout option | One clear run-level guardrail. |
| Time-limit one external command | timeout { sh ... } |
Narrowest affected scope. |
Never wrap non-idempotent deployment/publication side effects in blind retries. Verify external state before retrying.
5. Declarative structure versus script escape hatch
The script step allows Scripted Pipeline/Groovy inside
Declarative steps. It is useful for bounded logic that
cannot be expressed cleanly with ordinary steps/directives. It
should not become a hiding place for an entire second Pipeline
language.
steps {
script {
def allowed = ['sandbox', 'qa']
if (!allowed.contains(params.TARGET)) {
error "Unsupported TARGET"
}
}
sh 'printf "validated target=%s\\n" "$TARGET"'
}
Here the script block performs a small controller-side validation. Heavy computation, network loops, file processing, and long-running work belong in agent-side tools/steps rather than Groovy executed by the Pipeline engine.
6. Tool placement follows agent placement
If one top-level agent serves the whole Pipeline, top-level
tools can be simple. With agent none,
define tools in the stage that acquires an agent. Remember that
Declarative's built-in tool directive currently covers configured
Maven, JDK, and Gradle tools; other ecosystems may rely on dedicated
plugins, wrappers, or pre-baked agent/container images.
7. when is routing policy, not authorization
when decides whether a stage should execute based on
branch, expression, environment, changeset, and other supported
conditions. It does not authorize a human or service identity. A
deployment stage skipped because TARGET != 'qa' is a
control-flow decision, not proof that unauthorized users cannot
alter or trigger the job.
8. Design post around evidence ownership
Stage-level post is useful when evidence belongs to
that stage's execution context. Pipeline-level post is
useful for final run-level status. If cleanup requires an external
resource identifier, save that identifier before the risky action
and make cleanup bounded/idempotent.
Do not make the only copy of failure evidence something your cleanup step deletes.
9. Worked scenario: three-stage synthetic delivery
Requirements: compile with JDK/Maven, run tests on a generic Linux agent, then pause for approval before writing a synthetic “promotion” record. No production system exists.
| Choice | Decision | Prerequisite | Observable evidence | Rollback |
|---|---|---|---|---|
| Agent strategy |
agent none; stage-specific
lab-linux
|
Agent label online | Queue/node/workspace per stage | Revert Jenkinsfile commit |
| Tools |
Stage-local jdk21-build, maven-3.9
|
Configured/verified tool definitions | Version output in artifact | Restore previous tool name/revision |
| Approval | Stage input before agent |
Authorized approver in lab | Input action + later node allocation | Abort without side effect |
| Target | Choice parameter sandbox|qa |
No free-form production values | Recorded non-secret parameter | Trigger a new run with corrected immutable input |
| Evidence | Archive per-stage text/checksum | Workspace only during stage | Archived artifacts/fingerprints | Artifacts stay with original run |
10. Decision checklist
- Which executor must be held, and for how long?
- Which values must be visible to every stage versus one stage only?
- Does a retry repeat an external side effect?
-
Is a
scriptblock doing orchestration or accidentally doing heavy work on the controller? - What source SHA and plugin/tool versions make the run reproducible?
- What evidence survives workspace deletion?
- What exact Jenkinsfile commit reverses the configuration change?
Knowledge check
When is a top-level agent attractive?
When stages share one compatible execution context and workspace continuity/capacity cost is acceptable.
Why prefer stage-scoped environment for a value used by only one stage?
It narrows exposure and makes ownership/intent clearer.
Why can blindly retrying a deploy step be unsafe?
The first attempt may already have changed external state; repeating it without verification can duplicate or corrupt the side effect.
What is a good use of script?
Small bounded dynamic logic that cannot be expressed cleanly with Declarative directives/steps, not heavy controller-side processing.
Does when replace authorization?
No. It is control-flow routing, not an identity/permission boundary.
Official references and version notes
- Jenkins LTS changelog — current LTS line and tested Java configurations.
-
Pipeline Syntax
— authoritative Declarative sections/directives, scopes, options,
parameters, environment, tools,
when,input, andpost. - Using a Jenkinsfile — Pipeline-as-Code, environment, credentials, parameters, and source-controlled Jenkinsfiles.
- Jenkins Pipeline handbook — Pipeline concepts and execution model.
- Pipeline: Declarative — Declarative Pipeline implementation and current compatibility.
- Pipeline — Pipeline plugin aggregator baseline.
- Credentials Binding — credential-binding behavior and secret-handling cautions.
- Pipeline: Stage View — optional visualization; it is not the source of execution truth.
Rechecked on 2026-09-16. Examples assume
Jenkins 2.568.3 LTS, tested with Java 21 and 25,
Pipeline aggregator 608.v67378e9d3db_1, Pipeline:
Declarative 2.2293.v6e7193cec599, Credentials
Binding 728.v902a_273b_8947, and optional Stage
View 2.41. Declarative 2.2293 requires Jenkins
2.504.3 or newer. Labs reuse the Chapter 08 tool names
jdk21-build and maven-3.9; verify what
exact binaries those names resolve to on your disposable agent
before running. Plugin versions and supported directives change
independently, so capture the installed baseline rather than
assuming these versions forever.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.