CI: reach Postgres through the gateway instead of a shared namespace
CI / verify (push) Failing after 5s
CI / verify (push) Failing after 5s
Second attempt failed differently: /etc/hostname inside the job reports the HOST's name rather than the container id, so `--network container:$HOSTNAME` found no such container. Rather than hunt for our own container id through /proc, publish the port on the host and connect through the job container's default gateway. That needs no container identity at all. The port is derived from the run id so two concurrent runs cannot collide, and DATABASE_URL is exported through GITHUB_ENV once Postgres is actually accepting connections. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+25
-9
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user