Jenkins coordinates delivery work as jobs and Pipelines. Store a Pipeline in a
versioned Jenkinsfile because build logic, application code, and tool versions
must change under the same review process.
Controller, Agents, and Workspaces #
The controller stores configuration and build records, evaluates scheduling
decisions, serves the user interface, and coordinates agents. Builds should not
run on the controller. An agent supplies one or more executors; each executor can
occupy one Pipeline task at a time. Labels describe capabilities such as
linux, arm64, or docker, and a Pipeline’s agent selection constrains
where its workspace is allocated.
A workspace is mutable checkout and build state, not an artifact repository.
Concurrent builds can receive distinct workspace paths, and an ephemeral agent
can disappear after a stage. Publish outputs with archiveArtifacts, transfer
small files between stages with stash and unstash, or upload release
artifacts to a dedicated repository. Do not rely on files left by a previous
build.
Agents should have only the tools, network paths, and credentials required by their labels. Ephemeral agents reduce cross-build contamination, but reproducible builds still require pinned container images, toolchains, plugins, and dependency inputs.
Declarative and Scripted Pipelines #
Declarative Pipeline provides a validated structure around pipeline, agent,
stages, steps, environment, options, and post. Scripted Pipeline uses
Groovy control flow inside node and other Pipeline steps. Declarative
script { ... } can contain an imperative section, but large scripted regions
discard declarative validation and stage semantics. Put reusable policy in a
versioned Shared Library rather than copying Groovy between repositories.
pipeline {
agent { label 'linux && container' }
options {
timeout(time: 20, unit: 'MINUTES')
disableConcurrentBuilds()
}
stages {
stage('Test') {
steps {
retry(2) {
sh './mvnw --batch-mode verify'
}
}
post {
always { junit 'target/surefire-reports/*.xml' }
}
}
stage('Package') {
steps {
sh './mvnw --batch-mode package -DskipTests'
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
}
}
}
post {
always { deleteDir() }
}
}Pipeline steps persist execution state so a durable task can survive controller
restarts, but external commands must remain restart-safe. Use timeout to bound
stalled work and retry only for operations known to be idempotent. Deployment
retries can duplicate side effects. parallel reduces latency when branches do
not mutate the same workspace or external resource; use separate workspaces or
agents when isolation is required.
Credentials and Least Privilege #
Store secrets in Jenkins credentials and bind them for the smallest possible scope:
withCredentials([file(credentialsId: 'registry-token-file',
variable: 'REGISTRY_TOKEN_FILE')]) {
sh 'registry-client --token-file "$REGISTRY_TOKEN_FILE"'
}Masking reduces accidental log disclosure; it cannot protect a secret from untrusted build code running in the same scope. Avoid Groovy interpolation of string secrets because the value can enter process arguments or Jenkins-generated scripts before masking. File credentials supply a temporary protected file, but untrusted code in the same build context can still read it. Restrict credential IDs by folder, isolate untrusted pull requests from deployment jobs, and grant agents short-lived credentials for one environment.
Operating the Pipeline #
Use multibranch jobs or trusted webhooks to associate execution with an exact
commit. Preserve test reports and immutable artifacts according to a retention
policy. Configure post actions for cleanup and notifications even when a stage
fails. Protect the controller with authentication and authorization, review
plugin updates as controller code, back up JENKINS_HOME, and keep build agents
outside the controller’s trust boundary.
Comments
Read or comment on GitHub (sign-in required to comment)