The Post Section in Jenkins

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.

Everyday Analogy

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.

i
Remember

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

1

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.

2

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.

3

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.

4

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.

10
named post conditions
2
places it can live: stage or pipeline
1
condition guaranteed to run last
A good pipeline is judged not by how it starts, but by how tidily it finishes.

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.

ResultTypical colorWhat it means
SUCCESSBlue or greenEverything worked as planned.
UNSTABLEYellowThe build ran to the end, but something softer went wrong, most often failing tests or code-quality violations.
FAILURERedA step failed hard, such as a compile error or a command returning an error code.
ABORTEDGraySomeone or something stopped the run, for example a person pressing stop or a timeout.
NOT_BUILTLight grayThe 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.

!
Key idea

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
Figure 1: Where the post section sits between the stages and the outside world.

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.

Brain

Controller

Schedules the run, keeps history, and shows results in the web page. It decides which post conditions apply.

Muscle

Agent

Runs the steps, including post steps. Needs to be alive and reachable while post steps run.

Workbench

Workspace

The folder of files. Post steps read from it and often delete it at the very end.

Recipe

Jenkinsfile

The text file that contains the stages and the post block, stored next to your code in version control.

Toolbox

Plugins

Provide steps for reports, emails and chat messages that post sections call.

Memory

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.

i
Rule of thumb

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

1

Find the location

Is it inside a stage or beside the stages? That tells you the scope.

2

List the conditions

Each named block is one reaction. Note which are broad (always, cleanup) and which are narrow (fixed, regression).

3

Check the order

Remember that conditions run in a fixed order, not the order you typed them, which Chapter 7 explains.

4

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.

Any result

always

Runs no matter what the result is. Best for saving test reports and logs, because you want those even when the build fails.

Compare

changed

Runs only when this result differs from the previous completed run. Green after green stays silent. Red after green speaks up.

Compare

fixed

Runs when this run succeeded and the previous run failed or was unstable. Perfect for the message “we are back to green.”

Compare

regression

Runs when this run failed, was unstable or was aborted, while the previous run succeeded. It flags a newly introduced problem.

Result

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.

Result

failure

Runs when the run failed. The usual home of “alert the team” and “collect extra debugging files.”

Result

success

Runs when everything worked. Useful for promoting an artifact, tagging a release or posting a happy message.

Result

unstable

Runs when the build finished but had soft problems, most often failing tests. Good for a gentler message than a failure.

Group

unsuccessful

Runs when the result is anything other than success, meaning failure, unstable or aborted. A handy catch-all for “something is not right.”

Last word

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.

!
Common confusion

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"]
Figure 2: Stage post blocks run right after their stage; the pipeline post block runs last.

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"]
Figure 3: The fixed order in which matching conditions are executed.

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.

i
Practical effect

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.

5
possible results to react to
1
final result shown in history
0
acceptable reasons to leave post steps untested

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 runCurrent runchangedfixedregression
SuccessSuccessNoNoNo
SuccessFailureYesNoYes
SuccessUnstableYesNoYes
SuccessAbortedYesNoYes
FailureFailureNoNoNo
FailureSuccessYesYesNo
UnstableSuccessYesYesNo
FailureUnstableYesNoNo

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.

!
Watch out

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"]
Figure 4: The natural lifecycle of a post section: rescue, tell, tidy.
1

Rescue

Collect what is valuable: test results, packages, logs and screenshots. This should never depend on the run succeeding.

2

Report

Publish those results so people can read them from the build page instead of hunting through logs.

3

Notify

Tell the right people, in the right channel, with a short message and a link to the run.

4

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.

Files

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.

Tests

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.

Email

Mail and extended mail

The built-in mail step sends a basic message. The Email Extension plugin adds richer templates and recipient rules.

Chat

Chat messages

Plugins such as the Slack Notification plugin post short messages to team channels, ideal for regression and fixed alerts.

Tidy

Clean the workspace

The Workspace Cleanup plugin deletes the workbench. A built-in step can also delete the current directory.

