fix: discover orphan compose networks so wt prune can reclaim subnet slots#4
Merged
Merged
Conversation
…Repo Docker Compose only removes its project network during `compose down`. When containers are reaped some other way — `docker rm -f`, Docker Desktop reset, OS crash, or a `wt new` killed mid-flight before the rollback path runs — the network survives but loses its only link to the wt label set, which was previously only applied to containers. Each leaked network still consumes a subnet slot from Docker's default address pool. After ~30 leaks `wt new` fails with `all predefined address pools have been fully subnetted` and `wt prune` cannot find the projects to clean (its discovery starts from container labels). Two changes: 1. `buildDockerComposeConfig` now emits a labeled `networks.default` carrying the same `dev.tokenbooks.wt.*` metadata as containers. Compose applies these on the real Docker network. 2. `listManagedDockerProjectsForRepo` scans `docker network ls` with the repo-root + managed filters in addition to the existing container scan, then merges by project name (no duplication when both containers and a network exist). `wt prune` already iterates `listManagedDockerProjectsForRepo` results and removes orphan projects, so the recovery path lights up automatically — no command-surface changes. Tests: - Unit: network labels rendered, orphan discovery, dedup, filter shape - Integration (WT_RUN_DOCKER_TESTS=1): real Compose run, force-remove the container, confirm `listManagedDockerProjectsForRepo` reports the survivor and `removeDockerServices` cleans it up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR improves wt prune’s ability to reclaim Docker subnet slots by ensuring Compose networks carry the same dev.tokenbooks.wt.* identity labels as containers, and by extending project discovery to include labeled networks (so projects remain discoverable even if their containers were removed).
Changes:
- Add
dev.tokenbooks.wt.*labels to the Compose default network generated bybuildDockerComposeConfig. - Extend
listManagedDockerProjectsForRepoto discover “network-only” orphan projects viadocker network ls+docker network inspect. - Add unit + Docker integration tests covering network orphan discovery and non-duplication behavior; update README documentation for the new recovery path.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/core/docker-services.ts |
Labels the default Compose network and adds network-based discovery for managed Docker projects. |
README.md |
Documents that wt prune now also recovers orphaned Docker networks that consume subnet slots. |
__tests__/docker-services.spec.ts |
Adds unit tests for network labeling and network-only orphan discovery (including dedupe + filter assertions). |
__tests__/docker-services.docker.spec.ts |
Adds an integration test that removes a container while leaving its network, verifying discovery + cleanup. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
Summary
dev.tokenbooks.wt.*labels we already put on containers, so Docker carries the wt project identity on the network itself.listManagedDockerProjectsForRepoto scandocker network ls --filter label=…repo-root=…in addition to containers, so projects whose containers were reaped but whose network survives are still discoverable.wt prunealready iterates this list, so the recovery path lights up automatically — no command-surface changes.Why
wt newstarted failing with:On the affected machine,
docker network lsshowed 24wt-*-…_defaultnetworks but only one had any containers — the other 23 were holding subnet slots from Docker's default address pool with no way forwt pruneto find them (its discovery starts from container labels, and Compose-applied labels don't carry the wt repo identity).After this fix,
wt prunefinds and removes the orphans. The leak window remains — Ctrl+C duringdocker compose up, Docker Desktop reset, etc. can still strand a network — but recovery becomes awt pruneaway instead of a manualdocker network prune.Test plan
buildDockerComposeConfigrenders the labeled default networklistManagedDockerProjectsForReporeports network-only orphansWT_RUN_DOCKER_TESTS=1) that exercises real Docker:ensureDockerServicesstarts redisdocker rm -fthe container to simulate a reap that leaves the network behindlistManagedDockerProjectsForReporeports the orphan withservices: [],containerNames: []removeDockerServicescleans the network uppnpm test,pnpm lint,pnpm build).🤖 Generated with Claude Code