A build definition carries the whole build; branches is legacy
`builds` and the legacy `branches` are now either/or: `branches` is read only while the merged configuration defines no build at all — a leftover `builds.maxConcurrent` is not one — and ignored with a warning as soon as one exists. Two half-answers to "what does this build run" would silently pull against each other, and the committed configs still carrying both must not change behaviour before they are migrated. A definition therefore gained the settings it was missing: `requirePullRequest` and `docker.enabled`/`network`. Those stay pinned — `stripPinned` now removes them from a branch layer wherever they appear, in a definition as well as in a legacy branch entry. `builds.default` becomes the base every other definition inherits its settings from, never its trigger: `onPush`, `atTimes`, `branches`, and `activeWithin` say when and where *this* build runs. The inheritance is applied after all layers are merged, which is what makes a build invented on a branch inherit the host's sandbox policy instead of the data-class default — otherwise a branch could get a native build past the pinning by defining a job the host has never heard of. Two bugs found on the way, both the same shape as the build command the artifact page used to get wrong: - `FileArtifactStore` read the artifact directories from the plain branch settings, so a job adding its own `artifactDirs` never had them stored. It goes through `GitTallyConfig.buildSettings` now, like everything else that asks what a build runs. - `Watcher.definitionsFor` cached the per-branch definitions by head commit alone, so an edited machine or project config only took effect once the branch moved — on a quiet branch, never. The primary config is part of the cache key now.
This commit is contained in:
@@ -545,6 +545,29 @@ class WatcherTest : FunSpec() {
|
||||
verify(exactly = 1) { harness.gitService.showFileAtCommit("commit-2", Watcher.CONFIG_FILE, any()) }
|
||||
}
|
||||
|
||||
test("an edited primary config takes effect without the branch moving") {
|
||||
val harness = Harness()
|
||||
every { harness.gitService.originBranches(any()) } returns listOf("main")
|
||||
every { harness.gitService.originBranchHeads(any()) } returns mapOf("main" to "commit-1")
|
||||
every { harness.gitService.originHeadCommit("main", any()) } returns "commit-1"
|
||||
|
||||
harness.watcher.poll(harness.workingDir)
|
||||
harness.startedBuilds.shouldBeEmpty()
|
||||
|
||||
// the machine config gains a scheduled build while the branch stays where it is:
|
||||
// caching the definitions by head commit alone would never notice
|
||||
val edited =
|
||||
GitTallyConfig(
|
||||
buildDefinitions = mapOf("nightly" to BuildDefinition(atTimes = listOf("11:00"))),
|
||||
)
|
||||
every { harness.configLoader.load(any()) } returns edited
|
||||
every { harness.configLoader.loadWithBranchLayer(any(), anyNullable()) } returns edited
|
||||
|
||||
harness.watcher.poll(harness.workingDir)
|
||||
|
||||
verify { harness.buildExecutor.startBuild("main", "commit-1", any(), "nightly") }
|
||||
}
|
||||
|
||||
test("an unreadable branch config falls back to the primary definitions instead of failing the poll") {
|
||||
val harness = Harness()
|
||||
every { harness.gitService.originBranches(any()) } returns listOf("main")
|
||||
|
||||
Reference in New Issue
Block a user