Skip to content

Quickstart / Validation Runbook: OS-Agnostic Test Infrastructure

Feature: 005-os-agnostic-test-infra

This runbook proves the success criteria: container-backed backend tests pass with zero manual setup — no proxy, no DOCKER_HOST override — on any machine with a current container engine.

Prerequisites

  • A running container engine (Docker 29.x on the dev workstation; GitHub-hosted runner Docker in CI).
  • JDK 21 toolchain (provided via mise).

1. Start from a clean shell (no workaround active)

pkill -f docker-api-proxy 2>/dev/null || true
rm -f /tmp/docker-proxy.sock
unset DOCKER_HOST            # ensure no socket override is inherited
docker version --format 'Server {{.Server.Version}} (MinAPIVersion {{.Server.MinAPIVersion}})'

Expected: a Docker 29.x server with MinAPIVersion ≥ 1.40 — i.e. exactly the environment that broke Testcontainers 1.21.3 and required the proxy.

2. Run the full backend build

./gradlew build        # lint + compile + all unit & integration tests

Expected: BUILD SUCCESSFUL, with the container-backed tests passing: - adapters/persistence-postgresTaskConcurrencyTest - apps/api-serviceSubmitDocumentE2ETest, MultiStageFlowE2ETest, ClaimDecideE2ETest, WorkListAndStatusE2ETest, PerfSmokeTest

3. Confirm a real container actually started (not skipped)

While the suite runs (or from the test logs), confirm a Postgres testcontainer was created:

docker ps --filter "ancestor=postgres:16-alpine"        # during the run
# or, after the run, check Gradle test output mentions Testcontainers pulling/starting postgres

Expected: a transient postgres:16-alpine container appears and is torn down — proving the test talked to the host Docker daemon directly via Testcontainers' native negotiation.

4. Regression guard — workaround is gone

test ! -f scripts/docker-api-proxy.py && echo "OK: proxy script deleted"
! grep -rn "docker-api-proxy\|docker-proxy.sock\|DOCKER_HOST" \
    build-logic .github/workflows .specify/memory \
  && echo "OK: no proxy/socket/host wiring remains"

Expected: both OK: lines print. (SC-003)

5. Coverage parity

Compare the test count before and after the change:

find . -path '*/build/test-results/test/*.xml' | xargs grep -h "<testsuite " | \
  sed -E 's/.*tests="([0-9]+)".*/\1/' | paste -sd+ | bc

Expected: the total equals the pre-change total — no tests lost or silently skipped (SC-005).

6. Full CI parity

mise run ci            # reproduces the exact CI sequence locally

Then push and confirm the GitHub Actions CI workflow is green. The CI run must succeed without the old "Start Docker API proxy" step and without any Docker-in-Docker / container: job — the ubuntu-latest runner's host daemon is used directly. (US2, SC-004)

Rollback

If the upgrade regresses, revert the branch's commits; the prior proxy-based path (Testcontainers 1.21.3 + scripts/docker-api-proxy.py + testing.gradle.kts DOCKER_HOST wiring + ci.yml proxy step + Principle VI proxy mandate) is restored as a unit.