Files
werkator/docs/prs/2026-09-30-PR#84-run-history-outlives-artifacts.md
miandmhoennig 2cc7a04987
werkator build succeeded after 01:56
werkator/deploy build succeeded after 00:07
run history now outlives artifacts (#84)
Co-authored-by: mhoennig <michael@hoennig.de>
Reviewed-on: #84
2026-09-30 11:16:57 +02:00

95 lines
5.3 KiB
Markdown

> **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
On vm4006 the History of hs.hsadmin.ng shows no duration trend for the `release` build.
A trend needs five successful builds of a definition within 30 days.
The repository sets `artifacts.retentionPerBranch: 3`, and retention dropped the result together with its artifacts.
`release` runs on master only, so it never had more than three results.
The `default` trend exists only because every branch keeps three results of its own, and the results of deleted branches stay since PR#59.
The 30-day window is a problem on its own:
- A rarely built repository never collects five builds in 30 days.
- A nightly build shows only its last month; a slow drift over weeks becomes the median, and "slower" never fires.
## Non-Goals
- No new configuration key; the number of kept records is fixed.
- No change to what keeps artifacts: `retentionPerBranch`, `retentionMaxAge` and `keepLatestGreen` mean what they meant for the artifacts.
- No paging in the History table.
## The Scenarios
### Feature: a build's record outlives its artifacts
#### Background
- A *record* is the entry in `build-results.json`: status, commit, times, duration, phases.
- The *artifacts* are the stored files and the log of a build.
#### Scenario#84.01: Retention takes the artifacts, not the record
So that a build with one branch only, like a release or nightly build, keeps a history of its durations.
- **Given** a build name with more builds than `retentionPerBranch`, or builds older than `retentionMaxAge`
- **When** retention runs
- **Then** those builds lose their artifacts and are marked with `artifactsPrunedAt`
- **and** their records stay, up to the newest 100 per build name
- **and** a marked record is no name's latest and no latest green, so no permanent link leads to missing artifacts
- **And** the mark stays on later passes: artifacts do not come back
##### Verified by
- [FileBuildResultRepositoryTest](../../src/test/kotlin/de/hoennig/werkator/build/FileBuildResultRepositoryTest.kt) — artifacts of the retention count, records of all, the mark kept; records only beyond a hundred; the latest lookups skip marked records; the adapted count, cutoff, keep-latest-green and gone-branch tests
- [WatcherTest](../../src/test/kotlin/de/hoennig/werkator/watcher/WatcherTest.kt) — keep-latest-green and the age limit take the artifacts, the records stay
#### Scenario#84.02: The History shows such a build without artifacts
So that the History is a history of the builds that ran.
- **Given** a record whose artifacts retention removed
- **Then** its History row shows status, commit, start and duration
- **and** its artifact cell says `n/a`, titled "Artifacts removed by retention"
- **And** the JSON carries `artifactsPruned: true`
- **And** the History answers with its newest 200 rows, because the page polls the whole list
##### Verified by
- [BuildsApiControllerTest](../../src/test/kotlin/de/hoennig/werkator/server/BuildsApiControllerTest.kt) — `artifactsPruned`, the duration kept, 200 rows
- [UiControllerTest](../../src/test/kotlin/de/hoennig/werkator/server/UiControllerTest.kt) — the row stays, no artifact link
#### Scenario#84.03: The trend shows the last 30 successful builds
So that a rarely built repository gets a trend, and a nightly build is compared with more than its last month.
- **Given** the successful builds of a definition
- **Then** its trend shows the newest 30 of them, however old they are
- **And** five builds are still the minimum for a trend
##### Verified by
- [BuildDurationTrendsTest](../../src/test/kotlin/de/hoennig/werkator/build/BuildDurationTrendsTest.kt) — forty nightly builds give the newest thirty; five builds months apart give a trend
## The Solution
`BuildResult.artifactsPrunedAt` is the second mark next to `branchGoneAt`; the extension `hasArtifacts` combines both.
`FileBuildResultRepository.prune` now computes two sets.
The artifact set is the old kept set, minus the records whose artifacts are gone already.
The record set is the active builds plus the newest `RECORDS_PER_NAME` (100) of each name.
A record outside the artifact set gets the mark, a record outside both is dropped.
`withArtifacts()` excludes marked records, so the artifact store, which is pruned to it, deletes their files.
A hundred is a fixed constant, not a key: a record is a few hundred bytes, and a hundred covers three months of a nightly build.
`BuildDurationTrends.of` takes the last `RUNS` (30) successful builds per definition instead of a window of days.
An older Werkator reading the file ignores the unknown field and sees the marked records as ordinary ones; its own retention then drops them as before.
## Additional Changes
- `AGENTS.md`, the architecture skill, `docs/configuration.md`, `docs/llms.md`, the `init` template and the `ArtifactsConfig` comments describe the new meaning of the retention keys.
- `BuildExecutorTest` Scenario#65.04 failed once on this branch's CI build: its other build slept three seconds, and a slow machine finished it before the deployment.
The other build now runs until the test opens a gate file.
- Version 1.24.0 with its release note.