#!/usr/bin/env bash # HireEx quickstart — pulls a prebuilt stack, writes compose.public.yml, boots Postgres + Redis + API + web. # Usage: # curl -fsSL https://raw.githubusercontent.com/chernistry/hireex/main/scripts/quickstart.sh | bash set -euo pipefail # ——— styling ——— if [[ -t 1 ]]; then BOLD=$'\033[1m'; DIM=$'\033[2m'; RESET=$'\033[0m' CREAM=$'\033[38;2;244;238;226m' INK=$'\033[38;2;26;22;19m' TERRA=$'\033[38;2;198;90;58m' OLIVE=$'\033[38;2;92;107;58m' MUSTARD=$'\033[38;2;214;165;69m' else BOLD=""; DIM=""; RESET=""; CREAM=""; INK=""; TERRA=""; OLIVE=""; MUSTARD="" fi step() { printf "%s→ %s%s\n" "$TERRA" "$1" "$RESET"; } ok() { printf "%s✓ %s%s\n" "$OLIVE" "$1" "$RESET"; } warn() { printf "%s! %s%s\n" "$MUSTARD" "$1" "$RESET"; } die() { printf "%sx %s%s\n" "$TERRA" "$1" "$RESET" >&2; exit 1; } # ——— banner ——— cat </dev/null || die "Docker not found. Install Docker Desktop or docker engine first." docker info >/dev/null 2>&1 || die "Docker daemon isn't running." if ! docker compose version >/dev/null 2>&1; then die "Docker Compose v2 not found. Upgrade Docker Desktop or install docker-compose-plugin." fi ok "docker ok" step "checking ports" for port in 3000 5432 6379 8000; do if lsof -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1; then warn "port $port is in use — stop whatever's holding it, then re-run." exit 1 fi done ok "ports 3000 / 5432 / 6379 / 8000 are free" # ——— workdir ——— WORKDIR="${HIREEX_HOME:-$PWD/hireex}" step "setting up $WORKDIR" mkdir -p "$WORKDIR" cd "$WORKDIR" # ——— compose file ——— COMPOSE="$WORKDIR/compose.public.yml" if [[ ! -f "$COMPOSE" ]]; then step "writing compose.public.yml" cat > "$COMPOSE" <<'YAML' # HireEx — public Compose bundle. Pulls prebuilt images, no source checkout. services: db: image: pgvector/pgvector:pg16 restart: unless-stopped environment: POSTGRES_USER: hireex POSTGRES_PASSWORD: hireex POSTGRES_DB: hireex volumes: [hireex-db:/var/lib/postgresql/data] healthcheck: test: ["CMD", "pg_isready", "-U", "hireex"] interval: 5s retries: 20 redis: image: redis:7-alpine restart: unless-stopped volumes: [hireex-redis:/data] healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s retries: 20 api: image: ghcr.io/chernistry/hireex-api:latest restart: unless-stopped depends_on: db: { condition: service_healthy } redis: { condition: service_healthy } environment: DATABASE_URL: postgresql+asyncpg://hireex:hireex@db:5432/hireex REDIS_URL: redis://redis:6379/0 HIREEX_HOME: /data volumes: [hireex-data:/data] ports: ["8000:8000"] web: image: ghcr.io/chernistry/hireex-web:latest restart: unless-stopped depends_on: api: { condition: service_started } environment: NEXT_PUBLIC_API_URL: http://localhost:8000 ports: ["3000:3000"] volumes: hireex-db: hireex-redis: hireex-data: YAML ok "compose.public.yml written" else ok "compose.public.yml already present — reusing" fi # ——— boot ——— step "pulling images (prebuilt — no compile)" docker compose -f "$COMPOSE" pull --quiet ok "images pulled" step "starting stack" docker compose -f "$COMPOSE" up -d ok "stack up" # ——— wait for api ——— step "waiting for api to be ready" for i in {1..60}; do if curl -fsSL http://localhost:8000/health >/dev/null 2>&1; then ok "api healthy" break fi sleep 2 done # ——— done ——— cat <