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

2.8 KiB

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.