Fix port auto-allocation on host conflict#820
Merged
Conversation
The promise of `make dev` "just works" across worktrees was not being kept: since `.env.dist` ships `MW_SERVER_PORT=8484`, every fresh clone hit the "explicit request" branch in `set-port.sh` on first run and skipped the host-port-free check, so a busy 8484 (or any second worktree) failed at `docker compose up` with a cryptic bind error. Three fixes, scoped to the same code path: * `Makefile` `ensure-port`: skip allocation when our compose stack is already running, so an idempotent `make dev` re-run does not silently reallocate and force-recreate the live mediawiki container. When the stack is down and no `port=` override is given, pass empty string to `set-port.sh` so the existing `allocate()` logic (reuse if free, else range-scan) actually runs. * `set-port.sh` explicit-request branch: validate that the requested port is free and exit with a clear error if not, rather than writing it back and letting docker bind fail later with an opaque message. * `set-port.sh` `allocate()`: when the existing `.env` value is held AND outside the configured range, treat it as a deliberate user override and error out instead of silently swapping it for an in-range port. Follows-up to #811 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Establishes Docker/tests/ as the home for shell-script tests at the Docker layer, keeping the top-level tests/ subtree PHP-only. * Docker/test.sh -> Docker/tests/smoke.sh. Renamed to a descriptive name (was ambiguous "test.sh"), and now resolves Docker/.env relative to its own script directory so it can be invoked from anywhere. * Docker/tests/test-set-port.sh added. Locks in the coverage matrix from the previous commit as an executable regression suite, catching the Morne fresh-clone bug and the three new behaviours of the fix: idempotent re-run, explicit-port-validation, and out-of-range override protection. Uses python3 to hold contested ports (backlog 128 + accept-and-close loop to avoid kernel SYN drops once the accept queue fills). Allocates into a high MW range (38484-38499) so a busy 8484-8499 on the host does not perturb assertions. * New `make test-scripts` target runs the regression suite. Kept out of `make test` / `make ci` so it does not become a CI gate on the first iteration. Promote to CI after a few sprints once stability is confirmed. Note: PR #818's draft `smoke-test` target needs to point at `Docker/tests/smoke.sh` after this lands. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.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.
Follows-up to #811
The promise of
make dev"just works" across worktrees was not being kept:since
.env.distshipsMW_SERVER_PORT=8484, every fresh clone hit the"explicit request" branch in
set-port.shon first run and skipped thehost-port-free check, so a busy 8484 (or any second worktree) failed at
docker compose upwith a cryptic bind error.Commits
1. Fix port auto-allocation on host conflict
Three fixes, scoped to the same code path:
Makefileensure-port: skip allocation when our compose stack isalready running, so an idempotent
make devre-run does not silentlyreallocate and force-recreate the live mediawiki container. When the
stack is down and no
port=override is given, pass empty string toset-port.shso the existingallocate()logic (reuse if free, elserange-scan) actually runs.
set-port.shexplicit-request branch: validate that the requestedport is free and exit with a clear error if not, rather than writing
it back and letting docker bind fail later with an opaque message.
set-port.shallocate(): when the existing.envvalue is heldAND outside the configured range, treat it as a deliberate user
override and error out instead of silently swapping it for an
in-range port.
2. Add Docker/tests/ with smoke test rename and set-port regression suite
Establishes
Docker/tests/as the home for shell-script tests at theDocker layer, keeping the top-level
tests/subtree PHP-only.Docker/test.sh→Docker/tests/smoke.sh. Renamed (was an ambiguous"test.sh") and now resolves
.envrelative to the script so it canbe invoked from anywhere.
Docker/tests/test-set-port.shlocks in the coverage matrix as anexecutable regression suite. Uses python3 to hold contested ports
(backlog 128 + accept-and-close loop), allocates into a high MW range
(38484-38499) so a busy 8484-8499 on the host does not perturb
assertions.
make test-scriptsruns the regression suite. Kept out ofmake test/make ciso it does not become a CI gate on the firstiteration. Promote to CI after a few sprints once stability is
confirmed.
Heads-up: PR #818 references
Docker/test.shin its plannedsmoke-testtarget — that path becomesDocker/tests/smoke.shafterthis PR lands. (Will leave a note on #818.)
Coverage matrix
.env=8484, A holds itport=N, N freeport=N, N held by other.env=9999, 9999 free.env=9999, 9999 heldTest plan
make test-scriptspass..envwith python TCP listeners holding the contested port for each row.