skip to content

A pipeline uploads its Allure results directory to a shared results store only when the test command exits successfully. What does that store end up missing, and why is the failed run the one worth having?

level: middleimportance: should knowfreq 52%

answer

  1. the red run is the one you need
  2. runner workspaces are thrown away
  3. results are written per test as they finish
  4. verdict and publish are different switches

basics

~20 s

The store ends up holding only green runs. Every failed run's results, messages and attachments stay on an ephemeral runner and are discarded with the workspace, so the runs someone actually needs to look at are the ones absent.

solid answer

~50 s

Conditioning the publish on the test command's success inverts the value of the store: the run you most want to open is a red one, and that is precisely the run that never gets pushed. The failed run's `-result.json` files, its failure messages and its `-attachment` bytes exist only in the runner's workspace, which is reclaimed as soon as the job ends — there is no later step that can go and fetch them. The result is a store whose history has a hole at every failure, so nobody can compare this failure against the last one or open the screenshot from the build that broke. The publish step should run whatever the suite's outcome was; whether the build goes red is a separate signal carried by the suite's own exit status, and the two should not share one switch.

go deeper

for a junior

Say plainly that the failed run is the one someone will want to open, and that skipping its upload throws that evidence away when the runner is cleaned up.

for a middle

Explain that results are written per test as tests finish, so a red run leaves a complete, valid directory, and that the build verdict and the publish condition are separate signals.

for a senior

Demonstrate that you would still guard the genuinely empty directory, so an unconditional push cannot quietly record a crashed run as a small passing one.

for a principal

Own the position that a results store which only ever received green runs cannot answer comparative questions, and set the publish contract once for every team rather than per pipeline.

## What the condition is actually filtering A publish step gated on the test command's success does not filter *bad uploads*. It filters **failures**. Every run it declines to push is, by construction, a run in which something went wrong — which is the entire population anyone would ever want to look up later. The reasoning behind the gate is usually a half-remembered instinct that a failed run produced nothing worth keeping. That is false for Allure-style delivery: the adaptor writes a result file for each test **as that test finishes**, so a failing run leaves a directory that is complete for every test that ran, including the ones that failed and the evidence attached to them. The directory is not damaged by the failure. It is the most valuable directory the job will ever produce. ## What is lost, concretely When the push is skipped on red, all of the following exist only on the runner and then cease to exist: - the `-result.json` files for the tests that failed, carrying their status and their failure message and trace - the `-attachment` bytes — the screenshot, the page source, the captured log — that the failing tests recorded at the moment of failure - the `-container.json` files showing what setup ran around them, which is often where the real cause sits - the whole-run files (`executor.json`, `environment.properties`) that would have said which build and which environment produced this ## Why "we still have the job log" is not an answer A CI job's console log is a single flat text stream. It is not per-test, it is not searchable across runs, and it has no attachments — the screenshot was written to a file on disk, not printed. It also decays on its own schedule, separately from the results store, so the two go missing at different times and neither is a backup of the other. More importantly, the store's value is **comparative**. Its usefulness comes from holding this run beside the previous ones so you can ask whether the failure is new. A store that only ever received green runs cannot answer that question about any failure, ever. ## Two switches, not one The confusion at the root of this bug is that one boolean is being asked to do two unrelated jobs. | Question | What decides it | |---|---| | Is the build red? | the suite command's own exit status | | Do the results get published? | nothing about the suite's outcome — always | Those are independent. Making the publish unconditional does **not** hide a failure; the suite already reported it. Making the publish conditional does not make the build any redder; it just deletes the evidence. Treat the upload as part of producing the run, not as a reward for passing. ## The edge that unconditional publishing does create There is one genuine case to think about: the suite crashes before any test executes — a compilation error, a missing driver, an environment that never came up. The results directory is then empty or nearly so, and an unconditional push sends it. The store records a run containing almost nothing. That is still better than silence, but only if it reads as what it is. Two habits keep it honest: 1. **Check the directory before pushing.** If it is empty, fail the publish step with a message saying so, rather than pushing an empty run that looks like a healthy short one. 2. **Do not let an almost-empty run pass for a small green run.** A run reporting a handful of tests when the suite normally reports thousands should be visibly anomalous to whoever reads the store, not quietly averaged in. ## What to do instead - Make the publish step run regardless of the suite's outcome. - Keep the build verdict where it already lives — on the suite command — and do not route it through the publish condition. - Guard the empty-directory case explicitly, so the one situation where there really is nothing to push says so out loud. The test of whether you have got this right is simple: after the next red build, can somebody who was not there open that run in the store and see the failure and its evidence? If the answer depends on the build having passed, the wiring is backwards.

  • If the publish now always runs, what does it push when the suite crashed before executing a single test?
    An empty or near-empty results directory, which the store then records as a run with almost no tests — easy to misread as a small healthy run. Guard it explicitly: check the directory is non-empty immediately before the push and fail the publish step with a clear message if it is not, rather than shipping the emptiness.
  • Why can't the team just retrieve the failed run's files from the runner afterwards?
    Runners are ephemeral. The workspace is reclaimed when the job ends, so anything not pushed within the job's own lifetime is gone, and no later step or manual request can reach it. Delivery has exactly one window, and it closes with the job.

saying these in an interview costs you the question

  • Thinks a failed run produces no usable results directory
  • Treats the job console log as a substitute for stored results
  • Believes publishing a red run somehow hides the failure
  • Uses one condition for both the build verdict and the upload