From f5039d46b62bd4e50a3a07344fcde6b846bb4ffb Mon Sep 17 00:00:00 2001 From: Bill Date: Tue, 30 Dec 2025 20:51:02 -0500 Subject: [PATCH] docs: add git worktree isolation section Document the critical requirement to set COMPOSE_PROJECT_NAME for worktree isolation: - Problem: Without COMPOSE_PROJECT_NAME, all worktrees share image names (e.g., test-price-db:latest) causing build conflicts - Solution: export COMPOSE_PROJECT_NAME="test-${TEST_INSTANCE_ID}" - Cleanup scoping: Only remove containers for current branch Also updated: - Common Mistakes table with new isolation pitfalls - Service Test Script Template with COMPOSE_PROJECT_NAME export --- SKILL.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/SKILL.md b/SKILL.md index e00cac2..8d33f96 100644 --- a/SKILL.md +++ b/SKILL.md @@ -192,6 +192,59 @@ export TEST_API_URL="http://localhost:${API_PORT}" export TEST_DATABASE_URL="postgresql://test:test@localhost:${DB_PORT}/testdb" ``` +### Git Worktree Isolation + +When using git worktrees for parallel feature development, additional isolation is required beyond container and network naming. + +**Problem**: Without `COMPOSE_PROJECT_NAME`, Docker Compose uses the directory name as the project name. Since all test directories are typically named `test`, all worktrees share the same image names (e.g., `test-price-db:latest`). When worktree A builds while worktree B is testing, B's containers can fail due to image conflicts. + +**Solution**: Set `COMPOSE_PROJECT_NAME` to include the instance ID: + +```bash +# scripts/test-service.sh +TEST_INSTANCE_ID=$(./scripts/get-test-instance-id.sh) +export TEST_INSTANCE_ID + +# CRITICAL: Isolate Docker images between worktrees +# Without this, all worktrees share image names like "test-price-db:latest" +export COMPOSE_PROJECT_NAME="test-${TEST_INSTANCE_ID}" + +cd "services/${SERVICE}/deploy/test" +docker compose up -d --build --wait +``` + +**Result**: Each worktree gets unique image names: +- `test-feature-auth-price-db:latest` (worktree on feature/auth) +- `test-feature-api-price-db:latest` (worktree on feature/api) +- `test-main-price-db:latest` (main branch) + +**What gets isolated with full implementation**: + +| Resource | Isolation Variable | Example | +|----------|-------------------|---------| +| Container names | `container_name: mydb-test-${TEST_INSTANCE_ID}` | `mydb-test-feature-auth` | +| Network names | `name: myproject-test-${TEST_INSTANCE_ID}` | `myproject-test-feature-auth` | +| Image names | `COMPOSE_PROJECT_NAME=test-${TEST_INSTANCE_ID}` | `test-feature-auth-mydb:latest` | + +### Cleanup Command Scoping + +**Problem**: A global `test-clean-all` command that removes all containers matching `name=test-` will interfere with tests running in other worktrees. + +**Solution**: Scope cleanup to the current branch's instance ID: + +```makefile +# BAD: Removes ALL test containers across all branches +test-clean-all: + @docker ps -a --filter "name=test-" --format "{{.Names}}" | xargs -r docker rm -f + +# GOOD: Only removes containers for current branch +test-clean-all: + @TEST_INSTANCE_ID=$$(./scripts/get-test-instance-id.sh); \ + echo "Cleaning up test containers for instance: $$TEST_INSTANCE_ID..."; \ + docker ps -a --filter "name=test-$$TEST_INSTANCE_ID" --format "{{.Names}}" | xargs -r docker rm -f 2>/dev/null || true; \ + docker network rm "myproject-test-network-$$TEST_INSTANCE_ID" 2>/dev/null || true +``` + ## Docker Compose Patterns ### Development Environment @@ -416,6 +469,8 @@ test-infra-down: | Verbose test output | Context exhaustion | Use rich progress display, details only on failure | | Single test stage | Slow feedback, hard to debug | Separate unit → service → integration | | No branch isolation | Concurrent branches conflict | Use `TEST_INSTANCE_ID` from git branch | +| No `COMPOSE_PROJECT_NAME` | Worktrees share images, builds conflict | Set `COMPOSE_PROJECT_NAME=test-${TEST_INSTANCE_ID}` | +| Global test cleanup | Kills tests in other worktrees | Scope cleanup to current `TEST_INSTANCE_ID` | | Building all services on every change | Slow CI | Use matrix strategy, only build changed services | ## Quick Reference @@ -440,6 +495,9 @@ SERVICE=$1 TEST_INSTANCE_ID=$(./scripts/get-test-instance-id.sh) export TEST_INSTANCE_ID +# CRITICAL: Isolate Docker images between worktrees +export COMPOSE_PROJECT_NAME="test-${TEST_INSTANCE_ID}" + # Start service-specific containers cd "services/${SERVICE}/deploy/test" docker compose up -d --build --wait