Containers

Stop helper containers

Shuts down databases or test services started for the run so they do not keep using memory and ports.

Reports

Publish HTML reports

Shows coverage or performance pages inside Jenkins so reviewers do not need to open files by hand.

Chain

Trigger another job

Starts a follow-up job, such as a deployment job after a successful build, only when the result is success.

i
Design tip

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.

QuestionStage-level postPipeline-level post
When does it run?Right after its own stageOnce, after all stages
Which result does it see?That stage onlyThe whole run
Best forStage-specific reports and helper servicesFinal alerts and final cleanup
WorkspaceThe stage’s workspace and agent are still aliveThe top-level agent’s workspace, if one is declared
RiskRepeating the same block in many stagesTrying 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.

Everyday Analogy

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.

Secrets

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.

Leaks

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.

Files

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.

Residue

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.

Trust

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.

Pull requests

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.

!
Security rule

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

MetricWhy it mattersWarning sign
Post section durationSlow cleanup delays the next run on the same agent.Post takes more than a few percent of the total run time.
Notification failure countTells you when chat or email services are unreachable.Repeated errors in post steps across many jobs.
Agent disk usageReveals cleanup that is not really cleaning.Free space shrinking week after week.
Alerts per day per channelMeasures noise.People muting the channel.
Time from failure to fixThe 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.

ANTI-PATTERN 01Avoid
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.

ANTI-PATTERN 02Avoid
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.

ANTI-PATTERN 03Avoid
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.

ANTI-PATTERN 04Avoid
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 always so failures still leave evidence.
  • Delete workspaces in cleanup, the last condition.
  • Alert on regression, celebrate on fixed.
  • 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 always that 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.

i
Habit to build

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

ChoiceBenefitCost
Many small stage-level blocksPrecise cleanup right after each stageMore repetition and more places to review
One large pipeline-level blockEverything in one placeLoses stage detail and needs a top-level agent
Alerting on every failureNothing is ever missedNoise, then ignored alerts
Alerting only on changesQuiet and meaningfulOngoing failures are not repeated, so ownership must be clear
Cleaning every runClean, predictable agentsSlower next start because caches are lost
Keeping workspacesFaster incremental buildsDisk 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
Figure 5: A typical production ending: different reactions per result, one shared cleanup.

20Post Section Versus Other Ways to Finish a Build

Where the post section fits among older and alternative tools.

ApproachHow it worksStrengthWeakness
Freestyle post-build actionsConfigured through web forms in the jobEasy for beginnersHard to review, copy or keep in version control
Scripted pipeline with try, catch and finallyGeneral programming structures around the stagesTotal flexibilityEasy to write inconsistently; every team invents its own style
Declarative post sectionNamed conditions with stepsClear, standard, readableLess flexible; fixed condition order
Separate follow-up jobsA different job reacts to the first job’s resultClean separation and own historyMore 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.

!
Choosing

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.

1

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.

2

Build stage

The code compiles without problems. This stage has no post block, so the run moves straight to the next stage.

3

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.

4

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.

5

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.

6

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.

7

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.

8

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.

9

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.

The best automation is the kind nobody has to think about on a bad day.

22Troubleshooting Guide

Symptoms, likely causes and calm fixes.

SymptomLikely causeWhat to do
No alert on failing testsThe run was unstable, not failedAdd an unstable block or use unsuccessful
Error about a missing context in postNo agent at the pipeline top levelMove file steps into a stage post block or request an agent for them
Reports missing after a failed buildReport step was in success, or ran after a step that stopped the pipelineMove it to always at the stage that produces the files
Files gone when a later block ranWorkspace deleted too earlyMove deletion to cleanup
Alert sent on every failed runAlert placed in failureUse regression and fixed
Good build turned redA post step failed, such as an unreachable chat serviceMake notification steps tolerant and log their errors
Stage post never ranThe stage was skipped by a when ruleMove the action to the pipeline-level block
Changed or fixed never firesNo previous run to compare, or a different branch historyWait for a second run and check the branch
Agent disk keeps growingCleanup only on some resultsUse cleanup, which covers every result
Archive step fails on empty outputNo matching files were producedAllow an empty archive or check the file pattern

