Build output must be managed well so it can be downloaded, shared between agents, and not fill up the disk. This episode covers archiving artifacts with fingerprinting, transferring files between nodes with stash and unstash, and workspace cleanup strategies to keep Jenkins infrastructure healthy.

In episode 9 we centralized pipeline logic with Shared Libraries — now the Jenkinsfiles in all repos are thin and consistent. But there is a question often forgotten until the disk fills up or someone asks "where is the build output?": where does the build output go?
Imagine a factory that keeps producing goods but never tidies its warehouse. Finished goods are stored haphazardly, workers from the first floor cannot send goods to the second floor, and eventually the warehouse fills up until production stops. That is what happens to a Jenkins whose artifacts are not archived, whose files cannot be shared between agents, and whose workspaces are never cleaned.
In this episode we discuss three things that make build output reliable: archiveArtifacts to store build output and download it through the UI, stash and unstash to move files between stages and between agents, and workspace management so the disk never fills up and old builds do not pile up.
archiveArtifactsAfter the application is built successfully, the result must be stored as a build artifact. The archiveArtifacts step uploads files from the workspace to Jenkins, so they can be downloaded at any time from the build page:
stage('Build') {
steps {
sh 'mvn -q package'
}
}
stage('Archive') {
steps {
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
}
}The artifacts parameter accepts a glob pattern — here all jar files in the target directory. The fingerprint: true parameter enables fingerprinting: Jenkins computes the file checksum and tracks which build produced it and which builds used it. This is very useful for auditing: if there is a bug in a specific jar version, you can search for which build produced that jar.
To download it, open the job page → click a specific build → the Artifacts section → click the file name. A direct download URL is also available at the Jenkins address under /job/<job-name>/lastSuccessfulBuild/artifact/<file-name> — useful when other scripts want to fetch an artifact automatically.
Warning
Artifacts are stored on the controller disk. Archiving large files such as Docker images or installers of hundreds of MB will quickly fill the JENKINS_HOME disk. Rule of thumb: archive small, important output (jars, packages, reports), while large artifacts belong in an artifact repository such as Nexus, Artifactory, or a container registry — and store their URL as metadata.
stash and unstashNot every stage runs on the same agent. The parallel test stages from episode 7 can run on different nodes, and they all need the build output from the previous stage. The stash step stores files as an archive attached to the build, then unstash restores them on another agent:
stage('Build') {
steps {
sh 'npm run build'
stash name: 'build-output', includes: 'dist/**'
}
}
stage('E2E Test') {
agent { label 'tester-agent' }
steps {
unstash 'build-output'
sh 'npm run test:e2e'
}
}The Build stage produces the dist directory, then stores it under the name build-output. The E2E Test stage runs on an agent labeled tester-agent — a different agent — and restores that dist before running end-to-end tests. This lets the pipeline balance load: build on a fast machine, test on a dedicated machine.
A few things to understand:
stash name: 'build-output', includes: 'dist/**' specifies a glob pattern; you can also add exclude for specific files.A workspace is the agent working directory where pipelines execute steps. The problem is that every build that downloads dependencies, does a checkout, and produces files leaves traces. Without cleanup, the agent disk accumulates until it is full and builds fail with a disk full error.
Cleaning the workspace after a build. The cleanWs step from the Workspace Cleanup plugin deletes the workspace contents. The best place to call it is in the post { cleanup } block from episode 7, because it always runs at the end — including when a build fails:
pipeline {
agent any
stages {
stage('Test') {
steps {
sh 'npm test'
}
}
}
post {
always {
junit 'reports/**/*.xml'
}
cleanup {
cleanWs()
}
}
}Discarding old builds. Besides workspaces, accumulating build records also consume disk (artifacts, logs, metadata). The buildDiscarder step in the options block automatically prunes old builds:
pipeline {
agent any
options {
buildDiscarder(logRotator(numToKeepStr: '10', daysToKeepStr: '30'))
}
stages {
stage('Build') {
steps {
sh 'mvn -q package'
}
}
}
}The configuration above keeps a maximum of the last 10 builds, and builds older than 30 days are also discarded — whichever is reached first. This balances the need for history (for rollback and audit) against disk constraints.
Note
Understand the disk difference: JENKINS_HOME (controller disk) holds configuration, artifacts, and build history; workspaces live on the agent disk. Workspace cleanup protects the agent disk, while buildDiscarder protects the controller disk. Both need management, and at large scale there are additional plugins such as Disk Usage to monitor who is the biggest disk consumer.
To choose the right mechanism, here is the summary:
| Mechanism | Purpose | Shareable between agents? | Stored in | Size |
|---|---|---|---|---|
| archiveArtifacts | Distributing final output via the UI | Not directly | Controller disk | Small to medium |
| stash / unstash | Transferring files between stages within one build | Yes | Build archive | Small |
| Artifact repository | Long-term storage | N/A | Nexus, Artifactory, registry | Large |
The rule of thumb: stash to move files between stages in one build, archiveArtifacts for output the team must download, and an artifact repository for anything large or long-lived.
Everything combined into one pipeline: build, stash for use by parallel tests, archive the output, and full cleanup:
pipeline {
agent any
options {
buildDiscarder(logRotator(numToKeepStr: '10', daysToKeepStr: '30'))
}
stages {
stage('Build') {
steps {
sh 'npm ci'
sh 'npm run build'
stash name: 'build-output', includes: 'dist/**'
}
}
stage('Test & Archive') {
steps {
unstash 'build-output'
sh 'npm run test:unit'
archiveArtifacts artifacts: 'dist/**/*.js', fingerprint: true
}
}
}
post {
cleanup {
cleanWs()
}
}
}The full flow: the build produces dist, stashes it, then unstashes it in the next stage for testing and archiving. buildDiscarder keeps the build history slim, and cleanWs in the post block deletes leftover workspace every time the pipeline finishes — whatever the build outcome.
In episode 10 we dissected the lifecycle of build output: archiveArtifacts with fingerprinting to store and download build output via the UI, stash and unstash to move files between stages and between agents within one build, and workspace management — cleanWs in post { cleanup } to prevent the agent disk from filling up and buildDiscarder with logRotator to discard old builds from the controller disk.
The key takeaways to carry with you:
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true stores build output; fingerprinting enables tracing a file's origin.stash and unstash move files between agents within one build; do not stash large files.cleanWs() in post { cleanup } cleans the workspace every build, whatever the outcome.buildDiscarder limits the number and age of stored builds.So far you have mastered a complete pipeline foundation: from writing Jenkinsfiles to managing build output. In episode 11 we enter the security phase: Jenkins Security, RBAC & Authentication — disabling anonymous access, building an authorization model with Role-Based Strategy, and securing the controller from external threats. See you in episode 11!