-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdev.sh
More file actions
executable file
·175 lines (150 loc) · 6.27 KB
/
dev.sh
File metadata and controls
executable file
·175 lines (150 loc) · 6.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/usr/bin/env bash
set -euo pipefail
# ── Ouro local dev launcher ──────────────────────────────────────────
# Usage: ./dev.sh [--fresh] [--down] [compose args...]
# --fresh Drop DB volume and re-init from 01-init.sql + 02-seed.sql
# --down Stop and remove containers (add -v to also remove volumes)
# --detach Run in background (passed through to docker compose)
# agent Start only agent + postgres (passed through to docker compose)
GCP_PROJECT="${GCP_PROJECT:-ouro-hpc-2026}"
GCP_ZONE="${GCP_ZONE:-us-central1-a}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SCRIPT_DIR"
# ── Colors ────────────────────────────────────────────────────────────
red() { printf '\033[0;31m%s\033[0m\n' "$*"; }
yellow() { printf '\033[0;33m%s\033[0m\n' "$*"; }
green() { printf '\033[0;32m%s\033[0m\n' "$*"; }
bold() { printf '\033[1m%s\033[0m\n' "$*"; }
# ── Parse args ────────────────────────────────────────────────────────
FRESH=false
DOWN=false
COMPOSE_ARGS=()
for arg in "$@"; do
if [ "$arg" = "--fresh" ]; then
FRESH=true
elif [ "$arg" = "--down" ]; then
DOWN=true
else
COMPOSE_ARGS+=("$arg")
fi
done
if [ "$DOWN" = true ]; then
bold "Stopping Ouro containers..."
docker compose down "${COMPOSE_ARGS[@]}"
green "Done"
exit 0
fi
# ── 1. Prerequisites ─────────────────────────────────────────────────
bold "Checking prerequisites..."
if ! command -v docker &>/dev/null; then
red "Docker is not installed. Install Docker Desktop: https://www.docker.com/products/docker-desktop/"
exit 1
fi
if ! docker info &>/dev/null; then
red "Docker daemon is not running. Start Docker Desktop and try again."
exit 1
fi
if ! command -v doppler &>/dev/null; then
red "Doppler CLI is not installed."
echo " Install: https://docs.doppler.com/docs/install-cli"
exit 1
fi
if ! doppler me --json &>/dev/null; then
red "Doppler is not authenticated."
echo " Run: doppler login && doppler setup"
exit 1
fi
green "Prerequisites OK"
# ── 2. Slurm IP sync (best-effort) ───────────────────────────────────
if command -v gcloud &>/dev/null; then
SLURM_IP=$(gcloud compute instances describe ouro-slurm \
--project="$GCP_PROJECT" --zone="$GCP_ZONE" \
--format='get(networkInterfaces[0].accessConfigs[0].natIP)' 2>/dev/null || true)
if [ -n "$SLURM_IP" ]; then
export SLURMREST_URL="http://${SLURM_IP}:6820"
green "Slurm IP synced: $SLURM_IP"
# Persist to .env if it exists
if [ -f .env ]; then
if [[ "$(uname)" == "Darwin" ]]; then
sed -i '' "s|^SLURMREST_URL=.*|SLURMREST_URL=$SLURMREST_URL|" .env
else
sed -i "s|^SLURMREST_URL=.*|SLURMREST_URL=$SLURMREST_URL|" .env
fi
fi
else
yellow "Warning: ouro-slurm instance appears stopped. Slurm won't be available."
fi
else
if [ -f .env ] && grep -q '^SLURMREST_URL=.' .env; then
yellow "No gcloud CLI — using SLURMREST_URL from .env"
else
yellow "No gcloud CLI and no SLURMREST_URL in .env. Slurm won't be available."
fi
fi
# ── 3. Port conflict detection ────────────────────────────────────────
find_free_port() {
local port=$1 max=$2
while [ "$port" -le "$max" ]; do
if ! lsof -i :"$port" -sTCP:LISTEN >/dev/null 2>&1; then
echo "$port"
return 0
fi
port=$((port + 1))
done
return 1
}
# Check if a port has a non-Docker listener
port_has_conflict() {
local port=$1
# Get PIDs listening on the port
local pids
pids=$(lsof -i :"$port" -sTCP:LISTEN -F p 2>/dev/null | grep '^p' | sed 's/^p//' || true)
[ -z "$pids" ] && return 1 # Nothing listening — no conflict
# Check if all listeners are Docker
for pid in $pids; do
local cmd
cmd=$(lsof -i :"$port" -sTCP:LISTEN -F pc 2>/dev/null | grep -A1 "^p${pid}$" | grep '^c' | sed 's/^c//' || true)
if [[ "$cmd" != "com.docke"* ]]; then
return 0 # Non-Docker process found — conflict
fi
done
return 1 # All Docker — no conflict
}
# Check if Ouro compose containers are already running
OURO_RUNNING=$(docker compose ps --format '{{.Name}}' 2>/dev/null || true)
if [ -n "$OURO_RUNNING" ]; then
yellow "Replacing existing Ouro containers..."
fi
check_and_resolve_port() {
local name=$1 default=$2 range_start=$3 range_end=$4 env_var=$5
if port_has_conflict "$default"; then
local free
if free=$(find_free_port "$range_start" "$range_end"); then
yellow "Port $default in use — $name will use port $free"
export "$env_var=$free"
else
red "Ports ${default}-${range_end} all in use. Free a port and retry."
exit 1
fi
fi
}
check_and_resolve_port "Dashboard" 3000 3001 3010 DASHBOARD_PORT
check_and_resolve_port "Agent API" 8000 8001 8010 AGENT_PORT
check_and_resolve_port "Postgres" 5432 5433 5442 DB_EXPOSE_PORT
# ── 4. Handle --fresh ────────────────────────────────────────────────
if [ "$FRESH" = true ]; then
yellow "Dropping DB volume for fresh init..."
docker compose down -v
fi
# ── 5. Build MCP server ────────────────────────────────────────────
bold "Building MCP server..."
(cd mcp && npm install --silent && npm run build --silent)
green "MCP server ready → mcp/dist/index.js"
# ── 6. Launch ─────────────────────────────────────────────────────────
echo ""
bold "Starting Ouro..."
echo " Dashboard: http://localhost:${DASHBOARD_PORT:-3000}"
echo " Agent API: http://localhost:${AGENT_PORT:-8000}"
echo " Postgres: localhost:${DB_EXPOSE_PORT:-5432}"
echo ""
exec doppler run -- docker compose up --build "${COMPOSE_ARGS[@]}"