@@ -293,13 +293,16 @@ jobs:
293293 echo "local_port=$LOCAL_PORT" >> $GITHUB_OUTPUT
294294
295295 # Start SSM session in background with timeout
296- timeout --foreground $TUNNEL_TIMEOUT \
296+ # Use nohup and disown to prevent process from being killed when step shell exits
297+ nohup timeout --foreground $TUNNEL_TIMEOUT \
297298 aws ssm start-session \
298299 --target ${{ steps.db-config.outputs.ssm_instance_id }} \
299300 --document-name AWS-StartPortForwardingSessionToRemoteHost \
300- --parameters '{"host":["${{ steps.db-config.outputs.db_host }}"],"portNumber":["${{ steps.db-config.outputs.db_port }}"],"localPortNumber":["'$LOCAL_PORT'"]}' &
301-
301+ --parameters '{"host":["${{ steps.db-config.outputs.db_host }}"],"portNumber":["${{ steps.db-config.outputs.db_port }}"],"localPortNumber":["'$LOCAL_PORT'"]}' \
302+ > /tmp/ssm_tunnel.log 2>&1 &
303+
302304 SSM_PID=$!
305+ disown $SSM_PID
303306 echo "pid=$SSM_PID" >> $GITHUB_OUTPUT
304307
305308 # Give SSM a moment to start
@@ -355,6 +358,27 @@ jobs:
355358 sleep $SLEEP_INTERVAL
356359 done
357360
361+ # Start keepalive to prevent idle timeout
362+ # Send pg_isready every 10 seconds (more frequent) to keep tunnel alive
363+ # Export variables so they're available in the subshell
364+ export KEEPALIVE_SSM_PID=$SSM_PID
365+ export KEEPALIVE_PORT=$LOCAL_PORT
366+ nohup bash -c '
367+ echo "Keepalive started for SSM PID: $KEEPALIVE_SSM_PID, Port: $KEEPALIVE_PORT"
368+ while true; do
369+ if ! ps -p $KEEPALIVE_SSM_PID >/dev/null 2>&1; then
370+ echo "SSM process $KEEPALIVE_SSM_PID is no longer running, exiting keepalive"
371+ exit 0
372+ fi
373+ pg_isready -h localhost -p $KEEPALIVE_PORT -t 1 >/dev/null 2>&1 || echo "pg_isready failed"
374+ sleep 10
375+ done
376+ ' > /tmp/keepalive.log 2>&1 &
377+ KEEPALIVE_PID=$!
378+ disown $KEEPALIVE_PID
379+ echo "keepalive_pid=$KEEPALIVE_PID" >> $GITHUB_OUTPUT
380+ echo "✅ Started keepalive process (PID: $KEEPALIVE_PID) monitoring SSM PID: $SSM_PID"
381+
358382 - name : Generate review configuration
359383 if : steps.check-trigger.outputs.triggered == 'true' && steps.pr-details.outputs.skip_non_main != 'true' && steps.strategy.outputs.skip_review == 'false'
360384 id : review-config
@@ -399,7 +423,26 @@ jobs:
399423
400424 # Pass password to next step via GITHUB_ENV
401425 echo "DB_PASSWORD=$DB_CREDS" >> $GITHUB_ENV
402-
426+
427+ # Verify tunnel is still running
428+ echo "Checking tunnel status..."
429+ if ps -p ${{ steps.tunnel.outputs.pid }} >/dev/null 2>&1; then
430+ echo "✅ SSM tunnel process is running (PID: ${{ steps.tunnel.outputs.pid }})"
431+ else
432+ echo "❌ SSM tunnel process is NOT running (PID: ${{ steps.tunnel.outputs.pid }})"
433+ echo "Tunnel log contents:"
434+ cat /tmp/ssm_tunnel.log 2>/dev/null || echo "No tunnel log found"
435+ exit 1
436+ fi
437+
438+ # Check if port is listening
439+ if nc -z localhost ${{ steps.tunnel.outputs.local_port }} 2>/dev/null; then
440+ echo "✅ Port ${{ steps.tunnel.outputs.local_port }} is listening"
441+ else
442+ echo "❌ Port ${{ steps.tunnel.outputs.local_port }} is NOT listening"
443+ exit 1
444+ fi
445+
403446 # Quick database connectivity check
404447 echo "Testing database connection..."
405448 echo "Connection details: localhost:${{ steps.tunnel.outputs.local_port }} user=${{ steps.db-config.outputs.db_user }} db=${{ steps.db-config.outputs.db_name }}"
0 commit comments