more boilerplate and dev environment

This commit is contained in:
2026-07-16 16:04:48 -07:00
parent ea34be4e1b
commit a06f21a5c2
27 changed files with 670 additions and 27 deletions
Executable
+157
View File
@@ -0,0 +1,157 @@
#!/usr/bin/env bash
set -euo pipefail
# Dev startup script for OwOrganizer.
# Runs the database in Docker and the backend/frontend natively.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
DB_CONTAINER_NAME="oworganizer-dev-db"
DB_ROOT_PASSWORD="${DB_ROOT_PASSWORD:-top-secret}"
DB_PASSWORD="${DB_PASSWORD:-secret}"
DB_USER="oworganizer"
DB_NAME="oworganizer"
DB_PORT="${DB_PORT:-3306}"
# Colors for output
RESET='\033[0m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
RED='\033[0;31m'
log() {
echo -e "${GREEN}[dev]${RESET} $1"
}
warn() {
echo -e "${YELLOW}[dev]${RESET} $1"
}
cleanup() {
echo
warn "Shutting down dev environment..."
if [[ -n "${BACKEND_PID:-}" ]] && kill -0 "$BACKEND_PID" 2>/dev/null; then
log "Stopping backend (PID $BACKEND_PID)..."
kill "$BACKEND_PID" 2>/dev/null || true
wait "$BACKEND_PID" 2>/dev/null || true
fi
if [[ -n "${FRONTEND_PID:-}" ]] && kill -0 "$FRONTEND_PID" 2>/dev/null; then
log "Stopping frontend (PID $FRONTEND_PID)..."
kill "$FRONTEND_PID" 2>/dev/null || true
wait "$FRONTEND_PID" 2>/dev/null || true
fi
if [[ "${STOP_DB_ON_EXIT:-true}" == "true" ]]; then
log "Stopping database container..."
docker stop "$DB_CONTAINER_NAME" >/dev/null 2>&1 || true
else
warn "Leaving database container '$DB_CONTAINER_NAME' running."
fi
log "Dev environment stopped."
}
trap cleanup EXIT INT TERM
# Ensure required tools are available
command -v docker >/dev/null 2>&1 || { echo -e "${RED}docker is required but not installed.${RESET}"; exit 1; }
command -v go >/dev/null 2>&1 || { echo -e "${RED}go is required but not installed.${RESET}"; exit 1; }
command -v npm >/dev/null 2>&1 || { echo -e "${RED}npm is required but not installed.${RESET}"; exit 1; }
# Start the database container if it's not already running
if docker ps --format '{{.Names}}' | grep -q "^${DB_CONTAINER_NAME}$"; then
warn "Database container '$DB_CONTAINER_NAME' is already running. Reusing it."
elif docker ps -a --format '{{.Names}}' | grep -q "^${DB_CONTAINER_NAME}$"; then
log "Starting existing database container '$DB_CONTAINER_NAME'..."
docker start "$DB_CONTAINER_NAME" >/dev/null
else
log "Creating and starting database container '$DB_CONTAINER_NAME'..."
docker run -d \
--name "$DB_CONTAINER_NAME" \
-e MYSQL_ROOT_PASSWORD="$DB_ROOT_PASSWORD" \
-e MYSQL_USER="$DB_USER" \
-e MYSQL_PASSWORD="$DB_PASSWORD" \
-e MYSQL_DATABASE="$DB_NAME" \
-p "${DB_PORT}:3306" \
mariadb:10 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci \
>/dev/null
fi
# Wait for MariaDB to be ready
log "Waiting for database to be ready..."
for i in {1..60}; do
if docker exec "$DB_CONTAINER_NAME" mysqladmin ping \
-h localhost -u "$DB_USER" --password="$DB_PASSWORD" \
>/dev/null 2>&1; then
# mysqladmin ping can return true before the server accepts SQL connections,
# so wait a little longer for the server to finish initializing.
sleep 2
log "Database is ready."
break
fi
if [[ "$i" -eq 60 ]]; then
echo -e "${RED}Database did not become ready in time.${RESET}"
exit 1
fi
sleep 1
done
# Start the backend (with retries in case the DB isn't fully accepting connections yet)
log "Starting backend..."
cd "$PROJECT_DIR/backend"
BACKEND_START_ATTEMPTS="${BACKEND_START_ATTEMPTS:-3}"
for attempt in $(seq 1 "$BACKEND_START_ATTEMPTS"); do
DB_HOST=localhost DB_PASSWORD="$DB_PASSWORD" go run . &
BACKEND_PID=$!
# Wait for backend to be ready
log "Waiting for backend to be ready (attempt $attempt/$BACKEND_START_ATTEMPTS)..."
ready=false
for i in {1..30}; do
if curl -s http://localhost:8080/ping >/dev/null 2>&1; then
log "Backend is ready at http://localhost:8080"
ready=true
break
fi
if ! kill -0 "$BACKEND_PID" 2>/dev/null; then
warn "Backend exited early, possibly waiting for DB."
break
fi
sleep 1
done
if [[ "$ready" == "true" ]]; then
break
fi
if [[ "$attempt" -eq "$BACKEND_START_ATTEMPTS" ]]; then
echo -e "${RED}Backend did not become ready after $BACKEND_START_ATTEMPTS attempts.${RESET}"
exit 1
fi
warn "Retrying backend startup..."
sleep 2
done
# Start the frontend
log "Starting frontend..."
cd "$PROJECT_DIR/frontend"
if [[ ! -f .env ]]; then
warn "No .env file found in frontend/. Creating from .env.example..."
cp .env.example .env
fi
npm run dev &
FRONTEND_PID=$!
log "Frontend starting. It will be available at http://localhost:5173"
log "${BLUE}Press Ctrl-C to stop all services.${RESET}"
# Wait for either process to exit
wait -n "$BACKEND_PID" "$FRONTEND_PID" 2>/dev/null || true