Files
werkator/docs/prs/2026-10-12-PR#156-outdated-failures.md
claude-code c218a0c0c2
werkator build succeeded after 04:34
werkator/deploy build succeeded after 00:14
A failed build is shown as outdated once its branch is gone or a newer build ended (#156)
Co-authored-by: claude-code <claude-code@javagil.de>
2026-10-12 16:07:33 +02:00

143 lines
7.1 KiB
Markdown

# PR#156: A failed build is shown as outdated once its branch is gone or a newer build ended
> **WARNING:** This document describes only the change applied in this PR.
> It may already be outdated once the next PR is merged.
> Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.
## The Problem
The History shows every failed build in red, with a red row, for as long as it is recorded.
A failure is still red after the branch went green again, at the same commit or a newer one.
It is still red after its branch was merged and deleted.
So the page shows many red rows, and most of them say nothing about how a branch stands now.
A reader cannot see at a glance which failure still needs work.
The bar strips on the home page have the same problem.
## Non-Goals
- No change to the Latest and Branches views: they show the newest run of each name, and a gone branch is not there.
- No change to the counters "failed this week", the red repository chips or the card tint: they count only the newest run of each name already.
- No change to the commit statuses in Gitea.
- No stored mark: the decision is made on read, like the duration trend.
- No build-definition key, so ADR 0010 is not touched.
## The Scenarios
### Feature: an overtaken failure is shown as outdated
#### Background
- A run's *name* is its pool, `<branch>` or `<branch>@<build>`.
- A *verdict* is the end of a run that says how the code stands: `success`, `failed` or `timed_out`.
- `pending`, `running`, `cancelled` and `interrupted` are no verdict.
#### Scenario#156.01: A failure a newer green run followed is outdated!
So that a branch that is green again shows no red for its old failure.
- **Given** a failed run of a name
- **When** a newer run of the same name succeeds, at the same commit or a newer one
- **Then** the failed run is outdated, superseded by that green run
##### Verified by
- [OutdatedRunsUnitTest: a failure a newer green run followed is outdated](../../src/test/kotlin/de/hoennig/werkator/build/OutdatedRunsUnitTest.kt)
#### Scenario#156.02: A newer failure outdates the older one, and the newest stays a problem!
So that a branch that fails again and again shows one red row, the one that says how it stands now.
- **Given** a failed or timed-out run of a name
- **When** a newer run of the same name fails or times out
- **Then** the older run is outdated
- **and** the newest failure is not
##### Verified by
- [OutdatedRunsUnitTest: a newer failure outdates the older one](../../src/test/kotlin/de/hoennig/werkator/build/OutdatedRunsUnitTest.kt)
#### Scenario#156.03: A failure of a branch deleted from origin is outdated!
So that a merged and deleted branch leaves no red row behind.
- **Given** a failed or timed-out run
- **When** its branch is gone from origin (`branchGoneAt`)
- **Then** the run is outdated, even as the newest run of its name
##### Verified by
- [OutdatedRunsUnitTest: a failure of a branch deleted from origin is outdated](../../src/test/kotlin/de/hoennig/werkator/build/OutdatedRunsUnitTest.kt)
#### Scenario#156.04: A newer run without a verdict leaves the failure a problem!
So that a queued, running, cancelled or interrupted run does not hide a failure it has not yet answered.
- **Given** a failed run of a name
- **When** the only newer run of the same name is pending, running, cancelled or interrupted
- **Then** the failed run is not outdated
##### Verified by
- [OutdatedRunsUnitTest: a newer run without a verdict leaves the failure a problem](../../src/test/kotlin/de/hoennig/werkator/build/OutdatedRunsUnitTest.kt)
#### Scenario#156.05: The History shows an outdated failure grey, with its reason!
So that a reader sees at once which failures still count, and why the others do not.
- **Given** an outdated run in the History
- **When** the page renders it, first by the server and then by every poll
- **Then** the row loses its red tint and has dimmed text
- **and** the status keeps its word, with a grey outlined dot
- **and** a tag `outdated` stands beside it, with the reason as its title
- **and** the tag links to the run that superseded it, while that run has its artifacts
##### Verified by
- [BuildsApiControllerRestTest: history names why a failure is outdated](../../src/test/kotlin/de/hoennig/werkator/server/BuildsApiControllerRestTest.kt)
- [UiBuildListsRestTest: an outdated failure is a dimmed row with a tag](../../src/test/kotlin/de/hoennig/werkator/server/UiBuildListsRestTest.kt)
- [UiViewsUnitTest: an outdated row names why in its tag's title](../../src/test/kotlin/de/hoennig/werkator/server/UiViewsUnitTest.kt)
#### Scenario#156.06: The home strip draws an outdated failure grey!
So that a repository card shows red only for the failures that still count.
- **Given** an outdated run among the last twelve builds of a repository
- **When** the home page draws the bar strip
- **Then** the bar keeps its height and is grey instead of red
- **and** the legend names it "outdated failure"
##### Verified by
- [RepoOverviewsUnitTest: the strip marks a failure a newer run overtook](../../src/test/kotlin/de/hoennig/werkator/server/RepoOverviewsUnitTest.kt)
- [UiViewsUnitTest: an outdated failure is a grey bar of its own height](../../src/test/kotlin/de/hoennig/werkator/server/UiViewsUnitTest.kt)
#### Scenario#156.07: A private repository tells why a run is outdated, but not which commit superseded it!
So that the reason stays metadata and names no work (RFC 0003, D8).
- **Given** an outdated run of a private repository
- **When** a visitor without the control token reads the History
- **Then** the reason, the outcome and the time of the newer run stay
- **and** its commit is `n/a` and its page is not linked
##### Verified by
- [RedactionUnitTest: an outdated run keeps why and when](../../src/test/kotlin/de/hoennig/werkator/server/RedactionUnitTest.kt)
## The Solution
- `OutdatedRuns.of(history)` walks the history newest first and keeps, per name, the nearest newer verdict.
A failed or timed-out run is outdated by a gone branch first, else by that verdict.
The result is a map by artifact key, so nothing is stored, and a branch that comes back is current again with its mark.
- The history endpoints of the API and the page compute the map over the whole history, then take their 200 rows.
`BuildResultDto.outdated` carries it as `OutdatedDto`: the reason, and for `superseded` the commit, status, start and artifact key of the newer run.
The key is set only while that run has its artifacts, so the link never leads to a removed page.
- `UiFormats.outdatedTitle` and its twin `outdatedTitle` in `werkator.js` word the reason.
The status badge keeps its word; the colour and the filled dot go.
The row is dimmed by text colour, not by opacity: opacity already says "this browser lost the server".
The red row tint applies only to a failure that is not outdated.
- `RecentBuildDto.outdated` marks the bar, and `HomeBarView.strip` and `barStrip` give it the level `outdated`.
- `Redaction` keeps the reason, outcome and time, and replaces the commit and drops the key.
- Werkbaum: a node under `#ui`.
- Version 1.42.0, with an entry in the release notes.