Separate queue wait from build duration

BuildResult gains runningSince, set when a build leaves the queue; the
recorded duration now measures pure build time from that point, so build
runtimes can be tracked without queue wait. A build cancelled while still
queued records neither. The UI shows the live wait time in italics while
pending and switches to the real build time once the build runs; the Gitea
"after mm:ss" descriptions now also report pure build time.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-08-10 15:55:36 +02:00
co-authored by Claude Fable 5
parent a03f85bc17
commit 56aa306481
12 changed files with 112 additions and 17 deletions
@@ -13,6 +13,8 @@ data class BuildResultDto(
val commit: String,
val status: String,
val startedAt: Instant,
/** When the build left the queue; the UI derives the live build time from this, the wait time from [startedAt]. */
val runningSince: Instant? = null,
val durationSeconds: Long?,
val artifactKey: String,
) {
@@ -23,6 +25,7 @@ data class BuildResultDto(
commit = result.commit,
status = result.status.jsonName,
startedAt = result.startedAt,
runningSince = result.runningSince,
durationSeconds = result.duration?.seconds,
artifactKey = result.artifactKey,
)
@@ -40,6 +43,7 @@ data class BranchDto(
val commit: String,
val status: String,
val startedAt: Instant?,
val runningSince: Instant? = null,
val durationSeconds: Long?,
val artifactKey: String,
val latestGreenUrl: String? = null,
@@ -65,6 +69,7 @@ data class BranchDto(
commit = latest.commit,
status = latest.status.jsonName,
startedAt = latest.startedAt,
runningSince = latest.runningSince,
durationSeconds = latest.duration?.seconds,
artifactKey = latest.artifactKey,
latestGreenUrl = if (hasGreenBuild) BranchPermalinks.permanentUrl(branch) else null,
@@ -80,6 +85,7 @@ data class CurrentBuildDto(
val artifactKey: String,
val status: String,
val startedAt: Instant,
val runningSince: Instant? = null,
val logSize: Long,
)
@@ -60,6 +60,7 @@ class BuildsApiController(
(results.firstOrNull { it.artifactKey == build.artifactKey }?.status ?: BuildStatus.RUNNING)
.jsonName,
startedAt = build.startedAt,
runningSince = build.runningSince,
logSize = liveLogSize(build.liveLogFile),
)
}
@@ -87,6 +87,7 @@ class UiController(
.jsonName,
startedAtIso = build.startedAt.toString(),
startedAt = UiFormats.timestamp(build.startedAt),
runningSinceIso = build.runningSince?.toString() ?: "",
artifactKey = build.artifactKey,
branchUrl = links.branchUrl(build.branch),
commitUrl = links.commitUrl(build.commit),
@@ -75,6 +75,8 @@ data class BuildRowView(
val status: String,
val startedAtIso: String,
val startedAt: String,
/** ISO timestamp of the run start for the live build-time ticker; empty while queued. */
val runningSinceIso: String,
val duration: String,
val artifactKey: String,
val branchUrl: String?,
@@ -94,6 +96,7 @@ data class BuildRowView(
status = result.status.jsonName,
startedAtIso = result.startedAt.toString(),
startedAt = UiFormats.timestamp(result.startedAt),
runningSinceIso = result.runningSince?.toString() ?: "",
duration = UiFormats.duration(result.duration),
artifactKey = result.artifactKey,
branchUrl = links.branchUrl(result.branch),
@@ -112,6 +115,7 @@ data class BuildRowView(
status = entry.status,
startedAtIso = entry.startedAt?.toString() ?: "",
startedAt = entry.startedAt?.let { UiFormats.timestamp(it) } ?: "",
runningSinceIso = entry.runningSince?.toString() ?: "",
duration = UiFormats.duration(entry.durationSeconds?.let { Duration.ofSeconds(it) }),
artifactKey = entry.artifactKey,
branchUrl = links.branchUrl(entry.branch),
@@ -130,6 +134,7 @@ data class CurrentBuildView(
val status: String,
val startedAtIso: String,
val startedAt: String,
val runningSinceIso: String,
val artifactKey: String,
val branchUrl: String?,
val commitUrl: String?,