added permanent artifact links for latest green builds: /branches/<branch-key>/... serves the latest green build's artifacts (green-only, resolved per request), keepLatestGreen retention protection, permanent artifact-index page, and latestGreenUrl links in the branches view
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
83e70e73c3
commit
bb06c8b731
@@ -12,6 +12,13 @@ import java.time.Instant
|
||||
object ArtifactKeys {
|
||||
fun branchKey(branch: String): String = "${sanitize(branch)}-${sha256Prefix(branch)}"
|
||||
|
||||
/**
|
||||
* The hash-free key of the permanent `/branches/<key>/…` artifact URLs, e.g.
|
||||
* `feature/demo` → `feature_demo`. Unlike [branchKey] it is not necessarily
|
||||
* unique; lookups must reject ambiguous matches.
|
||||
*/
|
||||
fun permanentBranchKey(branch: String): String = sanitize(branch)
|
||||
|
||||
fun buildKey(
|
||||
branch: String,
|
||||
startedAt: Instant,
|
||||
|
||||
@@ -17,6 +17,9 @@ interface BuildResultRepository {
|
||||
|
||||
fun latestFor(branch: String): BuildResult?
|
||||
|
||||
/** The newest SUCCESS entry of [branch] — the build behind the permanent `/branches/…` links. */
|
||||
fun latestGreenFor(branch: String): BuildResult?
|
||||
|
||||
/** The newest entry of each branch, newest first. */
|
||||
fun latestPerBranch(): List<BuildResult>
|
||||
|
||||
@@ -34,10 +37,13 @@ interface BuildResultRepository {
|
||||
|
||||
/**
|
||||
* Keeps the newest [retentionPerBranch] entries per branch and drops entries of branches
|
||||
* not contained in [originBranches]. Returns the removed entries.
|
||||
* not contained in [originBranches]. With [keepLatestGreen], the newest SUCCESS entry of
|
||||
* each surviving branch is kept even beyond the retention count, so the permanent
|
||||
* `/branches/…` artifact links stay valid while newer builds fail. Returns the removed entries.
|
||||
*/
|
||||
fun prune(
|
||||
originBranches: Collection<String>,
|
||||
retentionPerBranch: Int,
|
||||
keepLatestGreen: Boolean = false,
|
||||
): List<BuildResult>
|
||||
}
|
||||
|
||||
@@ -70,6 +70,11 @@ class FileBuildResultRepository(
|
||||
return indexOfLatest(results, branch)?.let { results[it] }
|
||||
}
|
||||
|
||||
override fun latestGreenFor(branch: String): BuildResult? =
|
||||
load()
|
||||
.filter { it.branch == branch && it.status == BuildStatus.SUCCESS }
|
||||
.maxByOrNull { it.startedAt }
|
||||
|
||||
override fun latestPerBranch(): List<BuildResult> =
|
||||
load()
|
||||
.groupBy { it.branch }
|
||||
@@ -117,6 +122,7 @@ class FileBuildResultRepository(
|
||||
override fun prune(
|
||||
originBranches: Collection<String>,
|
||||
retentionPerBranch: Int,
|
||||
keepLatestGreen: Boolean,
|
||||
): List<BuildResult> {
|
||||
synchronized(lock) {
|
||||
val results = load()
|
||||
@@ -127,9 +133,15 @@ class FileBuildResultRepository(
|
||||
.groupBy { it.branch }
|
||||
.values
|
||||
.flatMap { entries ->
|
||||
entries
|
||||
.sortedByDescending { it.startedAt }
|
||||
.take(retentionPerBranch.coerceAtLeast(0))
|
||||
val newest =
|
||||
entries
|
||||
.sortedByDescending { it.startedAt }
|
||||
.take(retentionPerBranch.coerceAtLeast(0))
|
||||
val latestGreen =
|
||||
entries
|
||||
.filter { keepLatestGreen && it.status == BuildStatus.SUCCESS }
|
||||
.maxByOrNull { it.startedAt }
|
||||
newest + listOfNotNull(latestGreen)
|
||||
}.toSet()
|
||||
val removed = results.filterNot { it in kept }
|
||||
if (removed.isNotEmpty()) {
|
||||
|
||||
Reference in New Issue
Block a user