## The Problem After PR#111 `BuildDefinition.applyTo` had the highest Mutation-CRAP score of Werkator: 34 at a complexity of 34. A score is never below the complexity, so no test could bring it under the limit of 15. The method laid a build definition over its branch's settings in one `copy` of 21 fields, each with its own `?:` fallback, the docker and werkdock blocks nested inside. What the definition says falls into three groups, but the method did not show them: what the build runs, the rules the instance runs it under, and the sandbox it runs in. Only one test checked a single field of it (Scenario#72.01); every other field was held only by tests of the config loader. ## Non-Goals - No change in behaviour: which settings a definition can say, how they inherit, and which are pinned stay as they are. ## The Scenarios ### Feature: A build definition laid over its branch's settings #### Scenario#112.01: A definition that says nothing runs the branch's settings unchanged So that `builds.<name>` with only a trigger builds exactly what the branch describes. - **Given** a branch with a non-default value for every setting - **When** an empty definition, or one with empty docker and werkdock blocks, is applied - **Then** the result equals the branch's settings ##### Verified by - [BuildDefinitionUnitTest](../../src/test/kotlin/de/hoennig/werkator/config/BuildDefinitionUnitTest.kt) — Scenario#112.01 #### Scenario#112.02: Every setting a definition says replaces the branch's own So that no key of `builds.<name>` is read and then silently dropped. - **Given** the same branch, and a definition saying every setting, docker and werkdock included, with other values - **When** the definition is applied - **Then** every setting is the definition's ##### Verified by - [BuildDefinitionUnitTest](../../src/test/kotlin/de/hoennig/werkator/config/BuildDefinitionUnitTest.kt) — Scenario#112.02 #### Scenario#112.03: A definition saying some settings of a block keeps the rest of that block So that `docker.image` alone does not reset the branch's network, socket or environment. - **Given** the same branch, and a definition saying only the timeout, the docker image and the werkdock rootfs - **When** the definition is applied - **Then** those three are the definition's, everything else is the branch's ##### Verified by - [BuildDefinitionUnitTest](../../src/test/kotlin/de/hoennig/werkator/config/BuildDefinitionUnitTest.kt) — Scenario#112.03 ## The Solution `applyTo` lays the definition over the branch in three blocks: | Block | Settings | | ------------- | ------------------------------------------------------------------------ | | `withWork` | `buildCommand`, `cleanCommand`, `artifactDirs`, `stdoutLog`, `stderrLog` | | `withRules` | `requirePullRequest`, `statusContext`, `timeout`, `restartsInstance` | | `withSandbox` | `docker`, `werkdock` | `DockerOverrides.applyTo` and `WerkdockOverrides.applyTo` lay each sandbox's overrides over the branch's sandbox of that kind. The overrides and their config class now stand side by side, where Scenario#72.03 already holds that every setting of the one exists in the other. Measured with PIT as the nightly build runs it: | Method | Before | After | | ----------------------------- | ------ | ---------- | | `BuildDefinition.applyTo` | 34 | no mutants | | `BuildDefinition.withWork` | — | 6 | | `BuildDefinition.withRules` | — | 5 | | `BuildDefinition.withSandbox` | — | 5 | | `DockerOverrides.applyTo` | — | 8 | | `WerkdockOverrides.applyTo` | — | 6 | Every mutant of the new methods is killed, none is `INCONCLUSIVE`; each score equals its complexity. The gate `maxMutationCrap` falls from 35 to 34: the highest score left is `CapacitySizing.cpu` at 33.17. ## Additional Changes - Version 1.34.9 with its release note. - `BuildExecutorUnitTest`, Scenario#108.05, waits for the executing build's process before it cancels the build: a build counts as running before its process is started, and a cancel in between left no process to see terminated (`List is empty`, seen once in this PR's local build). ## Follow-up PRs - `CapacitySizing.cpu` (33.17) in its own PR. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: mhoennig <michael@hoennig.de> Reviewed-on: #112
95 lines
4.6 KiB
Markdown
95 lines
4.6 KiB
Markdown
> **WARNING:** This document describes only the change applied in this PR.
|
|
> It may already be outdated once the next PR is merged.
|
|
> Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.
|
|
|
|
## The Problem
|
|
|
|
After PR#111 `BuildDefinition.applyTo` had the highest Mutation-CRAP score of Werkator: 34 at a complexity of 34.
|
|
A score is never below the complexity, so no test could bring it under the limit of 15.
|
|
|
|
The method laid a build definition over its branch's settings in one `copy` of 21 fields, each with its own `?:` fallback, the docker and werkdock blocks nested inside.
|
|
What the definition says falls into three groups, but the method did not show them:
|
|
what the build runs, the rules the instance runs it under, and the sandbox it runs in.
|
|
Only one test checked a single field of it (Scenario#72.01); every other field was held only by tests of the config loader.
|
|
|
|
## Non-Goals
|
|
|
|
- No change in behaviour: which settings a definition can say, how they inherit, and which are pinned stay as they are.
|
|
|
|
## The Scenarios
|
|
|
|
### Feature: A build definition laid over its branch's settings
|
|
|
|
#### Scenario#112.01: A definition that says nothing runs the branch's settings unchanged
|
|
|
|
So that `builds.<name>` with only a trigger builds exactly what the branch describes.
|
|
|
|
- **Given** a branch with a non-default value for every setting
|
|
- **When** an empty definition, or one with empty docker and werkdock blocks, is applied
|
|
- **Then** the result equals the branch's settings
|
|
|
|
##### Verified by
|
|
|
|
- [BuildDefinitionUnitTest](../../src/test/kotlin/de/hoennig/werkator/config/BuildDefinitionUnitTest.kt) — Scenario#112.01
|
|
|
|
#### Scenario#112.02: Every setting a definition says replaces the branch's own
|
|
|
|
So that no key of `builds.<name>` is read and then silently dropped.
|
|
|
|
- **Given** the same branch, and a definition saying every setting, docker and werkdock included, with other values
|
|
- **When** the definition is applied
|
|
- **Then** every setting is the definition's
|
|
|
|
##### Verified by
|
|
|
|
- [BuildDefinitionUnitTest](../../src/test/kotlin/de/hoennig/werkator/config/BuildDefinitionUnitTest.kt) — Scenario#112.02
|
|
|
|
#### Scenario#112.03: A definition saying some settings of a block keeps the rest of that block
|
|
|
|
So that `docker.image` alone does not reset the branch's network, socket or environment.
|
|
|
|
- **Given** the same branch, and a definition saying only the timeout, the docker image and the werkdock rootfs
|
|
- **When** the definition is applied
|
|
- **Then** those three are the definition's, everything else is the branch's
|
|
|
|
##### Verified by
|
|
|
|
- [BuildDefinitionUnitTest](../../src/test/kotlin/de/hoennig/werkator/config/BuildDefinitionUnitTest.kt) — Scenario#112.03
|
|
|
|
## The Solution
|
|
|
|
`applyTo` lays the definition over the branch in three blocks:
|
|
|
|
| Block | Settings |
|
|
| ------------- | ------------------------------------------------------------------------ |
|
|
| `withWork` | `buildCommand`, `cleanCommand`, `artifactDirs`, `stdoutLog`, `stderrLog` |
|
|
| `withRules` | `requirePullRequest`, `statusContext`, `timeout`, `restartsInstance` |
|
|
| `withSandbox` | `docker`, `werkdock` |
|
|
|
|
`DockerOverrides.applyTo` and `WerkdockOverrides.applyTo` lay each sandbox's overrides over the branch's sandbox of that kind.
|
|
The overrides and their config class now stand side by side, where Scenario#72.03 already holds that every setting of the one exists in the other.
|
|
|
|
Measured with PIT as the nightly build runs it:
|
|
|
|
| Method | Before | After |
|
|
| ----------------------------- | ------ | ---------- |
|
|
| `BuildDefinition.applyTo` | 34 | no mutants |
|
|
| `BuildDefinition.withWork` | — | 6 |
|
|
| `BuildDefinition.withRules` | — | 5 |
|
|
| `BuildDefinition.withSandbox` | — | 5 |
|
|
| `DockerOverrides.applyTo` | — | 8 |
|
|
| `WerkdockOverrides.applyTo` | — | 6 |
|
|
|
|
Every mutant of the new methods is killed, none is `INCONCLUSIVE`; each score equals its complexity.
|
|
|
|
The gate `maxMutationCrap` falls from 35 to 34: the highest score left is `CapacitySizing.cpu` at 33.17.
|
|
|
|
## Additional Changes
|
|
|
|
- Version 1.34.9 with its release note.
|
|
- `BuildExecutorUnitTest`, Scenario#108.05, waits for the executing build's process before it cancels the build: a build counts as running before its process is started, and a cancel in between left no process to see terminated (`List is empty`, seen once in this PR's local build).
|
|
|
|
## Follow-up PRs
|
|
|
|
- `CapacitySizing.cpu` (33.17) in its own PR.
|