From 159d3f33486a4a403f3db4a894906a2ec9d69b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ullrich=20Sch=C3=A4fer?= Date: Wed, 22 Jul 2026 20:33:43 +0200 Subject: [PATCH] ci(forgejo): adapt e2e + image-smoke to isolated per-job DinD runners Runners migrated to 2 isolated runner+dind pairs (capacity 1 each): each job gets its own docker daemon (job-to-job isolation; host daemon untouched). - e2e: seed BRouter segment into the compose volume via a DinD container (no cross-daemon bind mount); services addressed at host.docker.internal; compose project pinned to 'trails'. - image-smoke: db:push reaches postgres at host.docker.internal; the --network-host journal container uses localhost; health-check via host.docker.internal. DOCKER_HOST is also injected globally via the runner's config (runner.envs). Co-Authored-By: Claude Opus 4.8 (1M context) --- .forgejo/workflows/ci.yml | 48 ++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index e35325f..4a6077d 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -196,9 +196,9 @@ jobs: needs: build runs-on: ubuntu-latest env: - DATABASE_URL: postgres://trails:trails@localhost:5432/trails - # The DinD daemon lives at this address on the runner network; the job - # container needs it explicitly (it has no /var/run/docker.sock). + # Services run on the DinD daemon; from the job container their published + # ports are reachable at host.docker.internal (not localhost). + DATABASE_URL: postgres://trails:trails@host.docker.internal:5432/trails DOCKER_HOST: tcp://host.docker.internal:2375 steps: - uses: actions/checkout@v7 @@ -209,36 +209,25 @@ jobs: cache: pnpm - run: pnpm install --frozen-lockfile - - name: Cache BRouter segment - id: segment-cache - uses: actions/cache@v6 - with: - path: /tmp/brouter-segments - key: brouter-segment-E10_N50-v1.7.9 - - - name: Download Berlin segment - if: steps.segment-cache.outputs.cache-hit != 'true' - run: | - mkdir -p /tmp/brouter-segments - wget -q "https://brouter.de/brouter/segments4/E10_N50.rd5" -O /tmp/brouter-segments/E10_N50.rd5 - - - name: Pre-seed BRouter segment volume + - name: Seed BRouter segment volume + # Download the segment directly into the compose volume via a DinD + # container — a job-side download + bind mount would not be visible to + # the DinD daemon (separate filesystem). Project name pinned to `trails` + # so the volume matches docker-compose.dev.yml's `brouter_segments`. run: | docker volume create trails_brouter_segments - docker run --rm \ - -v /tmp/brouter-segments:/src:ro \ - -v trails_brouter_segments:/dst \ - alpine sh -c "cp /src/*.rd5 /dst/ && chmod a+r /dst/*.rd5" + docker run --rm -v trails_brouter_segments:/dst alpine sh -c \ + "wget -q https://brouter.de/brouter/segments4/E10_N50.rd5 -O /dst/E10_N50.rd5 && chmod a+r /dst/*.rd5" - name: Start services - run: docker compose -f docker-compose.dev.yml up -d --wait --build + run: docker compose -p trails -f docker-compose.dev.yml up -d --wait --build postgres brouter env: - BROUTER_URL: http://localhost:17777 + BROUTER_URL: http://host.docker.internal:17777 - name: Wait for BRouter routing run: | for i in $(seq 1 60); do - curl -s 'http://localhost:17777/brouter?lonlats=13.4,52.5|13.5,52.5&profile=trekking&format=geojson' 2>/dev/null | grep -q "FeatureCollection" && echo "BRouter ready" && break + curl -s 'http://host.docker.internal:17777/brouter?lonlats=13.4,52.5|13.5,52.5&profile=trekking&format=geojson' 2>/dev/null | grep -q "FeatureCollection" && echo "BRouter ready" && break [ "$i" = "60" ] && echo "BRouter not ready after 120s" && exit 1 sleep 2 done @@ -280,7 +269,7 @@ jobs: - name: Run E2E tests run: pnpm test:e2e env: - BROUTER_URL: http://localhost:17777 + BROUTER_URL: http://host.docker.internal:17777 E2E: "true" INTEGRATION_SECRET: ${{ secrets.INTEGRATION_SECRET }} @@ -339,7 +328,8 @@ jobs: --health-timeout 5s --health-retries 20 env: - DATABASE_URL: postgres://trails:trails@localhost:5432/trails + # From the job container the postgres service is at host.docker.internal. + DATABASE_URL: postgres://trails:trails@host.docker.internal:5432/trails DOCKER_HOST: tcp://host.docker.internal:2375 steps: - uses: actions/checkout@v7 @@ -358,13 +348,15 @@ jobs: - name: Boot image and wait for healthy run: | + # Journal runs --network host on the DinD daemon, so it reaches the + # postgres service (published on DinD) at localhost:5432. docker run -d --name journal-smoke --network host \ -e NODE_ENV=production -e E2E=true \ - -e DATABASE_URL="$DATABASE_URL" \ + -e DATABASE_URL="postgres://trails:trails@localhost:5432/trails" \ journal-smoke code=000 for i in $(seq 1 30); do - code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 3 http://localhost:3000/api/health || echo 000) + code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 3 http://host.docker.internal:3000/api/health || echo 000) echo "attempt $i: /api/health -> $code" [ "$code" = "200" ] && break if [ "$(docker inspect -f '{{.State.Running}}' journal-smoke 2>/dev/null)" != "true" ]; then