Jenkins (Groovy) CI/CD Pipeline Guidelines
Jenkins Groovy Style
- Use four-space indentation, braces and no semicolons.
- Use explicit types for variables, parameters, return values, closure parameters and collection elements.
- Prefer
String,boolean,int,long,List<T>,Set<T>,Map<K, V>andClosurewhere applicable. - Use wrapper types such as
BooleanorIntegeronly whennullis meaningful. - Use
defonly for genuinely dynamic Jenkins API objects. - Use
camelCasefor variables, methods and parameters;UpperCamelCasefor classes; andUPPER_SNAKE_CASEfor constants. - Use descriptive Boolean names such as
shouldDeployandimageExists. - Use single quotes for plain strings and double quotes only when interpolation is required.
- Keep methods small and focused.
- Extract duplicated behavior within one Jenkinsfile into typed helper methods.
- Move behavior reused across Jenkinsfiles to a Jenkins Shared Library.
- Keep the Jenkinsfile focused on orchestration; place substantial build, parsing and processing logic in project scripts or build tools.
- Prefer simple
forloops when invoking pipeline steps repeatedly. - Avoid complex Groovy collection operations around pipeline steps.
- Values that remain in use across pipeline steps must be serializable.
- Do not keep non-serializable objects such as iterators, streams or matchers for use after a pipeline step.
- Use an explicit
forloop and capture the current value in a local variable when constructing parallel pipeline branches. This avoids variable-scoping issues and reduces the risk of CPS method mismatches. - Avoid
@NonCPSunless required. An@NonCPSmethod must not invoke pipeline steps. - Do not share mutable state between parallel branches.
- Do not override standard pipeline steps or access Jenkins internals directly.
- Pass credentials and user-controlled values through environment variables; never interpolate them into Groovy command strings.
- Use
returnStatus: trueonly when the exit code is handled explicitly. - Unexpected failures must fail or abort the build.
- Catch exceptions only to retry transient failures, add context and rethrow or perform cleanup without masking the original build result.
- Comment lifecycle decisions and exceptions, not self-explanatory code.
Resource Lifecycle
- Every
node,wsor equivalent workspace allocation must clean its workspace in a localfinallyblock. (SeeonNodeWithTemporaryWorkspace) - Cleanup must run on the same node and in the same workspace context in which the resource was created.
- Parallel branches must own and clean their resources independently.
- A locked critical section whose node label resolves to exactly one target server may clean that target later.
Cleanup must still run in
finally. - Temporary Docker resources must have targeted immediate cleanup and ownership labels that allow abandoned resources to be identified by host level fallback cleanup.
Build owned resources use
ci.owner=jenkins,ci.jobandci.buildlabels. Add aci.resourcelabel when a resource type needs to be distinguished. - Every temporary Docker image must be registered for pipeline cleanup before creation.
- Temporary containers and their temporary volumes must be removed together when their lifecycle ends.
- Build specific cleanup must be targeted and idempotent.
Broad Docker prune commands must not run from the Jenkins pipelines.
Broader host level retention belongs to infrastructure managed
cleanupdataand must have an explicit scope and retention policy. - Cleanup failures must be logged without masking the original build result or swallowing an abort.
Performance
Every pipeline change must be reviewed for its effect on runtime and controller or agent resource usage.
Avoid:
- broad locks that serialize independent work
- expensive computation or large data processing in pipeline Groovy
- repeated checkouts, builds, Docker image pulls or dependency installations
- unnecessary repeated cleanup or broad filesystem and Docker scans
- restricting work to specific agents without justification and documentation
- excessive logging, retries, polling, network calls or large
stashoperations
Expensive work should run once, be narrowly scoped and be reused where safe.
Changes affecting expensive operations, lock scope, agent selection, caching, retries or large data transfers must be investigated for their runtime and resource impact.