The Post Section in Jenkins
Learn how Jenkins decides what happens after your pipeline finishes: cleanup, reports, notifications and final decisions, explained step by step from the very first idea to production-grade habits.
Every build ends. Some end happily, some end with a red cross, some are stopped halfway by a tired engineer, and some simply run out of time. What matters is what your system does in the last few seconds, because that is when test reports must be saved, files must be deleted, and the right people must hear the news. If those tasks are forgotten, servers slowly fill with junk, teams miss failures, and nobody trusts the pipeline.
Jenkins gives you one dedicated place for all of this work: the post section. It is a small block of a pipeline file that says, “no matter how this run went, here is what to do at the end.” This guide starts from zero. It explains every new word when it first appears, uses everyday pictures to make ideas stick, and then moves step by step into the details that senior engineers use in real production systems handling hundreds of builds a day.
By the end you will know what each post condition means, in what order they run, where to place them, how they interact with agents and workspaces, what can go wrong, and how to design end-of-build behavior that is safe, quiet when it should be, and loud when it must be.
1What Is the Post Section?
A first, plain-language look at the idea before any details.
Jenkins is a free, open-source automation server. Teams use it to build software, test it, and deliver it to servers without doing every step by hand. The work Jenkins performs is described in a pipeline, which is simply a recipe written as a text file, usually named the Jenkinsfile. A pipeline is split into stages, such as Build, Test and Deploy, and each stage contains steps, which are the individual actions, like running a command or copying a file.
The post section is a part of that recipe that runs when a stage or the whole pipeline is finished. Its job is to react to the outcome. It can say “always do this,” “only do this when something broke,” or “only do this when things got better than last time.” You write these reactions once, and Jenkins applies them on every run automatically.
Think of a restaurant closing for the night. It does not matter whether the evening was busy or empty: the staff still wipe the tables, count the money, switch off the stoves and lock the door. If the night went badly, the manager also gets a call. If it was a record night, the owner gets a happy message. The post section is that closing checklist for your pipeline.
The three questions it answers
Every closing checklist answers three simple questions. First, what must always happen, such as saving test results and deleting temporary files. Second, what must happen only on a certain outcome, such as alerting the team when the build breaks. Third, what must happen only when the outcome changed, such as announcing that a broken build is finally repaired. The post section has a named slot for each of these questions.
The post section belongs to Declarative Pipeline, the structured style of writing a Jenkinsfile. The older, free-form style called Scripted Pipeline does not have it and uses a different tool, which Chapter 20 compares.
A real-world picture helps. Large engineering organizations such as Netflix and Etsy have publicly described using Jenkins to build and test huge amounts of code every day. At that volume, nobody can watch each build. The end-of-build reactions must be written down in advance, and the post section is where they live.
2Why the Post Section Exists
The problem it solves, and the short history behind it.
The problem: builds end in many different ways
A naive pipeline is written as a straight line: do step one, then step two, then step three. That works only when everything succeeds. In real life, step two fails, and the line stops. Anything you placed after the failing step never runs. If your “delete temporary files” action was the last step, it is skipped exactly when the machine is in the messiest state.
This creates three classic pains. Test reports are lost because the command that ran the tests failed before the report-saving step. Disk space disappears because leftover files from failed builds pile up on the machine. Failures go unnoticed because the notification step was also at the end of the line and never executed.
A short history
Freestyle jobs and post-build actions
Jenkins began in 2011 as a fork of the Hudson project. Early jobs were configured through web forms, and a special area called “Post-build Actions” handled reports and emails.
Pipeline as code
The Pipeline plugin, first known as Workflow, let teams describe builds in a text file. Jenkins 2.0, released in 2016, made this style a headline feature.
Scripted style and its safety net
Scripted pipelines relied on general programming tools to guarantee cleanup, which is powerful but easy to forget or get wrong.
Declarative style arrives
Around 2017 Declarative Pipeline introduced a fixed structure with a built-in post section, giving every team the same clear, readable closing checklist.
3Core Concepts You Need First
Five small ideas that make everything else easy.
Agent
An agent is the machine (or container) where the steps actually run. Jenkins has a main brain called the controller, which schedules work, and worker machines called agents that do the heavy lifting. Think of the controller as a kitchen manager and the agents as the cooks.
Workspace
A workspace is a folder on the agent where the pipeline downloads code, compiles it and writes output. It is the cook’s workbench. Many post actions, such as collecting test reports, need this workbench to still exist, which is why the location of your post block matters.
Build status
Every run finishes with a result. Jenkins uses a small fixed vocabulary for it, and the post conditions are built on top of this vocabulary.
| Result | Typical color | What it means |
|---|---|---|
| SUCCESS | Blue or green | Everything worked as planned. |
| UNSTABLE | Yellow | The build ran to the end, but something softer went wrong, most often failing tests or code-quality violations. |
| FAILURE | Red | A step failed hard, such as a compile error or a command returning an error code. |
| ABORTED | Gray | Someone or something stopped the run, for example a person pressing stop or a timeout. |
| NOT_BUILT | Light gray | The run or stage was skipped, so it never really happened. |
Previous build
Jenkins remembers every past run of a job. Some post conditions compare today’s result with the last completed run. That memory is what allows Jenkins to say “this is newly broken” or “this is newly fixed.”
Steps and plugins
A step is a single action. Many steps come built in, and many more come from plugins, which are add-on packages that teach Jenkins new tricks, such as sending chat messages or publishing test graphs. Your post section will mostly call these steps.
Post conditions do not invent new logic. They simply watch the result and the previous result, then decide which group of steps to run.
4Architecture and Components
Which parts of a Jenkins setup are involved when a post section runs.
The post section is not a separate machine or service. It is part of the same pipeline run, executed by the same engine. Still, it touches many components, and understanding them explains almost every surprising behavior you will meet later.
flowchart LR
DEV["Developer pushes code"] --> SCM["Source Control Server"]
SCM -->|"webhook"| CTRL["Jenkins Controller"]
CTRL -->|"assigns work"| AGT["Build Agent"]
AGT --> WS["Workspace Folder"]
AGT -->|"stage steps"| STG["Stages: Build, Test, Deploy"]
STG -->|"result known"| POST["Post Section"]
POST -->|"save files"| ART["Artifact Storage"]
POST -->|"publish results"| REP["Test Report Views"]
POST -->|"send messages"| NOTI["Chat and Email Services"]
POST -->|"tidy up"| WS
CTRL --> HIST["Build History Records"]
POST -->|"final status"| HIST
Read the diagram from left to right. A developer pushes code to a source control server such as GitHub or GitLab. A webhook, which is an automatic message sent when something happens, tells the Jenkins controller about it. The controller hands the job to an agent. The agent creates a workspace and runs the stages. When the stages finish, the post section reacts. It saves files to artifact storage, publishes test results to report views, sends messages through chat and email services, tidies the workspace, and finally lets the final status land in the build history.
Controller
Schedules the run, keeps history, and shows results in the web page. It decides which post conditions apply.
Agent
Runs the steps, including post steps. Needs to be alive and reachable while post steps run.
Workspace
The folder of files. Post steps read from it and often delete it at the very end.
Jenkinsfile
The text file that contains the stages and the post block, stored next to your code in version control.
Plugins
Provide steps for reports, emails and chat messages that post sections call.
Build History
Stores each result so that conditions like changed and fixed can compare runs.
5Anatomy: Where the Post Block Lives
Two possible homes, one simple shape.
The shape of a post section is easy to describe in words. It is a block named post. Inside it you place one or more condition blocks, each named after a condition such as always or failure. Inside each condition block you place ordinary steps. You need at least one condition block, and you may use as many as you like.
Home one: the pipeline level
When the post block sits at the top level, next to the list of stages, it runs once, after every stage has finished. It sees the final result of the entire run. This is the right home for anything about the run as a whole: the final notification, the final workspace cleanup, the final summary.
Home two: the stage level
When the post block sits inside a stage, it runs right after that stage’s own steps finish, before the next stage begins. It sees only that stage’s result. This is the right home for anything tied to that stage: saving that stage’s test report, stopping a test database started only for that stage, or collecting that stage’s logs.
Ask “which part of the work owns the mess?” If a single stage created it, clean it in that stage’s post block. If the whole pipeline created it, clean it in the pipeline’s post block.
How to read a post block quickly
Find the location
Is it inside a stage or beside the stages? That tells you the scope.
List the conditions
Each named block is one reaction. Note which are broad (always, cleanup) and which are narrow (fixed, regression).
Check the order
Remember that conditions run in a fixed order, not the order you typed them, which Chapter 7 explains.
Inspect the steps
Look for steps that need a workspace and confirm an agent is available where they run.
6The Ten Post Conditions in Depth
Each condition is a question Jenkins asks about the finished run.
Here is every condition, explained with the question it answers and a natural use. Read them once, then use the table in Chapter 9 to see how three of them compare runs over time.
always
Runs no matter what the result is. Best for saving test reports and logs, because you want those even when the build fails.
changed
Runs only when this result differs from the previous completed run. Green after green stays silent. Red after green speaks up.
fixed
Runs when this run succeeded and the previous run failed or was unstable. Perfect for the message “we are back to green.”
regression
Runs when this run failed, was unstable or was aborted, while the previous run succeeded. It flags a newly introduced problem.
aborted
Runs when the run was stopped, often by a person or a timeout. Useful for releasing locks or shutting down things that were left running.
failure
Runs when the run failed. The usual home of “alert the team” and “collect extra debugging files.”
success
Runs when everything worked. Useful for promoting an artifact, tagging a release or posting a happy message.
unstable
Runs when the build finished but had soft problems, most often failing tests. Good for a gentler message than a failure.
unsuccessful
Runs when the result is anything other than success, meaning failure, unstable or aborted. A handy catch-all for “something is not right.”
cleanup
Runs after every other condition has been handled, whatever the result. The safest place to delete the workspace.
Choosing between similar conditions
Beginners often ask why there are so many. The answer is that each removes noise. If you only had always, you would need to write “if failed then…” inside it, repeated everywhere. Named conditions let Jenkins do that checking for you and keep the recipe readable.
failure means only a failed result. unsuccessful is wider and also includes unstable and aborted. If you want an alert for every non-green outcome, unsuccessful is the shorter choice, but you lose the ability to word each case differently.
Example: an online store’s checkout service
Imagine a team that ships a checkout service. On always they save test reports. On failure they message the payments channel. On fixed they post a short “back to green” note. On cleanup they delete the workspace. Four small blocks cover the entire ending of the pipeline.
7Internal Working and Order of Execution
What Jenkins actually does, in order, when a run ends.
Understanding order removes most confusion. There are two layers of order: the order between stage-level and pipeline-level post blocks, and the order among the conditions inside one block.
flowchart TD
S1["Stage 1: Build steps"] --> P1["Stage 1 post block"]
P1 --> S2["Stage 2: Test steps"]
S2 --> P2["Stage 2 post block"]
P2 --> S3["Stage 3: Deploy steps"]
S3 --> P3["Stage 3 post block"]
P3 --> PP["Pipeline level post block"]
PP --> END["Final result recorded"]
Layer one: stage before pipeline
A stage’s post block runs immediately after that stage’s steps finish. If the stage failed, the pipeline normally stops moving forward to later stages, but the failed stage’s own post block still runs. After all the stages that were going to run have run, the pipeline-level post block runs once.
Layer two: the order among conditions
Inside a single post block, Jenkins first works out the result, then checks each condition in a fixed order. Every condition that matches gets its steps executed. Several can match at once. For example, a failing run after a successful run matches changed, regression, failure and unsuccessful, along with always and cleanup.
flowchart TD
A["Run finishes and result is known"] --> B["always"]
B --> C["changed"]
C --> D["fixed"]
D --> E["regression"]
E --> F["aborted"]
F --> G["failure"]
G --> H["success"]
H --> I["unstable"]
I --> J["unsuccessful"]
J --> K["cleanup"]
K --> L["Post block complete"]
Each box in Figure 3 only runs its steps if its own question is answered “yes” for this run. The order never changes, no matter how you arrange the blocks in the file. The important promise is that cleanup is last, so anything that deletes files will not remove them before the earlier conditions have finished using them.
If you delete the workspace inside always, a later block such as failure may find its files gone. Put deletions in cleanup and this problem disappears.
What if a stage is skipped?
Stages can be skipped by a when rule, which says “only run this stage if a condition is true.” A skipped stage is treated as not built, and its own post block does not run, because there was no stage execution to react to. The pipeline-level post block still runs as normal.
8How the Result Is Decided
Where the result comes from, and how post steps can change it.
Jenkins tracks a result for the run as it goes. When a step fails, the result becomes failure and later stages are skipped by default. When the tests step reports failing tests but keeps going, the result becomes unstable. When a person presses stop, the result becomes aborted.
Two names that sound alike
Pipeline files can read the build through a built-in object called currentBuild. It has a property named result and another named currentResult. The first can be empty while a run is still healthy and in progress, because Jenkins only fills it in when something changes it. The second always has a value and is the better one to read inside a post block when you want to describe the run in a message.
Post steps can make things worse
Post steps are real steps. If one of them fails, for example an email server cannot be reached and the mail step raises an error, that failure can turn an otherwise successful run into a failed one. This surprises many teams. A sensible design treats notification steps as helpful, not vital, and protects them so that a broken chat service does not make good code look bad.
Common ways a run becomes unstable
- A test reporting step finds failed tests but the test command itself was allowed to continue.
- A code-quality tool reports more violations than the agreed limit.
- A step was told, on purpose, to mark the build yellow instead of red when it hits a known soft problem.
Knowing this, you can decide which outcomes deserve a loud alert and which deserve a quiet note.
9Comparing Runs: changed, fixed and regression
Three conditions that give Jenkins a memory.
Most conditions look only at the current run. These three also look at the run before it. That memory is what makes messages helpful instead of repetitive. Imagine a build that fails for five hours. Without memory, the team gets an alert on every run and starts ignoring them. With memory, the team gets one alert when things broke and one when they were fixed.
| Previous run | Current run | changed | fixed | regression |
|---|---|---|---|---|
| Success | Success | No | No | No |
| Success | Failure | Yes | No | Yes |
| Success | Unstable | Yes | No | Yes |
| Success | Aborted | Yes | No | Yes |
| Failure | Failure | No | No | No |
| Failure | Success | Yes | Yes | No |
| Unstable | Success | Yes | Yes | No |
| Failure | Unstable | Yes | No | No |
Reading the table
The middle rows are the most instructive. A run that fails after another failure does not trigger changed, so the team is not spammed. A run that goes from failure to unstable does trigger changed, because the status is different, but it is neither a fix nor a regression: it is an improvement that is not yet complete.
Illustration: a noisy afternoon
Suppose a team’s main branch runs 40 builds one afternoon, and builds 12 to 19 all fail for the same reason. With an alert on failure, that is 8 messages. With an alert on regression and a happy message on fixed, it is exactly 2 messages. The information is the same; the noise is far lower.
These conditions compare against the previous completed run. On a brand-new job with no history, there is nothing to compare, so do not rely on them for the very first run. Also remember that each branch of a multibranch job keeps its own history.
10Data Flow and Lifecycle of a Post Section
Follow the files, reports and messages from workbench to the outside world.
During a run, the workspace fills up with source code, compiled output, test result files, logs and temporary data. The post section is the moment when the valuable pieces are rescued and the rest is discarded. Think of it as sorting the workbench at the end of the day: keep the finished product, file the paperwork, sweep the sawdust.
flowchart LR
W["Workspace after stages"] --> R1{"Which files matter?"}
R1 -->|"test result files"| T["Publish test report"]
R1 -->|"packages and logs"| A["Archive artifacts"]
R1 -->|"temporary data"| D["Discard"]
T --> N["Notify people"]
A --> N
N --> C["Cleanup workspace"]
D --> C
C --> H["Result stored in history"]
Rescue
Collect what is valuable: test results, packages, logs and screenshots. This should never depend on the run succeeding.
Report
Publish those results so people can read them from the build page instead of hunting through logs.
Notify
Tell the right people, in the right channel, with a short message and a link to the run.
Tidy
Stop helper services, release locks and delete the workspace so the next run starts clean.
This ordering is not accidental. Rescue comes before tidy because deleted files cannot be rescued. Notify comes before tidy because a message often links to files that must still exist. The fixed order of conditions in Chapter 7 exists to support exactly this lifecycle.
11What You Put Inside: Common Post Steps
The everyday toolbox used in real post sections.
Archive artifacts
Saves chosen files, such as packages or logs, to the build record so they can be downloaded later. It has an option to allow an empty result so that a missing file does not break the run.
Publish test results
The JUnit step reads standard test result files and shows pass and fail counts and trend graphs. It marks the run unstable if tests failed. Put it in always so it runs even when the test command failed.
Mail and extended mail
The built-in mail step sends a basic message. The Email Extension plugin adds richer templates and recipient rules.
Chat messages
Plugins such as the Slack Notification plugin post short messages to team channels, ideal for regression and fixed alerts.
Clean the workspace
The Workspace Cleanup plugin deletes the workbench. A built-in step can also delete the current directory.
Stop helper containers
Shuts down databases or test services started for the run so they do not keep using memory and ports.
Publish HTML reports
Shows coverage or performance pages inside Jenkins so reviewers do not need to open files by hand.
Trigger another job
Starts a follow-up job, such as a deployment job after a successful build, only when the result is success.
Keep each post step small and defensive. The best post steps are the ones that cannot fail: they tolerate missing files, retry network calls gently, and never depend on a service that might be down.
A useful mental model is that every post step belongs to one of four families: rescue (archive, publish), tell (mail, chat), tidy (clean, stop) and chain (trigger). If a step does not fit any family, it probably belongs in a regular stage rather than the post section.
12Stage Level, Pipeline Level, Agents and Parallel Work
The details that decide whether your post steps can actually reach their files.
| Question | Stage-level post | Pipeline-level post |
|---|---|---|
| When does it run? | Right after its own stage | Once, after all stages |
| Which result does it see? | That stage only | The whole run |
| Best for | Stage-specific reports and helper services | Final alerts and final cleanup |
| Workspace | The stage’s workspace and agent are still alive | The top-level agent’s workspace, if one is declared |
| Risk | Repeating the same block in many stages | Trying to clean up things a stage already removed |
The “no agent at the top” trap
Some pipelines declare that no agent is used at the top and give each stage its own agent instead. This saves machines, because a stage only holds a worker while it is really working. The trap is that a pipeline-level post block then has no workspace at all. Steps that need files, like archiving or cleaning, fail with an error saying the required context is missing. The fix is to run those steps inside a small block that requests an agent, or to move the file-based steps into stage-level post blocks where the agent still exists.
Containers as agents
Many teams run stages inside containers, which are lightweight, throw-away environments. A stage-level post block runs while that stage’s container is still alive, so it can read files written inside it. Once the stage ends, the container is removed. If you need something from inside the container, rescue it in that stage’s post block, not later.
Parallel stages
Jenkins can run several stages at the same time, called parallel branches. Each branch may have its own post block. This is useful when, for example, unit tests and browser tests run side by side and each publishes its own report. The pipeline-level post block still runs once after all branches are done.
Imagine several chefs cooking different dishes for one banquet. Each chef cleans their own station when their dish is done, which is the stage-level post. After the last dish is served, the head chef checks the whole kitchen and locks up, which is the pipeline-level post.
13Security Around the Post Section
Because it runs on every outcome, it deserves careful handling.
The post section touches secrets, files and external services, which makes it a sensitive place. It also runs when things have gone wrong, which is exactly when careless logging tends to leak information.
Credentials in post steps
Notification services need tokens. Store them in the Jenkins credentials store and bind them only for the step that needs them. Jenkins masks bound secrets in logs, but masking is a helper, not a promise, so never print them on purpose.
What messages reveal
Failure messages that include full logs may reveal internal server names, file paths or tokens. Send a short summary and a link. Let access controls on Jenkins decide who sees the details.
Archived artifacts
Anything archived becomes downloadable by people with access to the job. Do not archive files that contain secrets, private keys or customer data.
Cleaning the workspace
A leftover workspace can hold checked-out code and temporary credentials. Deleting it in the last condition reduces the chance that the next job on that agent stumbles on them.
Who can edit the Jenkinsfile
Anyone who can change the Jenkinsfile can change the post section, including where messages and files are sent. Protect branches and require review, as you would for any deployment script.
Untrusted contributions
If builds run for code from outside contributors, a modified Jenkinsfile could add a malicious post block. Use settings that build trusted versions of the pipeline file for such changes.
Treat the post section with the same care as your deployment code. It has the same reach: it can read the workspace, use credentials and talk to the outside world.
14Monitoring, Logging and Metrics
How to know that your closing checklist itself is healthy.
Logging
Post steps write to the same console log as every other step, and Jenkins labels the post section clearly in the run page. Get into the habit of printing one short line per post action, such as “archived 14 files” or “sent failure alert to channel.” When a message never arrives, this one line tells you whether the step ran at all.
Metrics worth watching
| Metric | Why it matters | Warning sign |
|---|---|---|
| Post section duration | Slow cleanup delays the next run on the same agent. | Post takes more than a few percent of the total run time. |
| Notification failure count | Tells you when chat or email services are unreachable. | Repeated errors in post steps across many jobs. |
| Agent disk usage | Reveals cleanup that is not really cleaning. | Free space shrinking week after week. |
| Alerts per day per channel | Measures noise. | People muting the channel. |
| Time from failure to fix | The outcome your alerts should improve. | Alerts sent but fixes slow. |
Monitoring plugins, such as the one that exposes Jenkins numbers in a format the Prometheus monitoring system can read, help you chart these values over time. Build dashboards, which are wall-sized status screens, are common in teams that want failures to be visible without opening Jenkins.
Illustration: the disappearing disk
A team notices that one build agent runs out of disk space every ten days. The cause turns out to be a workspace cleanup placed inside the failure condition only. Successful runs left their files behind. Moving the deletion to the cleanup condition, which runs for every result, fixed the problem permanently.
15Useful Design Patterns
Reliable ways of arranging post blocks that many teams reuse.
Pattern 1: Rescue, then tidy
Use always for saving reports and archives, and cleanup for deleting the workspace. The fixed order guarantees that the rescue finishes first. This pattern alone prevents most lost-report and full-disk problems.
Pattern 2: Quiet by default, loud on change
Send chat messages on regression and fixed rather than on every failure or success. The team hears about the moment things break and the moment they mend, and nothing in between.
Pattern 3: Own your mess
Anything a stage starts, that same stage stops in its own post block. A stage that launches a temporary database also removes it in its own always block, so later stages never inherit a hidden leftover.
Pattern 4: Soft failure for messengers
Wrap notification steps so a broken chat service is logged but does not change the build result. The build’s verdict should depend on the code, not on the health of the chat system.
Pattern 5: Promote only on success
Use success to tag the release, publish the package or start a deployment job. Because it runs only when everything passed, no half-tested build ever gets promoted by accident.
Pattern 6: Shared library for standard endings
Large organizations often package their common post behavior into a shared library, a reusable code module that many Jenkinsfiles can call. Then one change updates the ending of hundreds of pipelines, and every team gets the same reports, alerts and cleanup.
16Anti-patterns to Avoid
Habits that look fine on day one and hurt on day ninety.
What people do
They place everything in always: reports, alerts, deletion and deployment triggers, all in one large block with hidden “if” checks.
Why it hurts
The block becomes long and fragile. Deletion can happen before something else uses the files, and the hidden checks repeat logic that named conditions already provide.
Better approach
Use the specific conditions. Keep always for rescue work and cleanup for deletion.
What people do
They alert on every single failure to a channel with hundreds of members.
Why it hurts
Repeated identical alerts train people to ignore the channel, and then the one alert that truly matters is ignored too.
Better approach
Use regression and fixed, keep messages short, and include a link to the run.
What people do
They put heavy, slow work such as long deployments or large uploads in post blocks.
Why it hurts
Post steps are meant for wrap-up. Real delivery work hidden there is easy to overlook, hard to retry on its own, and blurs the meaning of a “finished” build.
Better approach
Make deployment its own stage, or trigger a separate job from success, so it has its own status and its own history.
What people do
They never test the post section, because it “only runs at the end.”
Why it hurts
The first time a failure alert is needed is the first time it runs. A typo in a channel name or a missing credential is discovered at the worst possible moment.
Better approach
Deliberately fail a test branch to see the failure path, and fix a broken run to see the fixed path. Do this whenever the post section changes.
17Best Practices and Common Mistakes
A checklist you can apply to any Jenkinsfile today.
Do this
- Save test reports in
alwaysso failures still leave evidence. - Delete workspaces in
cleanup, the last condition. - Alert on
regression, celebrate onfixed. - Keep post steps short, tolerant and quick.
- Put stage-owned mess in that stage’s post block.
- Include the run link and branch name in every message.
- Practice failure paths on a test branch.
Avoid this
- Deleting files in
alwaysthat later blocks still need. - Alerting on every failed run of a long-broken build.
- Relying on a workspace when no agent exists at the top.
- Letting a notification error decide the build result.
- Putting deployment work in post blocks.
- Printing secrets or full logs in messages.
- Copying the same big block into every Jenkinsfile.
Mistakes people make when they are new
Expecting typed order to matter. The order of conditions in the file does not change the order in which they run. Do not rely on writing one block above another.
Forgetting that stages can be skipped. A stage-level post block does not fire for a stage that never ran. If the message must be sent anyway, put it at the pipeline level.
Confusing unstable and failure. A yellow run is not a red run. If your alert only listens to failure, failing tests that mark the run unstable will slip past silently.
Ignoring aborted runs. When a person stops a run, helper services may still be running. An aborted or cleanup block is the safe place to shut them down.
Using conditions on a new job. The comparing conditions need history. On the very first run they cannot say much.
Before merging any change to a Jenkinsfile, read its post section aloud in plain English: “Whatever happens, save the reports. If it breaks after being fine, tell the team. If it recovers, tell them again. At the very end, sweep up.” If it does not read that cleanly, simplify it.
18Advantages, Disadvantages and Trade-offs
An honest look at what the post section does well and where it strains.
Advantages
- One clear, standard place for all end-of-run behavior.
- Guarantees that wrap-up steps run even after failures.
- Named conditions replace fragile hand-written checks.
- Readable by newcomers, which speeds up reviews.
- Works at stage and pipeline level for precise scope.
- History-aware conditions cut alert noise.
Disadvantages
- Fixed order of conditions cannot be rearranged.
- Post steps can affect the final result if they fail.
- Needs an agent for file-based steps, which is easy to forget.
- Duplicated blocks across many stages become noisy.
- Limited expressiveness compared with full programming control.
- Errors appear only when the failure path is actually taken.
Trade-offs to weigh
| Choice | Benefit | Cost |
|---|---|---|
| Many small stage-level blocks | Precise cleanup right after each stage | More repetition and more places to review |
| One large pipeline-level block | Everything in one place | Loses stage detail and needs a top-level agent |
| Alerting on every failure | Nothing is ever missed | Noise, then ignored alerts |
| Alerting only on changes | Quiet and meaningful | Ongoing failures are not repeated, so ownership must be clear |
| Cleaning every run | Clean, predictable agents | Slower next start because caches are lost |
| Keeping workspaces | Faster incremental builds | Disk growth and stale-file surprises |
There is no universally right answer. The correct trade-off depends on how large your team is, how expensive agents are, and how fast your builds must be. What matters is that you choose on purpose and write the reasoning down for the next person.
19Real-World and Industry Examples
How the ideas look in the kinds of organizations that run Jenkins at scale.
Large streaming and e-commerce platforms
Companies of the size of Netflix and Etsy have publicly talked about running very large numbers of automated builds and tests, and about the importance of fast, trustworthy feedback. At that scale, end-of-build behavior must be automatic: test evidence saved, agents kept tidy, and only meaningful alerts sent, because no human can watch every run.
A bank’s release pipeline
In regulated industries, teams often need proof of what was tested. Their post sections archive test reports, security scan results and build logs on every run, including failed ones, because auditors may ask for evidence of both the pass and the fail. Cleanup then removes the workspace so no source code lingers on shared agents.
A mobile app team
Mobile builds are slow and use costly machines. The team uses stage-level post blocks to save crash logs and screenshots from device tests, and a pipeline-level regression alert so the owner of the last change is told quickly. Cleanup is careful to keep a shared cache while removing everything else.
A startup with a small team
A team of five keeps things very simple: reports in always, a chat message in failure, and workspace deletion in cleanup. Later, when the chat channel becomes noisy, they switch the alert to regression and add fixed. The design grows only when the pain appears.
flowchart TD
RUN["Pipeline run ends"] --> Q1{"Result?"}
Q1 -->|"Success"| OK["success block: tag and trigger deploy job"]
Q1 -->|"Unstable"| UN["unstable block: soft warning to team"]
Q1 -->|"Failure"| FA["failure block: alert and collect debug files"]
Q1 -->|"Aborted"| AB["aborted block: stop helper services"]
OK --> CL["cleanup block: delete workspace"]
UN --> CL
FA --> CL
AB --> CL
20Post Section Versus Other Ways to Finish a Build
Where the post section fits among older and alternative tools.
| Approach | How it works | Strength | Weakness |
|---|---|---|---|
| Freestyle post-build actions | Configured through web forms in the job | Easy for beginners | Hard to review, copy or keep in version control |
| Scripted pipeline with try, catch and finally | General programming structures around the stages | Total flexibility | Easy to write inconsistently; every team invents its own style |
| Declarative post section | Named conditions with steps | Clear, standard, readable | Less flexible; fixed condition order |
| Separate follow-up jobs | A different job reacts to the first job’s result | Clean separation and own history | More jobs to manage and link |
The scripted “finally” idea is the closest relative of the cleanup and always conditions. Both promise to run no matter what. The declarative version simply makes the promise easier to read and standard across teams. Teams that need exotic logic sometimes mix both styles, keeping the declarative structure and using a small scripted section inside a step when they need real programming control.
For most teams, start with the declarative post section. Reach for something more elaborate only when you can name a real need that the ten conditions cannot express.
21A Complete Run, Told as a Story
Follow one imaginary pipeline from the first push to the last cleanup.
Ideas stick better inside a story, so here is one. A small team owns an online booking service. Their Jenkinsfile has three stages: Build, Test and Package. Each of the Test and Package stages has its own post block, and the pipeline has one final post block with four conditions: always, regression, fixed and cleanup. The previous run on this branch was successful.
The push
A developer named Maya pushes a change to the branch. The source control server tells the Jenkins controller, which picks a free agent and creates a fresh workspace.
Build stage
The code compiles without problems. This stage has no post block, so the run moves straight to the next stage.
Test stage runs
The test command starts a temporary database and runs 800 tests. Nine tests fail, and the command returns an error code, so the stage is marked as failed.
Test stage post block
Even though the stage failed, its post block runs. Its always condition publishes the test result files, so the nine failures are visible with names and messages. Its second condition stops the temporary database so no container is left behind.
Package stage skipped
Because the Test stage failed, Jenkins does not run the Package stage. Its post block does not run either, since the stage never began.
Pipeline post block
Now the pipeline-level block runs. The result is failure and the previous run was a success, so always and regression match. fixed does not match. Jenkins runs them in order.
The alert
The regression block sends a short message to the team channel with the branch name, Maya’s name from the commit, the count of failed tests and a link to the run page.
Cleanup
Last of all, the cleanup condition deletes the workspace. Nothing after it needs the files, because the reports were already published and the message already sent.
The fix
Maya corrects the code and pushes again. This time all 800 tests pass. The result is success and the previous run failed, so fixed matches and a “back to green” message goes out. Nobody received a repeated alert in between.
Notice how little the team had to do by hand. There was no need to remember to save reports, stop the database or send messages. The closing checklist handled it, in the right order, for both the bad run and the good one.
22Troubleshooting Guide
Symptoms, likely causes and calm fixes.
| Symptom | Likely cause | What to do |
|---|---|---|
| No alert on failing tests | The run was unstable, not failed | Add an unstable block or use unsuccessful |
| Error about a missing context in post | No agent at the pipeline top level | Move file steps into a stage post block or request an agent for them |
| Reports missing after a failed build | Report step was in success, or ran after a step that stopped the pipeline | Move it to always at the stage that produces the files |
| Files gone when a later block ran | Workspace deleted too early | Move deletion to cleanup |
| Alert sent on every failed run | Alert placed in failure | Use regression and fixed |
| Good build turned red | A post step failed, such as an unreachable chat service | Make notification steps tolerant and log their errors |
| Stage post never ran | The stage was skipped by a when rule | Move the action to the pipeline-level block |
| Changed or fixed never fires | No previous run to compare, or a different branch history | Wait for a second run and check the branch |
| Agent disk keeps growing | Cleanup only on some results | Use cleanup, which covers every result |
| Archive step fails on empty output | No matching files were produced | Allow an empty archive or check the file pattern |
A calm debugging routine
- Open the run page and find the post section in the console output. Confirm it started at all.
- Check the result shown at the top. Was it red, yellow or gray? Match it with the condition you expected.
- Read the previous run’s result if the condition compares runs.
- Look at the agent and workspace messages for missing context or missing files.
- Reproduce on a test branch by forcing the same result, then adjust one thing at a time.
Change only one thing per attempt. Post sections are short, so it is tempting to rewrite them wholesale, but a single small change makes cause and effect obvious.
23Related Tools: Catching Errors and Marking Builds
Neighbors of the post section that people often mix it up with.
Three other features live close to the post section, and beginners often confuse them. Knowing the difference helps you choose the right tool.
Catch-error step
Wraps a group of steps. If they fail, it records the failure but lets the pipeline continue. Use it when a failure inside should not stop later stages, for example an optional quality scan.
Unstable step
Marks the run yellow on purpose without stopping it. Useful for soft problems that people should notice but that should not block the whole pipeline.
Retry and timeout
Retry repeats a flaky step a few times. Timeout stops a step that hangs, which usually leads to an aborted result that your post section can react to.
Post section
Does not change what happens in the middle. It reacts to the outcome after the stage or pipeline has finished.
A simple way to remember the difference: the other three tools shape how the run behaves while it is going, and the post section shapes what happens once it is over. A well-designed pipeline usually uses both. For example, a quality scan wrapped so it only marks the run yellow, and a post block that sends a gentle note on unstable and a firm alert on failure.
Example: a hanging test suite
A test stage sometimes hangs for hours because of a stuck network call. The team adds a timeout of thirty minutes. When it triggers, the stage is aborted, the stage’s aborted condition stops the helper services, and the pipeline-level cleanup removes the workspace. The agent is free again, instead of being blocked all night.
24Performance and Scalability
What happens to the post section when hundreds of builds run every day.
A single post section that takes ten seconds feels harmless. Multiply it by 500 builds a day and you spend well over an hour of agent time on wrap-up alone. Multiply it again by several agents waiting for cleanup to finish before they can take new work, and slow endings quietly become a queue for everyone. Scale changes the questions you ask about a post section: not only “does it work,” but “how long does it take, and who waits for it?”
Where the time goes
Deleting huge workspaces
Removing hundreds of thousands of small files, such as dependency folders, can take minutes. Keep large caches outside the workspace so deleting the workspace stays quick.
Archiving big files
Copying large packages from an agent to the controller uses network and disk. Archive only what people truly need, and store very large files in a dedicated artifact repository instead.
Waiting on outside services
A chat or email service that responds slowly holds the whole run open. Use short time limits on notification steps so they give up quickly.
Publishing rich reports
Very large HTML reports slow both the step and the page that later shows them. Trim the reports or publish summaries.
Scaling practices
- Set time limits on post steps that talk to the network, so one slow service cannot hold hundreds of agents.
- Prefer fresh, short-lived agents such as containers, which disappear after the run and reduce the need to delete files at all.
- Keep the post section small. If a task takes more than a minute, ask whether it belongs in a stage or a separate job.
- Limit stored history. Old runs and archived files use disk on the controller. Configure a policy to discard old builds and old artifacts, so the memory that powers
changedandfixedstays quick to search. - Share standard endings through a shared library so one improvement helps every pipeline.
Those numbers are only an illustration, but the lesson is real: shaving five seconds from a post section used at scale gives back more than forty minutes of agent time every day.
25Moving to a Post Section from Older Setups
A gentle path for teams that still use freestyle jobs or scripted endings.
Many teams inherit jobs built years ago with web forms. Moving them to a declarative pipeline with a post section is easier when done in small, safe steps.
List the old post-build actions
Write down every action the old job performs at the end: archives, test reports, emails, triggers and cleanup. This is your closing checklist in rough form.
Sort each action by when it should run
Ask for each one: always, only on failure, only on success, or only when things change. Match it to one of the ten conditions.
Decide the scope
Does the action belong to one stage or to the whole run? Place it in a stage-level or pipeline-level block accordingly.
Rebuild on a test branch
Create the new pipeline beside the old job, and compare outputs for a week. Confirm the same reports, files and messages appear.
Improve the noise
While migrating, replace “alert on every failure” with regression and fixed alerts. This is the perfect moment, because you are rewriting the alerts anyway.
Retire the old job
Once results match and the team is happy, disable the old job and keep it for a short time as a fallback before deleting it.
Do not try to copy old behavior exactly. Old jobs often carry habits that nobody remembers the reason for. Ask each action “who reads this and what do they do with it?” If nobody can answer, leave it out.
Coming from scripted try and finally
Teams with scripted pipelines can map ideas one to one. The code that always ran in the final section becomes the always or cleanup condition. The code inside a failure handler becomes failure. The comparison with the previous build, which scripted pipelines needed hand-written code for, is now free through changed, fixed and regression. The result is usually a shorter, easier-to-read file.
26Plain-English Glossary
Every important word in this guide, in one place.
| Word | Simple meaning |
|---|---|
| Jenkins | A free automation server that builds, tests and delivers software. |
| Pipeline | A written recipe of the steps Jenkins should follow. |
| Jenkinsfile | The text file that holds the pipeline, stored next to the code. |
| Stage | A named phase of the pipeline, like Build or Test. |
| Step | One single action inside a stage. |
| Controller | The main Jenkins server that schedules work and keeps history. |
| Agent | A worker machine or container that runs the steps. |
| Workspace | The folder on the agent where the run does its work. |
| Post section | The block that reacts to the outcome after a stage or pipeline ends. |
| Condition | A named question inside post, such as failure or fixed. |
| Artifact | A file saved from a run so it can be downloaded later. |
| Plugin | An add-on that gives Jenkins new abilities. |
| Webhook | An automatic message that tells Jenkins something happened. |
| Shared library | A reusable code module that many pipelines can call. |
| Unstable | A yellow result: the run finished but had soft problems like failing tests. |
| Regression | Something that used to work and now does not. |
27Frequently Asked Questions
Short answers to the questions that come up most often.
cleanup runs after all the other conditions have been handled. Use always for rescuing files and cleanup for deleting them.failure block will not run for an unstable result. Add an unstable block, or use unsuccessful.when rule never executes, so its post block has nothing to react to. The pipeline-level block still runs.regression instead of failure for alerts, and pair it with fixed. Together they announce the break once and the repair once.always, usually at the stage that runs the tests. That way the report is saved even when the test command itself failed.cleanup. Add more only when a real need appears.28Summary and Key Takeaways
The whole story in a few lines.
The post section is the closing checklist of a Jenkins pipeline. It exists because builds end in many different ways and the important wrap-up work must happen every time. You place it inside a stage for stage-owned work or beside the stages for whole-run work. You fill it with condition blocks that match the result and the history, and you fill those with small, safe steps. Used well, it saves evidence, keeps agents tidy, and makes alerts meaningful instead of noisy.
Key Takeaways
- Post is the guaranteed ending. It runs after failures, aborts and successes, so it is the right home for saving evidence and cleaning up.
- Ten conditions, one fixed order. Always, changed, fixed, regression, aborted, failure, success, unstable, unsuccessful, then cleanup, regardless of how you type them.
- Rescue in always, delete in cleanup. The fixed order makes this pairing safe and prevents lost reports and full disks.
- Use history to reduce noise. Alert on regression and celebrate on fixed, instead of shouting on every failed run.
- Mind the agent. File-based steps need a workspace, so avoid pipeline-level file steps when no top-level agent exists.
- Protect the verdict. Post steps can change the result, so make notification steps tolerant of outside outages.
- Test the failure path. Break a branch on purpose to see your alerts, cleanup and reports in action before you need them.