204 lines
6.9 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# ═══════════════════════════════════════════════════════════
# GooseFactory — First Boot Script
# Sets up the complete development environment from scratch.
# ═══════════════════════════════════════════════════════════
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
cd "$PROJECT_ROOT"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
print_header() { echo -e "\n${CYAN}═══════════════════════════════════════${NC}"; echo -e "${CYAN} $1${NC}"; echo -e "${CYAN}═══════════════════════════════════════${NC}\n"; }
print_step() { echo -e " ${BLUE}${NC} $1"; }
print_ok() { echo -e " ${GREEN}${NC} $1"; }
print_warn() { echo -e " ${YELLOW}⚠️${NC} $1"; }
print_fail() { echo -e " ${RED}${NC} $1"; }
# ─── Step 1: Check Prerequisites ───
print_header "Step 1: Checking Prerequisites"
MISSING=0
# Node.js
if command -v node &> /dev/null; then
NODE_VERSION=$(node --version)
print_ok "Node.js $NODE_VERSION"
NODE_MAJOR=$(echo "$NODE_VERSION" | sed 's/v//' | cut -d. -f1)
if [ "$NODE_MAJOR" -lt 20 ]; then
print_warn "Node.js 20+ recommended (found $NODE_VERSION)"
fi
else
print_fail "Node.js not found — install from https://nodejs.org"
MISSING=1
fi
# npm
if command -v npm &> /dev/null; then
print_ok "npm $(npm --version)"
else
print_fail "npm not found"
MISSING=1
fi
# Docker
if command -v docker &> /dev/null; then
print_ok "Docker $(docker --version | awk '{print $3}' | tr -d ',')"
else
print_warn "Docker not found — needed for PostgreSQL and Redis"
print_step "Install from https://www.docker.com/products/docker-desktop/"
print_step "Or install PostgreSQL/Redis natively"
fi
# Docker Compose
if command -v docker &> /dev/null && docker compose version &> /dev/null; then
print_ok "Docker Compose $(docker compose version --short 2>/dev/null || echo 'available')"
elif command -v docker-compose &> /dev/null; then
print_ok "Docker Compose (legacy) $(docker-compose --version | awk '{print $4}' | tr -d ',')"
else
print_warn "Docker Compose not found — needed for dev infrastructure"
fi
# Rust (optional, for desktop build)
if command -v rustc &> /dev/null; then
print_ok "Rust $(rustc --version | awk '{print $2}')"
else
print_warn "Rust not found — needed only for desktop app build"
print_step "Install from https://rustup.rs"
fi
if [ "$MISSING" -eq 1 ]; then
print_fail "Missing required prerequisites. Please install them and re-run."
exit 1
fi
# ─── Step 2: Environment Setup ───
print_header "Step 2: Environment Setup"
if [ ! -f .env ]; then
cp .env.example .env
print_ok "Created .env from .env.example"
print_warn "Edit .env to set your JWT_SECRET and other values"
else
print_ok ".env already exists"
fi
# Create feedback storage directories
mkdir -p ~/.config/goose/factory/feedback
mkdir -p ~/.config/goose/factory/memory
print_ok "Created feedback storage directories"
# ─── Step 3: Install Dependencies ───
print_header "Step 3: Installing Dependencies"
print_step "Running npm install (this may take a minute)..."
npm install --workspaces --include-workspace-root
print_ok "Dependencies installed"
# ─── Step 4: Build Shared Package ───
print_header "Step 4: Building Shared Package"
npm -w @goosefactory/shared run build
print_ok "@goosefactory/shared built"
# ─── Step 5: Start Docker Services ───
print_header "Step 5: Starting Infrastructure"
if command -v docker &> /dev/null; then
print_step "Starting PostgreSQL and Redis..."
docker compose -f infra/docker/docker-compose.yml up -d
# Wait for PostgreSQL to be ready
print_step "Waiting for PostgreSQL..."
RETRIES=30
until docker exec goosefactory-postgres pg_isready -U goosefactory -d goosefactory &>/dev/null || [ $RETRIES -eq 0 ]; do
RETRIES=$((RETRIES - 1))
sleep 1
done
if [ $RETRIES -gt 0 ]; then
print_ok "PostgreSQL ready"
else
print_warn "PostgreSQL may not be ready yet — check 'docker logs goosefactory-postgres'"
fi
# Wait for Redis to be ready
print_step "Waiting for Redis..."
RETRIES=10
until docker exec goosefactory-redis redis-cli ping &>/dev/null || [ $RETRIES -eq 0 ]; do
RETRIES=$((RETRIES - 1))
sleep 1
done
if [ $RETRIES -gt 0 ]; then
print_ok "Redis ready"
else
print_warn "Redis may not be ready — check 'docker logs goosefactory-redis'"
fi
else
print_warn "Docker not available — skipping infrastructure startup"
print_step "Make sure PostgreSQL and Redis are running manually"
fi
# ─── Step 6: Run Database Migrations ───
print_header "Step 6: Database Setup"
if command -v docker &> /dev/null && docker exec goosefactory-postgres pg_isready -U goosefactory -d goosefactory &>/dev/null; then
print_step "Database schema initialized via init.sql (Docker entrypoint)"
print_ok "Database ready"
# Seed data from factory if available
if [ -f "$SCRIPT_DIR/seed-from-factory.ts" ]; then
print_step "Seeding data from MCP factory state..."
npx tsx "$SCRIPT_DIR/seed-from-factory.ts" || print_warn "Seed script had issues (non-fatal)"
print_ok "Seed data imported"
fi
else
print_warn "Database not accessible — skipping migrations and seeding"
fi
# ─── Step 7: Verification ───
print_header "Step 7: Verification"
# Typecheck shared
print_step "Typechecking shared package..."
npm -w @goosefactory/shared run typecheck 2>/dev/null && print_ok "Shared types valid" || print_warn "Typecheck had warnings"
# ─── Summary ───
print_header "🏭 GooseFactory is Ready!"
echo -e " ${GREEN}Start development:${NC}"
echo -e " ${BLUE}npm run dev:api${NC} — Start API server (port 4000)"
echo -e " ${BLUE}npm run dev:mcp${NC} — Start MCP server"
echo -e " ${BLUE}npm run dev:learning${NC} — Start learning pipeline"
echo -e " ${BLUE}npm run dev${NC} — Start all services"
echo -e ""
echo -e " ${GREEN}Infrastructure:${NC}"
echo -e " ${BLUE}PostgreSQL${NC} → localhost:5432 (user: goosefactory)"
echo -e " ${BLUE}Redis${NC} → localhost:6379"
echo -e " ${BLUE}API${NC} → http://localhost:4000"
echo -e " ${BLUE}API Health${NC} → http://localhost:4000/health"
echo -e ""
echo -e " ${GREEN}Useful commands:${NC}"
echo -e " ${BLUE}npm run build${NC} — Build all packages"
echo -e " ${BLUE}npm run typecheck${NC} — Check types across monorepo"
echo -e " ${BLUE}npm run dev:infra:stop${NC} — Stop Docker services"
echo -e ""