This should have been committed 100 years ago
This commit is contained in:
parent
e57323ff3f
commit
a102c96bb4
1 changed files with 365 additions and 0 deletions
365
run-dev.sh
Executable file
365
run-dev.sh
Executable file
|
|
@ -0,0 +1,365 @@
|
|||
#!/bin/bash
|
||||
# Run Chattyness servers in development mode
|
||||
set -eu
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# =============================================================================
|
||||
# Constants
|
||||
# =============================================================================
|
||||
readonly APP_PORT=3000
|
||||
readonly OWNER_PORT=3001
|
||||
readonly LOCKFILE=".run-dev.lock"
|
||||
|
||||
# Process IDs (set during runtime)
|
||||
OWNER_PID=""
|
||||
APP_PID=""
|
||||
|
||||
# =============================================================================
|
||||
# Helper Functions
|
||||
# =============================================================================
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [build|watch] [--user-app|--owner-app|--both] [-f|-k|-s|-r]
|
||||
|
||||
Commands:
|
||||
build Build and run servers (default)
|
||||
watch Watch mode with hot reload
|
||||
|
||||
Options:
|
||||
--user-app Run only the user app (port $APP_PORT)
|
||||
--owner-app Run only the owner admin (port $OWNER_PORT)
|
||||
--both Run both servers (default)
|
||||
-f, --force Kill existing instance and start new one
|
||||
-k, --kill Kill existing instance and exit
|
||||
-s, --status Check if an instance is running
|
||||
-r, --release Build and run in release mode
|
||||
|
||||
Examples:
|
||||
$0 # Build and run both
|
||||
$0 watch # Watch mode for both
|
||||
$0 --owner-app # Build and run owner only
|
||||
$0 watch --user-app # Watch mode for user app only
|
||||
$0 -f watch # Kill existing, then watch mode
|
||||
$0 -k # Kill existing instance
|
||||
$0 -s # Check status
|
||||
$0 -r # Build and run in release mode
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Target helper functions
|
||||
run_owner() { [ "$TARGET" = "both" ] || [ "$TARGET" = "owner" ]; }
|
||||
run_app() { [ "$TARGET" = "both" ] || [ "$TARGET" = "app" ]; }
|
||||
|
||||
# Cleanup function - kills child processes and removes lock file
|
||||
cleanup() {
|
||||
echo ""
|
||||
echo "Shutting down..."
|
||||
[ -n "$OWNER_PID" ] && kill "$OWNER_PID" 2>/dev/null || true
|
||||
[ -n "$APP_PID" ] && kill "$APP_PID" 2>/dev/null || true
|
||||
[ -n "$OWNER_PID" ] && wait "$OWNER_PID" 2>/dev/null || true
|
||||
[ -n "$APP_PID" ] && wait "$APP_PID" 2>/dev/null || true
|
||||
rm -f "$LOCKFILE"
|
||||
echo "Done."
|
||||
}
|
||||
|
||||
# Print server URLs based on what's running
|
||||
print_server_info() {
|
||||
local mode="$1"
|
||||
local build_type="Debug"
|
||||
[ "$RELEASE" = "true" ] && build_type="Release"
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo " Chattyness Development ($mode - $build_type)"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
if run_owner; then
|
||||
echo " Owner Admin: http://127.0.0.1:$OWNER_PORT"
|
||||
fi
|
||||
if run_app; then
|
||||
echo " User App: http://127.0.0.1:$APP_PORT"
|
||||
echo " Realm Admin: http://127.0.0.1:$APP_PORT/admin"
|
||||
fi
|
||||
echo ""
|
||||
if [ "$TARGET" = "both" ]; then
|
||||
echo "Admin CSS lazy-loaded via symlink from owner build."
|
||||
fi
|
||||
echo "Press Ctrl+C to stop"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Wait for running child processes
|
||||
wait_for_processes() {
|
||||
if [ "$TARGET" = "both" ]; then
|
||||
wait "$OWNER_PID" "$APP_PID"
|
||||
elif [ "$TARGET" = "owner" ]; then
|
||||
wait "$OWNER_PID"
|
||||
else
|
||||
wait "$APP_PID"
|
||||
fi
|
||||
}
|
||||
|
||||
# Create symlink for admin CSS (user app loads admin CSS from owner build)
|
||||
setup_admin_css_symlink() {
|
||||
mkdir -p apps/chattyness-app/public
|
||||
local target="../../../target/site-owner/static/chattyness-owner.css"
|
||||
local link="apps/chattyness-app/public/admin.css"
|
||||
if [ ! -L "$link" ]; then
|
||||
ln -sf "$target" "$link"
|
||||
echo "Created symlink: $link -> $target"
|
||||
fi
|
||||
}
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_env() {
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
# shellcheck source=/dev/null
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
}
|
||||
|
||||
# Validate required environment variables
|
||||
check_env() {
|
||||
if [ -z "${DB_CHATTYNESS_OWNER:-}" ]; then
|
||||
echo "Error: DB_CHATTYNESS_OWNER not set"
|
||||
echo "Create a .env file with DB_CHATTYNESS_OWNER=your_password"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${DB_CHATTYNESS_APP:-}" ]; then
|
||||
echo "Error: DB_CHATTYNESS_APP not set"
|
||||
echo "Create a .env file with DB_CHATTYNESS_APP=your_password"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Lock File Management
|
||||
# =============================================================================
|
||||
|
||||
# Check if another instance is running (returns PID or empty)
|
||||
get_running_pid() {
|
||||
if [ -f "$LOCKFILE" ]; then
|
||||
local pid
|
||||
pid=$(cat "$LOCKFILE" 2>/dev/null)
|
||||
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
|
||||
echo "$pid"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Handle --status flag
|
||||
handle_status() {
|
||||
local pid
|
||||
pid=$(get_running_pid)
|
||||
if [ -n "$pid" ]; then
|
||||
echo "Running (PID: $pid)"
|
||||
exit 0
|
||||
else
|
||||
echo "Not running"
|
||||
[ -f "$LOCKFILE" ] && rm -f "$LOCKFILE" # Clean stale lock
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Kill any running instance (shared by -k and -f)
|
||||
kill_running_instance() {
|
||||
local pid
|
||||
pid=$(get_running_pid)
|
||||
if [ -n "$pid" ]; then
|
||||
echo "Killing existing run-dev.sh (PID: $pid)..."
|
||||
kill "$pid"
|
||||
else
|
||||
echo "No running instance found."
|
||||
[ -f "$LOCKFILE" ] && rm -f "$LOCKFILE" # Clean stale lock
|
||||
fi
|
||||
echo "Killing chattyness processes..."
|
||||
killall -9 chattyness-app 2>/dev/null || true
|
||||
killall -9 chattyness-owner 2>/dev/null || true
|
||||
echo "Done."
|
||||
}
|
||||
|
||||
# Handle --kill flag
|
||||
handle_kill() {
|
||||
kill_running_instance
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Handle --force flag (kill existing, then continue)
|
||||
handle_force() {
|
||||
kill_running_instance
|
||||
sleep 1 # Allow lock release
|
||||
}
|
||||
|
||||
# Acquire exclusive lock
|
||||
acquire_lock() {
|
||||
exec 200>"$LOCKFILE"
|
||||
if ! flock -n 200; then
|
||||
local pid
|
||||
pid=$(cat "$LOCKFILE" 2>/dev/null)
|
||||
echo ""
|
||||
echo "ERROR: Another run-dev.sh instance is already running (PID: $pid)"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " $0 -k Kill the existing instance"
|
||||
echo " $0 -f [args...] Kill existing and start new instance"
|
||||
echo " $0 -s Check status"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
echo $$ >"$LOCKFILE"
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Main Commands
|
||||
# =============================================================================
|
||||
|
||||
do_watch() {
|
||||
echo "Starting watch mode..."
|
||||
echo ""
|
||||
|
||||
local release_flag=""
|
||||
[ "$RELEASE" = "true" ] && release_flag="--release"
|
||||
|
||||
# Build owner first to create CSS (needed if user app needs admin CSS)
|
||||
if run_owner; then
|
||||
echo "Building owner app first (for admin CSS)..."
|
||||
cargo leptos build -p chattyness-owner $release_flag
|
||||
setup_admin_css_symlink
|
||||
fi
|
||||
|
||||
# Start watch processes
|
||||
if run_owner; then
|
||||
cargo leptos watch -p chattyness-owner $release_flag &
|
||||
OWNER_PID=$!
|
||||
fi
|
||||
|
||||
if run_app; then
|
||||
cargo leptos watch -p chattyness-app --split $release_flag &
|
||||
APP_PID=$!
|
||||
fi
|
||||
|
||||
print_server_info "Watch Mode"
|
||||
wait_for_processes
|
||||
}
|
||||
|
||||
do_build() {
|
||||
local release_flag=""
|
||||
local target_dir="debug"
|
||||
if [ "$RELEASE" = "true" ]; then
|
||||
release_flag="--release"
|
||||
target_dir="release"
|
||||
fi
|
||||
|
||||
# Build phase
|
||||
if run_owner; then
|
||||
echo "Running: cargo leptos build -p chattyness-owner $release_flag"
|
||||
cargo leptos build -p chattyness-owner $release_flag
|
||||
setup_admin_css_symlink
|
||||
fi
|
||||
|
||||
if run_app; then
|
||||
echo ""
|
||||
echo "Running: cargo leptos build -p chattyness-app --split $release_flag"
|
||||
cargo leptos build -p chattyness-app --split $release_flag
|
||||
fi
|
||||
|
||||
# Verify binaries exist
|
||||
if run_owner && [ ! -x "./target/$target_dir/chattyness-owner" ]; then
|
||||
echo "Error: ./target/$target_dir/chattyness-owner not found or not executable"
|
||||
exit 1
|
||||
fi
|
||||
if run_app && [ ! -x "./target/$target_dir/chattyness-app" ]; then
|
||||
echo "Error: ./target/$target_dir/chattyness-app not found or not executable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Start servers
|
||||
if run_owner; then
|
||||
echo "Starting Owner Server on :$OWNER_PORT..."
|
||||
./target/$target_dir/chattyness-owner &
|
||||
OWNER_PID=$!
|
||||
fi
|
||||
|
||||
if run_app; then
|
||||
echo "Starting App Server on :$APP_PORT..."
|
||||
./target/$target_dir/chattyness-app &
|
||||
APP_PID=$!
|
||||
fi
|
||||
|
||||
print_server_info "Servers"
|
||||
wait_for_processes
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Main Entry Point
|
||||
# =============================================================================
|
||||
|
||||
# Parse arguments
|
||||
LEPTOS_CMD="build"
|
||||
TARGET="both"
|
||||
FORCE="false"
|
||||
KILL_EXISTING="false"
|
||||
CHECK_STATUS="false"
|
||||
RELEASE="false"
|
||||
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
build | watch)
|
||||
LEPTOS_CMD="$arg"
|
||||
;;
|
||||
--user-app)
|
||||
TARGET="app"
|
||||
;;
|
||||
--owner-app)
|
||||
TARGET="owner"
|
||||
;;
|
||||
--both)
|
||||
TARGET="both"
|
||||
;;
|
||||
-f | --force)
|
||||
FORCE="true"
|
||||
;;
|
||||
-k | --kill)
|
||||
KILL_EXISTING="true"
|
||||
;;
|
||||
-s | --status)
|
||||
CHECK_STATUS="true"
|
||||
;;
|
||||
-r | --release)
|
||||
RELEASE="true"
|
||||
;;
|
||||
--help | -h)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $arg"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Handle special flags first (before acquiring lock)
|
||||
[ "$CHECK_STATUS" = "true" ] && handle_status
|
||||
[ "$KILL_EXISTING" = "true" ] && handle_kill
|
||||
[ "$FORCE" = "true" ] && handle_force
|
||||
|
||||
# Acquire lock and store PID
|
||||
acquire_lock
|
||||
|
||||
# Set up cleanup trap
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
# Load and validate environment
|
||||
load_env
|
||||
check_env
|
||||
|
||||
# Run the requested command
|
||||
case "$LEPTOS_CMD" in
|
||||
watch) do_watch ;;
|
||||
build) do_build ;;
|
||||
esac
|
||||
Loading…
Add table
Add a link
Reference in a new issue