Files
werkator/docs/plan/01-build-state-domain.md
T

62 lines
2.8 KiB
Markdown

# Step 01: Build State Domain and Repository
Prerequisites: none.
Read `README.md` and `00-legacy-analysis.md` first.
## Goal
A tested domain model for build results plus a persistent repository, replacing the legacy `build-results.tsv`.
## Design
Create package `de.hoennig.werkator.build`:
- `BuildStatus` enum: `PENDING`, `RUNNING`, `SUCCESS`, `FAILED`, `INTERRUPTED`, `CANCELLED`.
Add `isTerminal`, `isRestartable` (pending/running/interrupted) properties.
- `BuildResult` data class: branch, commit SHA, status, startedAt, duration, artifactKey.
Use `java.time.Instant`/`Duration`; format only at the edges.
- `BuildResultRepository` interface: append, update status of latest entry for a branch, query latest per branch, query history, delete entry, prune.
- `FileBuildResultRepository`: JSON file at `.git/werkator/build-results.json`.
Write atomically (write temp file, then `Files.move` with `ATOMIC_MOVE`).
Reuse the Jackson YAML/JSON setup style from `ConfigLoader`.
Business logic to include (port from legacy, see analysis):
- `markStaleRunningAsInterrupted()` — called at startup; running → interrupted, superseded pending → interrupted.
- Retention pruning: keep N builds per branch (`artifacts.retentionPerBranch`); drop entries for branches no longer on origin (branch list passed in as a parameter, no git dependency here).
## Out of Scope
- No git access, no Gitea, no execution — pure domain and file I/O.
- Artifact directory pruning (step 05 consumes the pruning result).
- Age-based retention (legacy supported `h`/`d` suffixes); count-based only, extend later if needed.
## Config
Uses existing `artifacts.retentionPerBranch`.
No new keys expected.
## Tests
Kotest `FunSpec`, no Spring context needed.
- Round-trip persistence, atomicity (temp file cleaned up).
- Status transition helpers and `markStaleRunningAsInterrupted` edge cases.
- Retention pruning: per-branch count, removed branches, ordering by timestamp.
- Corrupt/missing file → empty repository, no crash (legacy failed silently; we log a warning).
## Acceptance Criteria
- `./gradlew ktlintFormat` then `./gradlew build` is green.
- New code has no dependency on picocli or web classes.
## Execution Notes (done 2026-07-07)
Implemented as specified in `de.hoennig.werkator.build`; build green, 19 new tests.
Deviations and details:
- Added `jackson-datatype-jsr310` to `build.gradle.kts` for `Instant`/`Duration` JSON support (ISO-8601 strings).
- `FileBuildResultRepository` is a plain class, not a Spring bean; the file path depends on the runtime repo location, so wiring happens in step 04/06 via a factory or configuration.
- `prune(...)` and `markStaleRunningAsInterrupted()` return the removed/changed entries so step 05 can prune artifact directories and callers can log.
- Timestamp ties in `updateLatest`/`latestFor` resolve to the later appended entry.