#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" # shellcheck source=scripts/local-debug-env.sh source "$ROOT_DIR/scripts/local-debug-env.sh" mkdir -p "$LOCAL_DEBUG_LOG_DIR" "$LOCAL_DEBUG_PID_DIR" "$PLATFORM_DATA_DIR" "$PLATFORM_LOG_DIR" "$RUN_WORKSPACE_ROOT" "$RUN_SPOOL_ROOT" mkdir -p "$GOCACHE" managed_pid_running() { local pid_file="$1" if [[ ! -f "$pid_file" ]]; then return 1 fi local pid pid="$(cat "$pid_file")" [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null } port_listener_pid() { local port="$1" lsof -tiTCP:"$port" -sTCP:LISTEN 2>/dev/null | head -n 1 || true } listener_owned_by_local_debug() { local pid="$1" local details details="$(lsof -nP -p "$pid" 2>/dev/null || true)" [[ "$details" == *"$ROOT_DIR"* || "$details" == *"$LOCAL_DEBUG_ROOT"* ]] } wait_for_pid_exit() { local pid="$1" for _ in $(seq 1 20); do if ! kill -0 "$pid" 2>/dev/null; then return 0 fi sleep 0.25 done return 1 } ensure_port_available() { local name="$1" local port="$2" local pid_file="$LOCAL_DEBUG_PID_DIR/$name.pid" local listener_pid listener_pid="$(port_listener_pid "$port")" if [[ -z "$listener_pid" ]]; then return 0 fi if managed_pid_running "$pid_file" && [[ "$listener_pid" == "$(cat "$pid_file")" ]]; then return 0 fi if listener_owned_by_local_debug "$listener_pid"; then printf 'stopping stale %s listener pid %s on port %s\n' "$name" "$listener_pid" "$port" kill "$listener_pid" 2>/dev/null || true if ! wait_for_pid_exit "$listener_pid"; then printf 'stale %s listener pid %s did not stop after SIGTERM; sending SIGKILL\n' "$name" "$listener_pid" kill -9 "$listener_pid" 2>/dev/null || true wait_for_pid_exit "$listener_pid" || true fi rm -f "$pid_file" return 0 fi printf '%s port %s is already used by pid %s; choose another LOCAL_DEBUG_*_PORT or stop the existing listener\n' "$name" "$port" "$listener_pid" >&2 return 1 } start_service() { local name="$1" local service_dir="$2" local pid_file="$LOCAL_DEBUG_PID_DIR/$name.pid" shift 2 if [[ -f "$pid_file" ]]; then local existing_pid existing_pid="$(cat "$pid_file")" if kill -0 "$existing_pid" 2>/dev/null; then printf '%s already running with pid %s\n' "$name" "$existing_pid" return 0 fi rm -f "$pid_file" fi printf 'starting %s\n' "$name" ( cd "$service_dir" exec nohup "$@" >"$LOCAL_DEBUG_LOG_DIR/$name.log" 2>&1 ) >/dev/null 2>&1 & printf '%s' "$!" >"$pid_file" printf '%s pid %s log %s\n' "$name" "$(cat "$pid_file")" "$LOCAL_DEBUG_LOG_DIR/$name.log" } wait_for_url() { local name="$1" local url="$2" local attempts="${3:-30}" printf 'waiting for %s at %s\n' "$name" "$url" for _ in $(seq 1 "$attempts"); do if curl -fsS "$url" >/dev/null 2>&1; then printf '%s is ready\n' "$name" return 0 fi sleep 1 done printf '%s did not become ready at %s\n' "$name" "$url" >&2 return 1 } printf 'local debug root: %s\n' "$LOCAL_DEBUG_ROOT" printf 'platform: %s\n' "$(local_debug_platform_url)" printf 'platform_web: %s\n' "$(local_debug_web_url)" printf 'run repo: %s\n' "$RUN_REPO_DIR" printf 'platform log: %s\n' "$LOCAL_DEBUG_LOG_DIR/platform.log" printf 'run log: %s\n' "$LOCAL_DEBUG_LOG_DIR/run.log" printf 'platform_web log: %s\n' "$LOCAL_DEBUG_LOG_DIR/platform_web.log" ensure_port_available platform "$LOCAL_DEBUG_PLATFORM_PORT" ensure_port_available platform_web "$LOCAL_DEBUG_WEB_PORT" start_service platform "$ROOT_DIR/platform" env \ GOCACHE="$GOCACHE" \ PLATFORM_ADDR="$PLATFORM_ADDR" \ PLATFORM_STORAGE_BACKEND="$PLATFORM_STORAGE_BACKEND" \ PLATFORM_DATA_DIR="$PLATFORM_DATA_DIR" \ PLATFORM_METADATA_PATH="$PLATFORM_METADATA_PATH" \ PLATFORM_LOG_BODY_BACKEND="$PLATFORM_LOG_BODY_BACKEND" \ PLATFORM_LOG_DIR="$PLATFORM_LOG_DIR" \ go run ./cmd/platform wait_for_url platform "$(local_debug_platform_url)/healthz" ensure_local_run_repo start_service run "$RUN_REPO_DIR" env \ GOCACHE="$GOCACHE" \ RUN_MODE="$RUN_MODE" \ RUN_PLATFORM_URL="$RUN_PLATFORM_URL" \ RUN_ENDPOINT_ID="$RUN_ENDPOINT_ID" \ RUN_DISPLAY_NAME="$RUN_DISPLAY_NAME" \ RUN_VERSION="$RUN_VERSION" \ RUN_REGISTRATION_TOKEN="$RUN_REGISTRATION_TOKEN" \ RUN_WORKSPACE_ROOT="$RUN_WORKSPACE_ROOT" \ RUN_SPOOL_ROOT="$RUN_SPOOL_ROOT" \ RUN_MAX_JOBS="$RUN_MAX_JOBS" \ RUN_HEARTBEAT_INTERVAL_MS="$RUN_HEARTBEAT_INTERVAL_MS" \ RUN_POLL_INTERVAL_MS="$RUN_POLL_INTERVAL_MS" \ RUN_RETRY_BACKOFF_MS="$RUN_RETRY_BACKOFF_MS" \ go run ./cmd/run start_service platform_web "$ROOT_DIR" env \ PLATFORM_API_PROXY="$PLATFORM_API_PROXY" \ VITE_PLATFORM_API_BASE_URL="$VITE_PLATFORM_API_BASE_URL" \ VITE_ENABLE_LOCAL_AUTH_FALLBACK="$VITE_ENABLE_LOCAL_AUTH_FALLBACK" \ npm --prefix platform_web run dev -- --port "$LOCAL_DEBUG_WEB_PORT" wait_for_url platform_web "$(local_debug_web_url)" cat <