A calm debugging routine

  1. Open the run page and find the post section in the console output. Confirm it started at all.
  2. Check the result shown at the top. Was it red, yellow or gray? Match it with the condition you expected.
  3. Read the previous run’s result if the condition compares runs.
  4. Look at the agent and workspace messages for missing context or missing files.
  5. Reproduce on a test branch by forcing the same result, then adjust one thing at a time.
i
Tip

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.

Error handling

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.

Marking

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.

Retries

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.

Ending

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

Slow

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.

Slow

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.

Slow

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.

Slow

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 changed and fixed stays quick to search.
  • Share standard endings through a shared library so one improvement helps every pipeline.
500
illustrative builds per day
10 s
illustrative post time per build
~83 min
agent time spent on endings daily

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.

1

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.

2

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.

3

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.

4

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.

5

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.

6

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.

i
Migration tip

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.

WordSimple meaning
JenkinsA free automation server that builds, tests and delivers software.
PipelineA written recipe of the steps Jenkins should follow.
JenkinsfileThe text file that holds the pipeline, stored next to the code.
StageA named phase of the pipeline, like Build or Test.
StepOne single action inside a stage.
ControllerThe main Jenkins server that schedules work and keeps history.
AgentA worker machine or container that runs the steps.
WorkspaceThe folder on the agent where the run does its work.
Post sectionThe block that reacts to the outcome after a stage or pipeline ends.
ConditionA named question inside post, such as failure or fixed.
ArtifactA file saved from a run so it can be downloaded later.
PluginAn add-on that gives Jenkins new abilities.
WebhookAn automatic message that tells Jenkins something happened.
Shared libraryA reusable code module that many pipelines can call.
UnstableA yellow result: the run finished but had soft problems like failing tests.
RegressionSomething that used to work and now does not.

27Frequently Asked Questions

Short answers to the questions that come up most often.

Q1Can I use more than one condition in the same post block?
Yes. You can list as many condition blocks as you like, and every one that matches the result will run, in the fixed order described in Chapter 7.
Q2Does the post section run if a stage fails?
Yes. The failing stage’s own post block runs, and the pipeline-level post block runs at the end. That is the main reason the section exists.
Q3What is the difference between always and cleanup?
Both run for every result, but cleanup runs after all the other conditions have been handled. Use always for rescuing files and cleanup for deleting them.
Q4Why did my failure alert not fire when tests failed?
Failing tests often make the run unstable, which is yellow, rather than failed. A failure block will not run for an unstable result. Add an unstable block, or use unsuccessful.
Q5Why do I get an error about a missing context when I archive files in post?
Your pipeline probably declares no agent at the top level, so the pipeline-level post has no workspace. Run those steps where an agent exists, such as inside the stage’s post block.
Q6Can a post step change the build result?
Yes. A failing post step can make the run fail, and the build object allows a pipeline to set its own result. Protect non-essential steps, like chat messages, so they cannot spoil a good build.
Q7Does a skipped stage run its post block?
No. A stage skipped by a when rule never executes, so its post block has nothing to react to. The pipeline-level block still runs.
Q8How do I stop getting the same alert every run of a broken build?
Use regression instead of failure for alerts, and pair it with fixed. Together they announce the break once and the repair once.
Q9Is the order of my condition blocks in the file important?
No. Jenkins runs matching conditions in its own fixed order, so the position in the file does not change execution order.
Q10Can I use the post section in a scripted pipeline?
No. The post section belongs to Declarative Pipeline. In a scripted pipeline you use programming structures such as try, catch and finally to get the same effect.
Q11Where should test reports be published?
In always, usually at the stage that runs the tests. That way the report is saved even when the test command itself failed.
Q12How many post conditions should a typical pipeline use?
Many good pipelines use only three or four: one for rescuing reports, one or two for alerts, and 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.