#!/usr/bin/env bash # setup.sh — Prepare the local development environment. # Safe to run multiple times: every step is a no-op if already complete. # # What it does: # 1. Checks prerequisites (docker, pnpm); installs just if missing # 2. Adds 127.0.0.1 keycloak to /etc/hosts (needed for GoTrue ↔ Keycloak) # 3. Creates .env with dev defaults if it doesn't exist # 4. Fixes supabase/migrations permissions if root-owned (common Docker artifact) # 5. Installs pnpm dependencies # 6. Starts the Docker stack # 7. Waits for postgres, kong, and keycloak to be healthy # 8. Applies SQL migrations (tracked — won't re-apply) # 9. Seeds the database (no-op if already seeded) # 10. Compiles Paraglide i18n files set -euo pipefail # ── Colours ─────────────────────────────────────────────────────────────────── RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' BOLD='\033[1m' NC='\033[0m' step() { echo; echo -e "${BOLD}${BLUE}==> $*${NC}"; } ok() { echo -e " ${GREEN}✓${NC} $*"; } warn() { echo -e " ${YELLOW}!${NC} $*"; } die() { echo -e "\n${RED}ERROR:${NC} $*" >&2; exit 1; } # ── Resolve project root ────────────────────────────────────────────────────── ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$ROOT" DC="docker compose --env-file .env -f infra/docker-compose.dev.yml" DB_CONTAINER="colectivo-dev-db-1" # ── 1. Prerequisites ────────────────────────────────────────────────────────── step "Checking prerequisites" command -v docker >/dev/null 2>&1 \ || die "docker not found. Install from https://docs.docker.com/get-docker/" docker compose version >/dev/null 2>&1 \ || die "docker compose v2 not found. Update Docker or install the compose plugin." ok "docker $(docker --version | grep -oP '[\d.]+' | head -1)" command -v pnpm >/dev/null 2>&1 \ || die "pnpm not found. Install: curl -fsSL https://get.pnpm.io/install.sh | sh" ok "pnpm $(pnpm --version)" command -v python3 >/dev/null 2>&1 \ || die "python3 not found — required to generate JWT tokens." # just may be installed in non-standard locations (Cargo, Homebrew, ~/.local/bin). # Extend PATH before checking so we don't reinstall needlessly. export PATH="$PATH:$HOME/.cargo/bin:$HOME/.local/bin:/home/linuxbrew/.linuxbrew/bin" if ! command -v just >/dev/null 2>&1; then warn "just not found — installing to ~/.local/bin (no sudo needed)" mkdir -p "$HOME/.local/bin" curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh \ | bash -s -- --to "$HOME/.local/bin" export PATH="$PATH:$HOME/.local/bin" ok "just $(just --version)" else ok "just $(just --version)" fi # ── 2. /etc/hosts ───────────────────────────────────────────────────────────── step "Checking /etc/hosts for 'keycloak' → 127.0.0.1" if grep -qE '^\s*127\.0\.0\.1\s+.*\bkeycloak\b' /etc/hosts 2>/dev/null; then ok "Entry already present" else warn "Adding '127.0.0.1 keycloak' to /etc/hosts (requires sudo)" if echo "127.0.0.1 keycloak" | sudo -n tee -a /etc/hosts >/dev/null 2>&1; then ok "Entry added" else # sudo requires a password — ask the user to do it once manually echo echo -e " ${YELLOW}Run this command manually, then re-run setup.sh:${NC}" echo echo " echo '127.0.0.1 keycloak' | sudo tee -a /etc/hosts" echo die "/etc/hosts entry missing and sudo requires a password. Add it manually (see above) and re-run." fi fi # ── 3. .env ──────────────────────────────────────────────────────────────────── step "Setting up .env" if [[ -f .env ]]; then ok ".env already exists — skipping" else warn ".env not found — generating with dev defaults" # Well-known dev-only JWT secret. Never use in production. JWT_SECRET="super-secret-jwt-token-with-at-least-32-characters-long" # Generate anon and service_role JWTs signed with the dev secret. # Python 3 is available on virtually every Linux/macOS dev machine. IFS=' ' read -r ANON_KEY SERVICE_KEY < <(python3 - < .env </dev/null; then ok "Permissions fixed" else echo echo -e " ${YELLOW}Run this command manually, then re-run setup.sh:${NC}" echo echo " sudo chown \$USER:\$USER supabase/migrations" echo die "supabase/migrations is not writable. Fix it manually (see above) and re-run." fi else ok "supabase/migrations is writable" fi # ── 5. Install dependencies ──────────────────────────────────────────────────── step "Installing pnpm dependencies" pnpm install ok "Dependencies ready" # ── 6. Start Docker stack ────────────────────────────────────────────────────── step "Starting Docker stack" $DC up -d ok "Containers started" # ── 7. Wait for services ─────────────────────────────────────────────────────── step "Waiting for services" # Usage: wait_for