189 lines
4.6 KiB
Bash
Executable file
189 lines
4.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
cd "$SCRIPT_DIR"
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
BOLD='\033[1m'
|
|
RESET='\033[0m'
|
|
|
|
log() { echo -e "${CYAN}[nightcrawler]${RESET} $*"; }
|
|
ok() { echo -e "${GREEN}[nightcrawler]${RESET} $*"; }
|
|
warn() { echo -e "${YELLOW}[nightcrawler]${RESET} $*"; }
|
|
err() { echo -e "${RED}[nightcrawler]${RESET} $*" >&2; }
|
|
|
|
usage() {
|
|
echo -e "${BOLD}Nightcrawler — Self-contained orchestration${RESET}"
|
|
echo ""
|
|
echo "Usage: ./run [command]"
|
|
echo ""
|
|
echo "Commands:"
|
|
echo " start Full startup: infra -> build frontend -> launch server (default)"
|
|
echo " stop Stop server + docker compose down"
|
|
echo " status Health check all components"
|
|
echo " infra Start only Docker containers (postgres, redis, tor)"
|
|
echo " build Build frontend only"
|
|
echo " logs [svc] Tail docker compose logs (optional: service name)"
|
|
echo ""
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Infrastructure
|
|
# ===========================================================================
|
|
|
|
infra_up() {
|
|
log "Starting infrastructure (postgres:25460, redis:26399, tor:3128)..."
|
|
docker compose up -d
|
|
|
|
log "Waiting for PostgreSQL..."
|
|
local retries=0
|
|
while ! docker exec nightcrawler-postgres pg_isready -U postgres -q 2>/dev/null; do
|
|
retries=$((retries + 1))
|
|
if [ "$retries" -ge 30 ]; then
|
|
err "PostgreSQL failed to become ready after 30s"
|
|
exit 1
|
|
fi
|
|
sleep 1
|
|
done
|
|
ok "PostgreSQL ready"
|
|
|
|
log "Waiting for Redis..."
|
|
retries=0
|
|
while ! docker exec nightcrawler-redis redis-cli ping 2>/dev/null | grep -q PONG; do
|
|
retries=$((retries + 1))
|
|
if [ "$retries" -ge 30 ]; then
|
|
err "Redis failed to become ready after 30s"
|
|
exit 1
|
|
fi
|
|
sleep 1
|
|
done
|
|
ok "Redis ready"
|
|
|
|
ok "Infrastructure up"
|
|
}
|
|
|
|
infra_down() {
|
|
log "Stopping infrastructure..."
|
|
docker compose down
|
|
ok "Infrastructure stopped"
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Frontend Build
|
|
# ===========================================================================
|
|
|
|
build_frontend() {
|
|
local force="${1:-}"
|
|
|
|
if [ "$force" = "--rebuild" ] || [ ! -d "frontend-controlpanel/dist" ]; then
|
|
log "Building frontend..."
|
|
(cd frontend-controlpanel && bun run build)
|
|
ok "Frontend built"
|
|
else
|
|
ok "Frontend already built (use --rebuild to force)"
|
|
fi
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Server
|
|
# ===========================================================================
|
|
|
|
start_server() {
|
|
log "Starting Nightcrawler API on port 3400..."
|
|
exec bunx tsx src/index.ts ui --port 3400
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Status
|
|
# ===========================================================================
|
|
|
|
check_status() {
|
|
echo -e "${BOLD}Nightcrawler Status${RESET}"
|
|
echo ""
|
|
|
|
# PostgreSQL
|
|
if docker exec nightcrawler-postgres pg_isready -U postgres -q 2>/dev/null; then
|
|
ok "PostgreSQL :25460 healthy"
|
|
else
|
|
err "PostgreSQL :25460 DOWN"
|
|
fi
|
|
|
|
# Redis
|
|
if docker exec nightcrawler-redis redis-cli ping 2>/dev/null | grep -q PONG; then
|
|
ok "Redis :26399 healthy"
|
|
else
|
|
err "Redis :26399 DOWN"
|
|
fi
|
|
|
|
# Tor
|
|
if docker inspect nightcrawler-tor --format='{{.State.Running}}' 2>/dev/null | grep -q true; then
|
|
ok "Tor Proxy :3128 running"
|
|
else
|
|
warn "Tor Proxy :3128 not running"
|
|
fi
|
|
|
|
# API
|
|
if curl -sf http://localhost:3400/api/health >/dev/null 2>&1; then
|
|
ok "API Server :3400 healthy"
|
|
else
|
|
warn "API Server :3400 not running"
|
|
fi
|
|
|
|
# CAPTCHA Solver
|
|
if curl -sf http://localhost:3400/api/captcha-solver/status >/dev/null 2>&1; then
|
|
ok "CAPTCHA Solver healthy"
|
|
else
|
|
warn "CAPTCHA Solver not running"
|
|
fi
|
|
|
|
# Frontend
|
|
if [ -d "frontend-controlpanel/dist" ]; then
|
|
ok "Frontend built"
|
|
else
|
|
warn "Frontend not built"
|
|
fi
|
|
|
|
echo ""
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Main
|
|
# ===========================================================================
|
|
|
|
COMMAND="${1:-start}"
|
|
shift || true
|
|
|
|
case "$COMMAND" in
|
|
start)
|
|
infra_up
|
|
build_frontend "${1:-}"
|
|
start_server
|
|
;;
|
|
stop)
|
|
infra_down
|
|
;;
|
|
status)
|
|
check_status
|
|
;;
|
|
infra)
|
|
infra_up
|
|
;;
|
|
build)
|
|
build_frontend "--rebuild"
|
|
;;
|
|
logs)
|
|
docker compose logs -f "$@"
|
|
;;
|
|
-h|--help|help)
|
|
usage
|
|
;;
|
|
*)
|
|
err "Unknown command: $COMMAND"
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|