> **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#108 the rest of `BuildExecutor` above the limit was its process handling: copying a command's output into the logs, sampling its processor time, keeping its deadline, ending its process tree. `runBuildCommands` stood at 20.78; it opened the three log files in three nested `use` blocks, and every `use` is several branches. This part needs real processes, and the only test with real processes, `BuildExecutorIntegrationTest`, takes minutes and stays out of the nightly mutation build. ## Non-Goals - No change in behaviour: the same logs, the same deadline, the same termination. - `BuildExecutorIntegrationTest` stays out of the nightly run. ## The Scenarios ### Feature: A build command's process #### Scenario#109.01: A command's output goes to its log and to the live log, and its exit code is the answer So that the page that follows a build shows both streams, and each log only its own. ##### Verified by - [CommandProcessIntegrationTest](../../src/test/kotlin/de/hoennig/werkator/build/CommandProcessIntegrationTest.kt) — Scenario#109.01 #### Scenario#109.02: A command past its deadline is told, its whole tree is ended, and it reports a failure So that a hanging build cannot outlive its timeout through a child process. - **Given** a command that starts a child and waits for it, and a deadline of 300 ms - **When** the command is awaited - **Then** the timeout is reported once, the command and its child are gone, and the exit code is not 0 - **And** a command within its deadline ends with its own exit code ##### Verified by - [CommandProcessIntegrationTest](../../src/test/kotlin/de/hoennig/werkator/build/CommandProcessIntegrationTest.kt) — Scenario#109.02 #### Scenario#109.03: Ending a process ends its whole tree So that a cancellation leaves no child running. ##### Verified by - [CommandProcessIntegrationTest](../../src/test/kotlin/de/hoennig/werkator/build/CommandProcessIntegrationTest.kt) — Scenario#109.03 #### Scenario#109.04: The processor time of a command is measured where it is the build's own, and only there So that a Docker build records no processor time rather than the client's second. ##### Verified by - [CommandProcessIntegrationTest](../../src/test/kotlin/de/hoennig/werkator/build/CommandProcessIntegrationTest.kt) — Scenario#109.04 #### Scenario#109.05: A log name that is a path is refused before anything is opened So that a build's output never lands outside its staging directory. ##### Verified by - [CommandProcessIntegrationTest](../../src/test/kotlin/de/hoennig/werkator/build/CommandProcessIntegrationTest.kt) — Scenario#109.05 ## The Solution - `CommandProcess` is one command while it runs: the pumps into the logs, the processor-time sampling, `awaitExit` with the deadline, `finish`, and `destroyTree` for the whole process tree. - `BuildLogs` opens the three logs of a build and closes them together; `runBuildCommands` uses it in one `use`. - `BuildExecutor` keeps the order of the commands; `startCommand` and `becomeBuildProcess` make a started process the one a cancellation ends, preparation processes included; `deadlineOf` takes the build's one deadline. - `CommandProcessIntegrationTest` runs real processes of a second or two, about four seconds in all, so the nightly run keeps it. Measured with PIT as the nightly build runs it: | Method | Before | After | | ---------------------------------------- | ------ | ----- | | `BuildExecutor.runBuildCommands` | 20.78 | 6.84 | | `destroyTree` (was `destroyProcessTree`) | 12 | 4.94 | | `awaitExit` (was `waitForBounded`) | 9.49 | 4.03 | | the processor-time sampling | 12 | 4.13 | Every method of `BuildExecutor` is below 15 now; the highest is `settle` at 12.19. The gate `maxMutationCrap` stays at 46: the highest score of Werkator is `NginxProxyManager.cleanupStaleContainers` at 45.04. ## Additional Changes - Version 1.34.6 with its release note. ## Follow-up PRs - `NginxProxyManager.cleanupStaleContainers` (45.04), `UiFormats.cpuTime` (43.81) and `MetricsConfiguration.monitoredDisks` (42), the highest scores left.