Task 11: a disposable PostgreSQL 16 environment for integration testing - #11
Merged
Conversation
docker-compose.postgres-test.yml brings up postgres:16 on a named volume with
pg_stat_statements preloaded, published on 127.0.0.1 only. Every credential is
a ${...} substitution from .env.test.local, which is gitignored; the Compose
file holds no password, no port, and no connection string, so it is safe to
read in a public repository.
Substitutions use ${VAR:?message} rather than a default value. A default lets a
typo in the env file start a server with credentials nobody chose, and the
failure then surfaces somewhere less obvious than the mistake.
CREATE EXTENSION pg_stat_statements runs from testdata/postgres-test-init.sql
at initdb time rather than as a documented manual step. The profiler degrades
gracefully when the extension is absent, so a skipped step would leave the
integration suite quietly exercising the degraded path instead of the one it
means to cover.
TestComposeSecrecy asserts these properties rather than trusting review: no
connection string in the Compose file, every credential field a bare ${...},
every published port bound to loopback, the env file ignored, no tracked .env*
file, and no credentialed URL in the docs. Rebinding to 0.0.0.0, hardcoding a
password, or dropping the preload each turns the suite red.
Running the tool against the live container found a real bug. PG_DUMP_ARGS was
spliced in ahead of --version, producing `pg_dump -w --version`. pg_dump
handles --version by comparing argv[1] before getopt runs and has no entry for
it in the long-option table, so anything ahead of it -- even a harmless -w --
makes it an unrecognized option and pg_dump exits 1 with only a "try --help"
hint. The unit test asserted the wrong argv and the fake matched on
`"--version" in argv`, so neither noticed. Fixed to `[pg_dump, "--version"]`,
with both tests corrected.
docs/TESTING.md documents start, health check, run, stop, and reset. Every
command passes --env-file, because interpolation runs for ps and exec and down
too. The health check expands credentials inside the container, so none reaches
shell history. There is deliberately no committed example env file: that is
where a real connection string eventually gets pasted, and no reviewer reading
the diff could tell the value was meant to be fake.
Verified end to end against the container: nine bundle entries, no warnings,
server_version_num 160015, stats_reset captured, and the host listening on
127.0.0.1 only. Runtime was Podman behind a docker shim; the Compose file uses
no Docker-specific extension.
363 tests pass; --check-safety, ruff, and the 3.9 grammar check are clean.
Co-Authored-By: roachdev-claude <roachdev-claude-bot@cockroachlabs.com>
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.
Adds the Docker/Podman environment the integration suite will run against, plus the docs and guard tests that keep it from leaking anything.
What's here
docker-compose.postgres-test.yml—postgres:16on a named volume,pg_stat_statementspreloaded, published on127.0.0.1only, with apg_isreadyhealth check so--waitblocks until the server actually answers. Every credential is a${...}substitution from the gitignored.env.test.local. The file holds no password, no port, and no connection string, so it is safe to read in a public repository.Substitutions are
${VAR:?message}, never${VAR:-default}. A default lets a typo in the env file start a server with credentials nobody chose, and the failure then surfaces somewhere less obvious than the mistake.testdata/postgres-test-init.sql—CREATE EXTENSION pg_stat_statements, mounted read-only at/docker-entrypoint-initdb.d/instead of being a documented manual step after start. The profiler degrades gracefully when the extension is absent, so a skipped step would leave the integration suite quietly exercising the degraded path rather than the one it means to cover. The cost is that it only runs against an empty volume, which is whydown -vgets its own section in the docs.docs/TESTING.md— start, health check, run, stop, reset. Every command passes--env-file, because interpolation runs forpsandexecanddowntoo, not justup. The health check expands credentials inside the container, so none reaches shell history or a host process's command line.There is deliberately no committed example env file. That is where a real connection string eventually gets pasted, and no reviewer reading the diff could tell the value was supposed to be fake. The doc lists variable names in a table instead.
A real bug, found by running it
The first run against the live container failed at
pg_dump exited with status 1.PG_DUMP_ARGSwas being spliced in ahead of--version, producingpg_dump -w --version. pg_dump handles--versionby comparingargv[1]before getopt runs, and its long-option table has no entry for it — so anything ahead of it, even a harmless-w, makes it an unrecognized option and pg_dump exits 1 with nothing but a "try --help" hint.The unit test asserted the wrong argv and the fake matched on
\"--version\" in argv, so neither noticed. Now[pg_dump, \"--version\"]exactly, with both tests corrected. This is precisely the class of bug the Docker environment exists to catch, and it showed up before the integration suite that was meant to catch it.Guard tests
TestComposeSecrecyasserts the properties rather than trusting review: no://in the Compose file, no token key, every credential field a bare${...}, no substitution carrying a default, every published port prefixed127.0.0.1:, the preload present,.env.test.localgitignored, no tracked.env*file, and no credentialed URL in the docs.Each was mutation-tested. Rebinding to
0.0.0.0, hardcoding a password, switching to${VAR:-postgres}, dropping the preload, and pasting a URL into a comment all turn the suite red.Verified
Against the live container: nine bundle entries, no warnings,
server_version_num160015,stats_resetcaptured. Host listener confirmed as127.0.0.1.55432only — a connection to the machine's LAN address is refused.Runtime was Podman 5.8.1 behind a
dockerCLI shim withpodman-compose. The Compose file uses no Docker-specific extension, and the docs say so rather than assuming Docker Desktop.