Files
wiggleverse-ecomm/scripts/dev.sh
ben.stull 4d1c957f42 fix(slice-1): dev.sh portable on bash 3.2 — drop wait -n, reap process subtree
macOS ships bash 3.2 (no wait -n): poll with kill -0 instead. npm spawns vite as a
grandchild, so cleanup now recurses pgrep -P to reap the whole subtree — Ctrl-C frees
both :8000 and :5173 cleanly. Verified clean-checkout -> dev.sh -> empty self-migrated
Postgres -> /healthz 200, and trap teardown.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 08:46:41 -07:00

65 lines
2.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Local bring-up for ecomm (SD-0001 PUC-10). From a clean checkout this:
# 1. starts the dev Postgres container and waits for it to be healthy (owns its
# lifecycle — Docker is the one prerequisite, docs/BOOTSTRAP.md);
# 2. ensures the backend venv + deps and the frontend node_modules;
# 3. runs the FastAPI backend (:8000, self-migrating an empty DB) and the Vite dev
# server (:5173, proxying /api -> :8000) together.
# Ctrl-C stops both processes; the container keeps running (stop it with
# `docker compose down`, or `docker compose down -v` to reset to empty).
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$repo_root"
export ECOMM_DATABASE_URL="${ECOMM_DATABASE_URL:-postgresql://ecomm:ecomm@localhost:5432/ecomm}"
echo "==> dev Postgres (docker compose up --wait)"
docker compose up -d --wait db
if [ ! -x "$repo_root/.venv/bin/python" ]; then
echo "==> creating backend venv"
python3 -m venv "$repo_root/.venv"
"$repo_root/.venv/bin/python" -m pip install --upgrade pip
"$repo_root/.venv/bin/python" -m pip install -r "$repo_root/backend/requirements.txt"
fi
if [ ! -d "$repo_root/frontend/node_modules" ]; then
echo "==> installing frontend deps"
( cd "$repo_root/frontend" && npm install )
fi
echo "==> starting backend (:8000) and Vite (:5173) — Ctrl-C to stop"
"$repo_root/.venv/bin/python" -m uvicorn app.main:app --app-dir "$repo_root/backend" --port 8000 --reload &
backend_pid=$!
( cd "$repo_root/frontend" && npm run dev ) &
frontend_pid=$!
# Kill a process and its whole descendant tree (children first), portably across
# macOS and Linux — npm spawns vite as a grandchild, so killing the captured pid
# alone would orphan it on :5173. `pgrep -P` (list children) exists on both.
kill_tree() {
local pid=$1 child
for child in $(pgrep -P "$pid" 2>/dev/null); do
kill_tree "$child"
done
kill "$pid" 2>/dev/null || true
}
cleanup() {
trap - INT TERM
echo
echo "==> stopping backend and Vite"
kill_tree "$backend_pid"
kill_tree "$frontend_pid"
wait "$backend_pid" "$frontend_pid" 2>/dev/null || true
}
trap cleanup INT TERM
# Wait until either process exits, then tear the other down. `wait -n` would be
# tidier but is unsupported on macOS's bundled bash 3.2, so poll portably.
while kill -0 "$backend_pid" 2>/dev/null && kill -0 "$frontend_pid" 2>/dev/null; do
sleep 1
done
cleanup