PR#55 added docker.socket to DockerConfig and to both pinning lists, but not to DockerOverrides. The key was parsed, pinned and enforced, and then dropped when the definition was applied — leaving the default false. Since ADR 0007 the sandbox lives under builds.<name>.docker, so the key was unreachable from the only section a current configuration uses; only the deprecated branches section could set it, which is where the existing test put it. On vm4006 this cost every Testcontainers test: the socket was never mounted, and the build found no Docker environment at all. Beside the three-line fix, a test now compares DockerConfig against DockerOverrides and WerkdockConfig against WerkdockOverrides, so a key added to a sandbox and forgotten in its overrides fails the build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: mhoennig <michael@hoennig.de> Reviewed-on: #72
6.1 KiB
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.
Related Links
- PR#55 — introduced
docker.socketas an opt-in, pinned key. - ADR 0007 — build definitions; the reason the key's only usable spelling is
builds.<name>.docker.socket.
The Problem
vm4006 was updated from 1.2.0 to 1.18.1 and every test using Testcontainers failed at once:
Could not find a valid Docker environment. Attempted configurations were:
UnixSocketClientProviderStrategy: failed with exception InvalidConfigurationException
(Could not find unix domain socket). Root cause NoSuchFileException (/var/run/docker.sock)
The host's configuration said builds.default.docker.socket: true, and werkator config:print confirmed it.
The socket was nevertheless not mounted into the build container.
DockerOverrides — the shape a build definition carries its docker settings in — had no socket field.
PR#55 added the key to DockerConfig, to the strip list and to the enforcement list, and stopped there.
So the key was parsed, pinned and enforced correctly, and then BuildDefinition.applyTo built the effective settings field by field and dropped it, leaving the data-class default false.
The key was therefore unreachable from the only section a current configuration uses.
Since ADR 0007 the sandbox policy lives under builds.<name>.docker; only the deprecated branches section could still set it — which is exactly where the existing test for the socket's pinning put it, which is why the gap survived a security PR with tests of its own.
This is the failure mode this repository names in AGENTS.md: a key that is silently ignored rather than refused means a build that quietly stops working.
Here it meant a CI host that could no longer run a single integration test, with a configuration that read correctly on the page and in config:print.
Non-Goals
- No change to what is pinned or how: the pinning was never the defect. A branch still cannot hand itself the socket.
- No new configuration key, and no change to the default (
false).
The Scenarios
Feature: a build definition can say what its build needs
Background
- A build definition (
builds.<name>) carries its settings as nullable overrides;applyTolays them over the branch settings, andnullinherits. docker.socketmounts the host's Docker socket into the build container. It is pinned: the host decides, a branch never.
Scenario#72.01: A definition's socket setting reaches the build
So that a build that talks to the Docker daemon itself can be configured the way every other setting is.
- Given a build definition with
docker.socket: true - When its settings are applied to the branch config
- Then the resulting settings have the socket enabled
Verified by
Scenario#72.02: A definition that says nothing inherits
So that the override stays an override.
- Given a branch config with the socket enabled
- and a definition that does not mention it
- When the definition is applied
- Then the socket stays enabled
Verified by
Scenario#72.03: Every sandbox setting can be said in a definition
So that the next key added to a sandbox cannot be forgotten in the overrides the same way.
- Given the
DockerConfig/DockerOverridesandWerkdockConfig/WerkdockOverridesclass pairs - When their properties are compared
- Then no setting exists that a build definition cannot express
Verified by
Scenario#72.04: The host's socket survives a branch layer
So that the shape vm4006 actually runs is covered end to end, not only the class pair.
- Given a host that configures the sandbox under
builds.default, socket included- and a branch whose committed configuration says nothing about docker
- When the branch's build settings are resolved
- Then the socket is still enabled
Verified by
The Solution
DockerOverrides gets a socket: Boolean?, and applyTo carries it over like every other docker setting.
Three lines, and the bug is gone.
The fourth change is the one worth having: Scenario#72.03 compares the properties of DockerConfig against DockerOverrides and WerkdockConfig against WerkdockOverrides.
Two data classes that have to be kept in step by hand will drift, and this one drifted in a security PR without anything noticing for four days.
The test does not check a behaviour; it checks that the pair is complete, which is the property that was actually violated.
It is worth saying what this test cannot do: a key added to DockerConfig and forgotten in the overrides is caught, because nothing else in the codebase would name it.
The defect found here would in fact have been caught twice over, since the scenarios above also fail to compile without the field.
Additional Changes
- None.
Prerequisite PRs
- None.
Follow-up PRs
- Artifacts are served with Spring's reflected-file-download default
Content-Disposition: inline;filename=f.txt, so a downloadedhsadmin-ng-0.0.1-SNAPSHOT.jarwould be saved asf.txt. Found while verifying vm4006. - The systemd unit
init --systemdgenerates declares noSuccessExitStatus=143, so every clean stop is journalled asFailed with result 'exit-code'.