First Mutation-CRAP refactoring. - `HomeNewestBuildView` / `RepoNewestBuildView` decide once whether a repository has built; card and entry read `newest.*`. - `UiFormats.runningTag` / `failedTag`: one wording of activity. - Tests for every card field, tint and counter. - Local PIT: HomeCardView.from 224 -> C 1, HomeTexts.meta 66 -> 3.2, RepoOverviewView.from 18 -> 2, toneOf 18 -> 5. - AGENTS.md: 15 hard limit, red from 12 an urgent warning. - Ratchet stays at 650 (BuildExecutor.execute is still the max). PR-doc: `docs/prs/2026-10-04-PR#105-home-card-newest-build.md` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: mhoennig <michael@hoennig.de> Reviewed-on: #105
106 lines
5.1 KiB
Markdown
106 lines
5.1 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
|
|
|
|
The first full Mutation-CRAP report (PR#104) put the home page's repository card second and third:
|
|
|
|
| Method | Mutation-CRAP | Complexity | Killed / eligible |
|
|
| ----------------------- | ------------- | ---------- | ----------------- |
|
|
| `HomeCardView.from` | 224.48 | 21 | 5 / 22 |
|
|
| `HomeTexts.meta` | 65.89 | 9 | 2 / 18 |
|
|
| `RepoOverviewView.from` | 18.00 | 18 | 17 / 18 |
|
|
| `HomeCardView.toneOf` | 17.79 | 5 | 1 / 5 |
|
|
|
|
Two causes, both of the card's own making.
|
|
Seven fields each asked whether the repository has a newest build at all (`entry.newest?.…`), and every `?.` is a branch, so a card that only copies fields reached a complexity of 21.
|
|
And almost nothing tested the card: one test looked at its pull request.
|
|
The Repositories page's entry had the same seven questions, and the words "N running" and "N failed" were written out in five places.
|
|
|
|
## Non-Goals
|
|
|
|
- No change for users: every card and every entry reads as before.
|
|
- The ratchet stays at 650: `BuildExecutor.execute` (647.55) is still the highest score; its PR lowers it.
|
|
|
|
## The Scenarios
|
|
|
|
### Feature: The home page's repository card
|
|
|
|
#### Scenario#105.01: A card says which repository, how it is doing, what it built last, and how its builds went
|
|
|
|
So that every field the reader sees is held by a test.
|
|
|
|
- **Given** a repository with a failed newest build, two running builds, three recent failures and two recent builds
|
|
- **When** its card is made
|
|
- **Then** it carries the name, link, status, build count, both tags, the newest build's branch, commit, duration and start, and the bar strip
|
|
|
|
##### Verified by
|
|
|
|
- [UiViewsUnitTest](../../src/test/kotlin/de/hoennig/werkator/server/UiViewsUnitTest.kt) — Scenario#105.01
|
|
|
|
#### Scenario#105.02: A card before the first build says unknown and nothing else about a build
|
|
|
|
So that "no build yet" is one case, decided once.
|
|
|
|
- **Given** a repository that never built
|
|
- **When** its card is made
|
|
- **Then** its status is `unknown`, its newest build is the empty one, it has no tags and no tint, and its strip is empty
|
|
|
|
##### Verified by
|
|
|
|
- [UiViewsUnitTest](../../src/test/kotlin/de/hoennig/werkator/server/UiViewsUnitTest.kt) — Scenario#105.02
|
|
|
|
#### Scenario#105.03: A card's tint: private before failed before running
|
|
|
|
So that a private repository never lights up, and a failure outweighs activity.
|
|
|
|
- **Given** cards quiet, running, running with a failure, and private with both
|
|
- **When** their tint is decided
|
|
- **Then** it is none, `run`, `bad`, and `ghost`
|
|
|
|
##### Verified by
|
|
|
|
- [UiViewsUnitTest](../../src/test/kotlin/de/hoennig/werkator/server/UiViewsUnitTest.kt) — Scenario#105.03
|
|
|
|
#### Scenario#105.04: The counter over the cards counts running builds and cards with a recent failure
|
|
|
|
So that the counter and the cards use the same words, and the difference between summing builds and counting cards is held.
|
|
|
|
- **Given** sets of cards with and without running builds and recent failures
|
|
- **When** the counter is written
|
|
- **Then** running builds are summed, failing cards are counted, and nothing is written for a quiet page
|
|
|
|
##### Verified by
|
|
|
|
- [UiViewsUnitTest](../../src/test/kotlin/de/hoennig/werkator/server/UiViewsUnitTest.kt) — Scenario#105.04
|
|
|
|
## The Solution
|
|
|
|
- A card is made of three parts, as the reader takes it in: which repository and how it is doing, what it built last, and how its recent builds went.
|
|
- `HomeNewestBuildView` holds what the card says about the newest build; `of` decides once whether there is one, and `NONE` is the card of a repository that has not built.
|
|
The card's `status` comes from it.
|
|
- `RepoNewestBuildView` does the same for the Repositories page, with the pull request as a link and the longer commit.
|
|
- `UiFormats.runningTag` and `failedTag` are the one wording of activity, used by the card, the counter and the Repositories page.
|
|
- `home.html` and `repos.html` read the newest build through `card.newest` and `entry.newest`.
|
|
|
|
Measured with PIT on these classes:
|
|
|
|
| Method | Before | After |
|
|
| ------------------------ | ------ | ----------------------- |
|
|
| `HomeCardView.from` | 224.48 | complexity 1, no mutant |
|
|
| `HomeNewestBuildView.of` | — | 5 (5 / 5 killed) |
|
|
| `HomeCardView.toneOf` | 17.79 | 5 (5 / 5 killed) |
|
|
| `HomeTexts.meta` | 65.89 | 3.24 |
|
|
| `RepoOverviewView.from` | 18.00 | 2 |
|
|
| `RepoNewestBuildView.of` | — | 2 |
|
|
|
|
## Additional Changes
|
|
|
|
- `AGENTS.md` words the limits as meant: 15 is the hard limit, red from 12 an urgent warning; PR#104 had made 12 a limit for every new or changed method.
|
|
- Version 1.34.2 with its release note.
|
|
|
|
## Follow-up PRs
|
|
|
|
- `BuildExecutor.execute`, split into the admission, the run and the settlement of a build; it lowers the ratchet.
|