fix: refuse a null wherever docker compose refuses one#61
Merged
Conversation
compose2pod is a drop-in replacement for docker compose on rootless runners:
the file it converts is the file the developer runs locally. That makes
accepting-what-Docker-refuses actively harmful rather than merely lax -- the
document is already broken in the real workflow, so converting it anyway means
CI goes green on a file docker compose would not run. A false green is worse
than a hard error.
So the test is not "does this null drop behavior?" but "would docker compose
run this file at all?". Eight positions failed it, accepted here and refused by
docker compose config, each emitting nothing:
healthcheck.test / .interval / .timeout / .retries / .start_period
deploy.resources / .limits / .reservations
top-level networks: / volumes: / secrets: / configs:
This reverses changes/2026-07-13.10's null-scalar ruling (a null healthcheck
timeout/retries/start_period meant "unset"). That ruling was taken on the stated
premise that it matched docker compose config. It does not -- Docker refuses all
three. The premise was wrong, so the conclusion goes with it.
A null INSIDE a value is untouched and still accepted, because Docker accepts it
too: environment: {KEY: null} is host-passthrough, labels: {KEY: null} an empty
label.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Carries #60's null policy down into every nested and top-level position. Design:
planning/changes/2026-07-14.08-nested-null-content-blocks.md.The principle, which I had wrong
compose2pod is a drop-in replacement for
docker composeon rootless runners — the file it converts is the same file the developer runs locally withdocker compose up. That makes the asymmetry sharp:docker composewould not run. A false green is worse than a hard error.So the test is not "does this null drop behavior?" but "would
docker composerun this file at all?" If it wouldn't, there is no point emitting a podman script for it.Eight positions failed that test
Accepted here, refused by
docker compose config(v5.1.2), each silently emitting nothing:healthcheck.test,.interval,.timeout,.retries,.start_perioddeploy.resources,.limits,.reservationsnetworks:,volumes:,secrets:,configs:Two of them drop real behavior — a bare
test:makes the healthcheck evaporate, a barelimits:means you get no memory limits. The rest drop nothing on their own, but they carry a document Docker won't run.This reverses an earlier ruling — and the reason it has to
2026-07-13.10ruled that a nullhealthcheck.timeout/retries/start_periodmeans "unset". I told the maintainer that matcheddocker compose config. It does not — Docker refuses all three. The ruling was taken on a false premise I supplied, so the conclusion goes with it. The architecture doc contained the same false sentence ("This matchesdocker compose config"); it is corrected here.Not parity for its own sake
A null inside a value is untouched and still accepted, because Docker accepts it:
environment: {KEY: null}is host-passthrough,labels: {KEY: null}an empty label. compose2pod also keeps its documented divergences elsewhere (it never builds;profilesis closure-authoritative). Parity on refusal is what the drop-in role demands — nothing more.Verification
All 12 null positions measured against
docker compose config, before and after: zero false greens remain, and no over-rejection (host-passthrough, empty labels, absent keys, andcommand: nullall still accepted).645 tests at 100% coverage; integration green against real podman.
🤖 Generated with Claude Code