From 65a055408b7cca4c042d723d44d99a1e65e61451 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Fri, 15 May 2026 22:18:01 -0400 Subject: [PATCH] ci(integration): reach services by bridge IP via docker socket, no host ports --- .forgejo/workflows/ci.yml | 52 ++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 556413d..09f329c 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -62,21 +62,22 @@ jobs: - run: npm run build integration: - # First-ever execution of the integration suite. Postgres uses the same - # pgvector image as docker-compose; Redis backs the celery smoke tests. - # The python-ci runner executes jobs on the host (not in a container), - # so services are NOT reachable by name — their ports are published and - # we connect via localhost. + # This act_runner (swarm-runner v0.6.1) puts service containers on the + # default bridge with NO service-name DNS, and publishing fixed host + # ports collides with the operator's running docker-compose dev stack on + # the same shared daemon. Workaround: publish NO host ports, and reach + # each service by its bridge IP — discovered at runtime via the mounted + # docker socket (the python-ci image ships /usr/bin/docker; build.yml + # relies on it). Default-bridge containers can talk by IP (only embedded + # DNS is missing), so IP addressing is reliable here. Everything runs in + # ONE step so resolved values don't depend on cross-step env passing. runs-on: python-ci env: DB_USER: fabledcurator DB_PASSWORD: ci_integration - DB_HOST: localhost DB_PORT: "5432" DB_NAME: fabledcurator_test SECRET_KEY: ci_integration_placeholder - CELERY_BROKER_URL: redis://localhost:6379/0 - CELERY_RESULT_BACKEND: redis://localhost:6379/0 services: postgres: image: pgvector/pgvector:pg16 @@ -84,8 +85,6 @@ jobs: POSTGRES_USER: fabledcurator POSTGRES_PASSWORD: ci_integration POSTGRES_DB: fabledcurator_test - ports: - - "5432:5432" options: >- --health-cmd "pg_isready -U fabledcurator" --health-interval 10s @@ -93,8 +92,6 @@ jobs: --health-retries 10 redis: image: redis:7-alpine - ports: - - "6379:6379" options: >- --health-cmd "redis-cli ping" --health-interval 10s @@ -103,11 +100,26 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install Python deps - run: pip install -r requirements.txt pytest pytest-asyncio - - - name: Migrate the test database - run: alembic upgrade head - - - name: Pytest (integration only) - run: pytest tests/ -v -m integration + - name: Integration suite (resolve service IPs, migrate, test) + run: | + set -eux + # Scope to THIS job's service containers (act_runner names them + # ...JOB-integration...); the operator's compose stack uses the + # same images but different names, so it won't match. + PG=$(docker ps --filter "name=JOB-integration" --filter "ancestor=pgvector/pgvector:pg16" -q | head -n1) + RD=$(docker ps --filter "name=JOB-integration" --filter "ancestor=redis:7-alpine" -q | head -n1) + test -n "$PG" && test -n "$RD" + PG_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$PG") + RD_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$RD") + test -n "$PG_IP" && test -n "$RD_IP" + export DB_HOST="$PG_IP" + export CELERY_BROKER_URL="redis://$RD_IP:6379/0" + export CELERY_RESULT_BACKEND="redis://$RD_IP:6379/0" + # Wait for Postgres to accept TCP (bash /dev/tcp; no extra tools). + for i in $(seq 1 60); do + (echo > "/dev/tcp/$PG_IP/5432") >/dev/null 2>&1 && break + sleep 2 + done + pip install -r requirements.txt pytest pytest-asyncio + alembic upgrade head + pytest tests/ -v -m integration