#!/usr/bin/env bash set -euo pipefail readonly RED='\033[0;31m' readonly GREEN='\033[0;32m' readonly YELLOW='\033[1;33m' readonly BLUE='\033[0;34m' readonly NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $*"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } log_error() { echo -e "${RED}[ERROR]${NC} $*"; } log_step() { echo -e "${BLUE}[STEP]${NC} $*"; } SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" WSL_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" AUTOMATION_DIR="$(cd "$WSL_DIR/.." && pwd)" PROJECT_ROOT="$(cd "$AUTOMATION_DIR/.." && pwd)" RUNNER_ENV_FILE="$AUTOMATION_DIR/wsl.local.env" DOCKER_ENV_FILE="$WSL_DIR/.env" COMPOSE_FILE="$WSL_DIR/docker-compose.yml" RUNTIME_DIR="$AUTOMATION_DIR/wsl_runtime" LOGS_DIR="$RUNTIME_DIR/logs" PID_DIR="$RUNTIME_DIR/pids" START_QUEUE_RUNNER="${START_QUEUE_RUNNER:-1}" mkdir -p "$LOGS_DIR" "$PID_DIR" if [[ -f "$RUNNER_ENV_FILE" ]]; then # shellcheck disable=SC1090 source "$RUNNER_ENV_FILE" fi if [[ -f "$DOCKER_ENV_FILE" ]]; then # shellcheck disable=SC1090 set -a source "$DOCKER_ENV_FILE" set +a fi compose_cmd() { docker compose --env-file "$DOCKER_ENV_FILE" -f "$COMPOSE_FILE" "$@" } check_prerequisites() { log_step "Checking prerequisites" command -v docker >/dev/null || { log_error "Docker is not installed"; exit 1; } docker compose version >/dev/null || { log_error "Docker Compose plugin is not available"; exit 1; } docker info >/dev/null || { log_error "Docker daemon is not running"; exit 1; } [[ -f "$DOCKER_ENV_FILE" ]] || { log_error "Missing docker env: $DOCKER_ENV_FILE"; exit 1; } [[ -f "$COMPOSE_FILE" ]] || { log_error "Missing compose file: $COMPOSE_FILE"; exit 1; } } wait_for_postgres() { log_info "Waiting for PostgreSQL" for _ in $(seq 1 60); do if compose_cmd exec -T postgres pg_isready -U "${POSTGRES_USER:-postgres}" -d "${POSTGRES_BOOTSTRAP_DB:-postgres}" >/dev/null 2>&1; then return 0 fi sleep 2 done log_error "PostgreSQL did not become ready in time" exit 1 } wait_for_service_http() { local service="$1" local url="$2" log_info "Waiting for $service" for _ in $(seq 1 60); do if curl -fsS "$url" >/dev/null 2>&1; then return 0 fi sleep 2 done log_warn "$service is not healthy yet: $url" return 1 } ensure_database() { local db_name="$1" if compose_cmd exec -T postgres psql -U "${POSTGRES_USER:-postgres}" -d "${POSTGRES_BOOTSTRAP_DB:-postgres}" -tAc "SELECT 1 FROM pg_database WHERE datname='${db_name}'" | grep -q 1; then return 0 fi compose_cmd exec -T postgres psql -U "${POSTGRES_USER:-postgres}" -d "${POSTGRES_BOOTSTRAP_DB:-postgres}" -c "CREATE DATABASE \"${db_name}\"" } ensure_gitea_admin() { local user="${GITEA_ADMIN_USER:-giteaadmin}" local password="${GITEA_ADMIN_PASSWORD:-changeme}" local email="${GITEA_ADMIN_EMAIL:-admin@localhost}" if compose_cmd exec -T gitea sh -c "HOME=/tmp /usr/local/bin/gitea admin user list 2>/dev/null | awk 'NR > 1 && \$2 == \"${user}\" { found=1 } END { exit found ? 0 : 1 }'"; then return 0 fi compose_cmd exec -T gitea sh -c "HOME=/tmp /usr/local/bin/gitea admin user create --admin --username '${user}' --password '${password}' --email '${email}' --must-change-password=false" >/dev/null 2>&1 || log_warn "Could not auto-create Gitea admin user; complete first-run in UI if needed" } start_docker_stack() { log_step "Starting Docker services" compose_cmd up -d postgres redis wait_for_postgres ensure_database "${GITEA_DB_NAME:-gitea}" ensure_database "${N8N_DB_NAME:-n8n}" compose_cmd up -d gitea n8n wait_for_service_http "Gitea" "http://localhost:${GITEA_HTTP_PORT:-3000}/api/healthz" || true wait_for_service_http "n8n" "http://localhost:${N8N_PORT:-5678}/healthz" || true ensure_gitea_admin } start_queue_runner() { if [[ "$START_QUEUE_RUNNER" != "1" ]]; then log_info "Queue runner startup skipped by START_QUEUE_RUNNER=$START_QUEUE_RUNNER" return fi if command -v systemctl >/dev/null 2>&1 && systemctl is-active abletonmcp-queue-runner.service >/dev/null 2>&1; then log_info "Queue runner already managed by systemd" return fi local pid_file="$PID_DIR/queue-runner.pid" if [[ -f "$pid_file" ]] && kill -0 "$(cat "$pid_file")" 2>/dev/null; then log_info "Queue runner already running" return fi log_step "Starting autonomous queue runner" nohup bash "$WSL_DIR/run_task_queue.sh" > "$LOGS_DIR/queue-runner.log" 2>&1 & echo $! > "$pid_file" log_info "Queue runner PID: $(cat "$pid_file")" } main() { check_prerequisites start_docker_stack start_queue_runner echo log_info "Stack started" echo " Gitea: http://localhost:${GITEA_HTTP_PORT:-3000}" echo " n8n: http://localhost:${N8N_PORT:-5678}" } main "$@"