4.9 KiB
Row 305 (#1812, Vikunja 591): shell suites remove the compose network they create
Owner Gizmoduck. Reviewer Filbert. Gate owner Sage. Brief:
docs/plans/2026-10-23_gate-env-rows.md, "Brief: shell suites remove the compose network they create
(Vikunja 591)", at c16e943b9. Base c16e943b9. Mos approved the change in mos-1442 point 2. Mos approved
the two new checks in mos-1445 under mos-1272, adding the presence half.
The leak, as the code has it at c16e943b9
packages/processing-control/src/containers.mjs:16-19.containerArgsbuildsdocker compose run --rm ....--rmremoves the container. The project's<project>_defaultnetwork stays.compose.yamlhas no top-levelname:, so compose names the project after the checkout directory. Every gate worktree left one network. By 10-23 they had used up Docker's address pools.
Does COMPOSE_PROJECT_NAME reach compose? Yes, on every path the two suites take
- Task path.
scripts/run-task.sh:29execsnode scripts/mosaic-task.mjs. Nothing scrubs the env before that:scripts/common.shhas noenv -i, nounsetand no COMPOSE.mosaic-task.mjs:326setsspawnEnv = { ...process.env },:405passesenv: spawnEnvtorunContainer, andcontainers.mjs:25passes those options tospawnSync('docker', ...). - test-release.
release.sh activatecallshealth_check, andhealth_checkcallsrun-task.shat:54, which is the task path above.env MOSAIC_MOCK_RESPONSE=...adds to the env and keeps the rest. The suite calls onlystatus,activateandrollback, sorelease.sh:122compose buildis off its path. - test-task seat cases (
:240,:315-351).agent.sh:209execspackages/processing-control/src/container-cli.mjs, andcontainer-cli.mjs:16callsrunContainerwithenv: process.env. build.sh:13,release.sh:122andverify.sh:40also run compose. Neither suite calls them.
Change (scripts/test-release.sh, scripts/test-task.sh only)
-
After
SANDBOX="$(mktemp -d)", exportCOMPOSE_PROJECT_NAME=mosaic-test-<release|task>-<id>.<id>is the sandbox name after its last dot, lowercased, alphanumeric only. -
remove_compose_networkrunsdocker network rm "${COMPOSE_PROJECT_NAME}_default":- If there's no docker binary, it returns 0.
- If the error says
not foundorNo such network, it returns 0. - On any other failure it prints one stderr line naming the network, then returns 0. That includes a daemon that is down. Sage kept that line in sage-3367 (a).
-
Each existing EXIT trap keeps everything it did and gains
; remove_compose_networkat the end. The trap's own exit status doesn't change the script's. -
One new check per suite, just before the summary. That is after the last Docker step whether or not the live cases ran. Both halves sit inside a
docker infobranch:- the network is present under the run's project name before the explicit
remove_compose_network(this proves the export reached compose); - after the remove, it is absent.
A failing
docker network lsfails the check. Without the daemon, the check prints a skip line. - the network is present under the run's project name before the explicit
-
No
docker compose down, and no other network is touched. No product file changes.
Commits: 541dee2b7 (draft), 3bce852d5 (presence half, mos-1445).
Gate (Sage's slot, in a gap)
- Before the first run, run
docker network rmon a name that was never created and record the daemon's exact wording (sage-3367 b). If the wording matches neither pattern, stop and report to Sage. - Each suite runs whole from a gate worktree, under
timeout -k 10 900. That is far more than 3x the row 302 gate's walls: test-release 3 s, test-task 16 s (mos-1275).- TMPDIR comes from
mktemp -d /mnt/storage/scratch/tmp/gXXX. - Before and after each run, record
docker network lsfiltered tomosaic-test-. The run's network must be absent after. - Grep
^skipand name every skip.
- TMPDIR comes from
- A run killed by the timeout's SIGKILL skips the EXIT trap and leaks its one network. The name is
per-run under
mosaic-test-, so the gate's after-listing finds it and removes it by its exact name (Filbert N1; no code change). - If
docker infoworks but there is no network to find, that's a first-run red. It goes to Sage for Mos, unfixed (mos-1445).
Mutants (mos-1445)
- (a) Drop the export. The new check must go red, because compose uses the directory's project and nothing exists under the run's name.
- (b) Make the function's
docker network rma no-op. The new check must go red, because the network is still present after the remove. - (c) Drop
remove_compose_networkfrom the trap. This one is a known survivor: the explicit call covers the normal path, and the trap covers early exits.
Each mutant runs on an isolated copy of the file. Restores are checked by sha256. After each mutant, the network it
leaves is removed by its exact name (mos-1438). Mutant (a) leaves the worktree directory's
<dir>_default, and mutant (b) leaves the run's ${COMPOSE_PROJECT_NAME}_default.