Skip to content

Persist the backing-service addresses and harden their failure paths - #1311

Open
alistair3149 wants to merge 1 commit into
masterfrom
docker/backing-address-hardening
Open

Persist the backing-service addresses and harden their failure paths#1311
alistair3149 wants to merge 1 commit into
masterfrom
docker/backing-address-hardening

Conversation

@alistair3149

@alistair3149 alistair3149 commented Aug 20, 2026

Copy link
Copy Markdown
Member

Follows-up to #1308

The environment-only configuration of the five backing-service address variables was ambient and non-sticky: any later target containing up -d, run from a shell without the exports (make phpunit starting test backends, tomorrow's make dev), silently recreated the mediawiki container back onto the bundled services; persisting the exports in a shell profile leaked one external backend into every checkout and worktree; and the documented raw compose commands resolved the variables with the opposite precedence to make.

  • Docker/.env is now where the addresses live. The Makefile captures the environment and command-line values before include Docker/.env, giving make the same precedence compose applies with --env-file: environment beats Docker/.env beats the default, and a blank value resolves to the default (a blank environment value hides Docker/.env, as it does for compose). Worktrees bootstrap their own .env, so stacks stay isolated. make print-backing-services shows the resolution, and Docker/tests/test-backing-services.sh pins the precedence table (part of make test-scripts).
  • make test-backends starts missing containers with --no-recreate, so starting test backends no longer recreates the running wiki over config drift; a second up scoped to the three test services still applies compose-file changes to them.
  • install-db runs install.php with MW_CONFIG_FILE pointing its LocalSettings.php detection at a nonexistent path and --confpath sending the generated file to a throwaway directory, so the real LocalSettings.php stays in place throughout: no settings-less window for web requests, and nothing to restore after a failed, interrupted, or concurrent run. A leading mv restores a LocalSettings.php still parked as __LocalSettings.php by the previous recipe.
  • The first-run seed probes pass --connect-timeout=15, failing in seconds against an unreachable external server instead of stalling every make dev for the OS connect timeout (~2 minutes) — generous, so a reachable-but-slow installed server does not read as "not installed".
  • setUpNeo4j refuses to run the test suite's MATCH (n) DETACH DELETE n unless NEO4J_URL_OVERRIDE and NEO4J_URL_READ_OVERRIDE are both set (empty counts as unset) while the wiki has a configured Neo4j backend, so the wipe can only ever hit the dedicated test instance — never the graph the wiki itself is configured against. Any phpunit invocation that bypasses NeoWiki's phpunit.xml.dist (MediaWiki core's standard entry point, in the dev stack or in any MediaWiki install carrying NeoWiki) previously wiped that configured graph, which with NEO4J_HOST can be a shared external one. Backend-less environments keep the "Neo4j not available" skip. The regression test points the configured URL at an unroutable sentinel, so a regressed guard fails to connect instead of wiping a real graph.
  • Docker/README.md documents where to set the variables and the precedence, states which tooling the addresses reach and that they are dialed from inside the containers, and scopes the tools-overlay compose commands to the service they expose so they cannot recreate the rest of a running stack.

Each failure mode was reproduced on master in an isolated worktree stack, then shown fixed: test-backends recreating and repointing the wiki container, install-db stranding LocalSettings.php with broken reruns, the probe hanging past 20s against a blackholed address, and setUpNeo4j wiping the wiki's graph without the overrides. make reset exercises the new install-db happy path end to end.

Considered, omitted:

  • A refusal at the URL-resolution point (NeoWikiConfigFactory declining the config fallback under MW_PHPUNIT_TEST) would also stop override-less page-saving tests from projecting into the wiki's graph; left out as a production-code change deserving its own discussion.
  • The probe still cannot distinguish an unreachable server from an empty one; the timeout only bounds how long that ambiguity stalls make dev.
  • Values in Docker/.env are parsed by both make and compose, which disagree on quoting and $; documented in .env.dist rather than normalized in make.
  • make -e test-scripts already fails on master in the pre-existing test-services.sh; not addressed here.
  • --no-recreate support under podman-compose was not verified on every version the repo's podman path may meet.

AI-authored — Claude Code, Fable 5 (ultracode); six findings picked by @alistair3149 from an in-session review of #1308, plus a README trim he requested; diff not yet human-reviewed; each fix reproduced-then-verified in a worktree stack, adversarial code-review findings verified and applied (incl. replacing the install flow with MW_CONFIG_FILE after an A/B check), harness and PHPUnit regression tests red→green and mutation-tested, non-Database lane (1909 tests) and phpcs+phpstan green locally, CI pending on the final push.

@alistair3149
alistair3149 force-pushed the docker/backing-address-hardening branch 4 times, most recently from 015c353 to a375e61 Compare August 20, 2026 15:33
Follows-up to #1308

The environment-only configuration of the five backing-service address
variables was ambient and non-sticky: any later target containing `up -d`,
run from a shell without the exports (`make phpunit` starting test backends,
tomorrow's `make dev`), silently recreated the mediawiki container back onto
the bundled services; persisting the exports in a shell profile leaked one
external backend into every checkout and worktree; and the documented raw
compose commands resolved the variables with the opposite precedence to make.

* Docker/.env is now where the addresses live. The Makefile captures the
  environment and command-line values before `include Docker/.env`, giving
  make the same precedence compose applies with --env-file: environment
  beats Docker/.env beats the default, and a blank value resolves to the
  default (a blank environment value hides Docker/.env, as it does for
  compose). Worktrees bootstrap their own .env, so stacks stay isolated.
  `make print-backing-services` shows the resolution, and
  Docker/tests/test-backing-services.sh pins the precedence table (part of
  `make test-scripts`).
* `make test-backends` starts missing containers with --no-recreate, so
  starting test backends no longer recreates the running wiki over config
  drift; a second up scoped to the three test services still applies
  compose-file changes to them.
* install-db runs install.php with MW_CONFIG_FILE pointing its
  LocalSettings.php detection at a nonexistent path and --confpath sending
  the generated file to a throwaway directory, so the real LocalSettings.php
  stays in place throughout: no settings-less window for web requests, and
  nothing to restore after a failed, interrupted, or concurrent run. A
  leading mv restores a LocalSettings.php still parked as
  __LocalSettings.php by the previous recipe.
* The first-run seed probes pass --connect-timeout=15, failing in seconds
  against an unreachable external server instead of stalling every
  `make dev` for the OS connect timeout (~2 minutes) — generous, so a
  reachable-but-slow installed server does not read as "not installed".
* setUpNeo4j refuses to run the test suite's `MATCH (n) DETACH DELETE n`
  unless NEO4J_URL_OVERRIDE and NEO4J_URL_READ_OVERRIDE are both set
  (empty counts as unset) while the wiki has a configured Neo4j backend, so
  the wipe can only ever hit the dedicated test instance — never the graph
  the wiki itself is configured against. Any phpunit invocation that
  bypasses NeoWiki's phpunit.xml.dist (MediaWiki core's standard entry
  point, in the dev stack or in any MediaWiki install carrying NeoWiki)
  previously wiped that configured graph, which with NEO4J_HOST can be a
  shared external one. Backend-less environments keep the "Neo4j not
  available" skip. The regression test points the configured URL at an
  unroutable sentinel, so a regressed guard fails to connect instead of
  wiping a real graph.
* Docker/README.md documents where to set the variables and the precedence,
  states which tooling the addresses reach and that they are dialed from
  inside the containers, and scopes the tools-overlay compose commands to
  the service they expose so they cannot recreate the rest of a running
  stack.

Each failure mode was reproduced on master in an isolated worktree stack,
then shown fixed: test-backends recreating and repointing the wiki
container, install-db stranding LocalSettings.php with broken reruns, the
probe hanging past 20s against a blackholed address, and setUpNeo4j wiping
the wiki's graph without the overrides. `make reset` exercises the new
install-db happy path end to end.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@alistair3149
alistair3149 force-pushed the docker/backing-address-hardening branch from a375e61 to 215139d Compare August 20, 2026 17:31
@alistair3149
alistair3149 marked this pull request as ready for review August 20, 2026 17:46
@alistair3149
alistair3149 requested a review from malberts August 20, 2026 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant