diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index ccd8d77..9a6e4c1 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -32,14 +32,20 @@ jobs: # Postgres is started as a step rather than through `services:`. # - # The runner here does not put service containers on the job's network, so - # `services:` yields "getaddrinfo EAI_AGAIN postgres". Sharing the job - # container's own network namespace (`--network container:$HOSTNAME`) puts - # Postgres on 127.0.0.1 and works regardless of how the runner is - # configured — which matters because this runner is shared with other - # repositories and should not have to be reconfigured to suit this one. + # Two approaches were tried and rejected before this one: + # + # `services:` — this runner does not attach service + # containers to the job network, giving + # "getaddrinfo EAI_AGAIN postgres". + # `--network container:$HOSTNAME` — /etc/hostname inside the job reports + # the HOST's name, not the container id, + # so the namespace join finds no such + # container. + # + # What works without needing to know our own container id: publish the port + # on the host and reach it through the job container's default gateway. The + # port is derived from the run id so concurrent runs cannot collide. env: - DATABASE_URL: postgres://pig:pig@127.0.0.1:5432/pig PG_CONTAINER: pig-ci-pg-${{ github.run_id }} steps: @@ -51,14 +57,24 @@ jobs: - name: Start Postgres run: | + # A per-run port in the ephemeral range, so two runs never collide. + PG_PORT=$(( 45000 + (${{ github.run_id }} % 15000) )) + GATEWAY=$(ip route | awk '/^default/ {print $3; exit}') + if [ -z "$GATEWAY" ]; then echo "Could not determine the gateway"; exit 1; fi + echo "Postgres will be published on ${GATEWAY}:${PG_PORT}" + docker rm -f "$PG_CONTAINER" 2>/dev/null || true docker run -d --name "$PG_CONTAINER" \ - --network "container:$(cat /etc/hostname)" \ + -p "${PG_PORT}:5432" \ -e POSTGRES_USER=pig -e POSTGRES_PASSWORD=pig -e POSTGRES_DB=pig \ postgres:16-alpine + for i in $(seq 1 60); do if docker exec "$PG_CONTAINER" pg_isready -U pig -q; then - echo "Postgres ready after ${i}s"; exit 0 + echo "Postgres ready after ${i}s" + # Export for every later step. + echo "DATABASE_URL=postgres://pig:pig@${GATEWAY}:${PG_PORT}/pig" >> "$GITHUB_ENV" + exit 0 fi sleep 1 done