fix(deploy): dynamically find a free PostgREST host port
Deploy to route.crispygoat.com / deploy (push) Failing after 13s
Build / build (push) Has been cancelled

Previous attempts hardcoded 3011, but something on tyler's host is
holding 3011 too. Instead of guessing ports, make the deploy probe
for the first free port starting from 3011 and thread that choice
through the rest of the workflow.

How it works:
1. Start Docker stack frees 3001 + the previous deploy's chosen port
   (read from .postgrest-port) so the lowest free port can be picked
   back up
2. Loops from 3011 upward, checking ss -tln until it finds a free
   port in the 3011-30200 range
3. Writes the chosen port to .postgrest-port in the workspace
4. Sets NEXT_PUBLIC_API_URL based on that port
5. Writes POSTGREST_HOST_PORT and NEXT_PUBLIC_API_URL to the .env
   that docker compose reads
6. Build and Deploy steps read .postgrest-port to set their
   NEXT_PUBLIC_API_URL dynamically — no more hardcoded 3011
This commit is contained in:
2026-06-06 00:12:23 +00:00
parent 9759dd042e
commit ffed10cd66
2 changed files with 40 additions and 13 deletions
+39 -12
View File
@@ -28,14 +28,36 @@ jobs:
run: |
APP_DIR=/home/tyler/route-commerce
mkdir -p $APP_DIR
# Free port 3001 if anything is still on it (stale container, leftover dev process)
if ss -tln 2>/dev/null | grep -q ':3001 '; then
echo "Port 3001 in use, attempting to free it..."
fuser -k 3001/tcp 2>/dev/null || true
docker ps -aq --filter "publish=3001" 2>/dev/null | xargs -r docker rm -f 2>/dev/null || true
docker compose -f $APP_DIR/docker-compose.yml down --remove-orphans 2>/dev/null || true
sleep 3
fi
# Free the dev-stack port (3001) and the port the previous deploy used
# (so a new deploy can pick it back up if it's the lowest free port)
PREV_PORT=$(cat .postgrest-port 2>/dev/null || echo "")
for port in 3001 $PREV_PORT; do
if [ -n "$port" ] && ss -tln 2>/dev/null | grep -q ":$port "; then
echo "Port $port in use, freeing..."
fuser -k -9 $port/tcp 2>/dev/null || true
docker ps -aq --filter "publish=$port" 2>/dev/null | xargs -r docker rm -f 2>/dev/null || true
fi
done
docker compose -f $APP_DIR/docker-compose.yml down --remove-orphans 2>/dev/null || true
sleep 3
# Find the first free host port starting from 3011. Persist the choice
# so the Build and Deploy steps below can use the same URL.
POSTGREST_HOST_PORT=3011
while ss -tln 2>/dev/null | grep -q ":$POSTGREST_HOST_PORT "; do
echo "Port $POSTGREST_HOST_PORT in use, trying next..."
POSTGREST_HOST_PORT=$((POSTGREST_HOST_PORT + 1))
if [ $POSTGREST_HOST_PORT -gt 30200 ]; then
echo "ERROR: no free port in 3011-30200 range"
exit 1
fi
done
echo "Using PostgREST host port: $POSTGREST_HOST_PORT"
echo "$POSTGREST_HOST_PORT" > .postgrest-port
export NEXT_PUBLIC_API_URL="http://localhost:$POSTGREST_HOST_PORT"
export POSTGREST_HOST_PORT
# Seed config files into APP_DIR if missing (they live in the repo, not in APP_DIR)
[ -f $APP_DIR/.env.example ] || cp .env.example $APP_DIR/.env.example
[ -f $APP_DIR/docker-compose.yml ] || cp docker-compose.yml $APP_DIR/docker-compose.yml
@@ -49,7 +71,8 @@ jobs:
echo "MINIO_ROOT_USER=${MINIO_ROOT_USER}"
echo "MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}"
echo "POSTGREST_JWT_SECRET=${POSTGREST_JWT_SECRET}"
echo "NEXT_PUBLIC_API_URL=http://localhost:3011"
echo "POSTGREST_HOST_PORT=$POSTGREST_HOST_PORT"
echo "NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL"
} >> .env
# Bring the stack up fresh — --force-recreate ensures no stale
# network/container references from prior failed attempts
@@ -86,7 +109,6 @@ jobs:
- name: Build
env:
NODE_ENV: production
NEXT_PUBLIC_API_URL: http://localhost:3011
DATABASE_URL: ${{ secrets.DATABASE_URL }}
BETTER_AUTH_SECRET: ${{ secrets.BETTER_AUTH_SECRET }}
BETTER_AUTH_URL: ${{ secrets.BETTER_AUTH_URL }}
@@ -107,11 +129,13 @@ jobs:
MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
MINIMAX_BASE_URL: ${{ secrets.MINIMAX_BASE_URL }}
FROM_EMAIL: ${{ secrets.FROM_EMAIL }}
run: npm run build
run: |
POSTGREST_HOST_PORT=$(cat .postgrest-port)
export NEXT_PUBLIC_API_URL="http://localhost:$POSTGREST_HOST_PORT"
npm run build
- name: Deploy
env:
NEXT_PUBLIC_API_URL: http://localhost:3011
DATABASE_URL: ${{ secrets.DATABASE_URL }}
POSTGRES_USER: ${{ secrets.POSTGRES_USER }}
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
@@ -145,6 +169,9 @@ jobs:
run: |
APP_DIR=/home/tyler/route-commerce
mkdir -p $APP_DIR
# Use the port chosen by Start Docker stack (persisted to .postgrest-port)
POSTGREST_HOST_PORT=$(cat .postgrest-port)
export NEXT_PUBLIC_API_URL="http://localhost:$POSTGREST_HOST_PORT"
# Write env file from secrets (preserves existing .env for docker compose)
{
+1 -1
View File
@@ -36,7 +36,7 @@ services:
PGRST_OPENAPI_MODE: disabled
PGRST_DB_EXTRA_SEARCH_PATH: public,extensions
ports:
- "127.0.0.1:3011:3001"
- "127.0.0.1:${POSTGREST_HOST_PORT:-3011}:3001"
minio:
image: minio/minio:latest