From f86a2db1611d548e5f84669748c4e983e91e4109 Mon Sep 17 00:00:00 2001 From: Xevion Date: Thu, 11 Dec 2025 18:19:48 -0600 Subject: [PATCH] feat(dev): add Overmind-based development workflow Add Procfile.dev for parallel backend/frontend development with Overmind, replacing the sequential build approach. The new `just dev` recipe starts both servers simultaneously with log multiplexing. Changes: - Update `just dev` to use Overmind - Add `build-demo` recipe with optional Windows cross-compilation - Add `smoke` recipe to verify development setup - Improve logging in backend with bind address and dev mode indicator - Allow missing Windows executable in debug builds --- .gitignore | 1 + Justfile | 82 +++++++++++++++++++++++++++++++++++++++++---- Procfile.dev | 5 +++ backend/src/main.rs | 21 +++++++++++- 4 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 Procfile.dev diff --git a/.gitignore b/.gitignore index 6d992cc..baa271e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ demo-* /public .env +.overmind.sock diff --git a/Justfile b/Justfile index e30e1f9..4ed8d1a 100644 --- a/Justfile +++ b/Justfile @@ -45,20 +45,63 @@ frontend-build: @echo "Building frontend..." pnpm --dir frontend build -# Development server with hot reload (backend + ensures frontend is built) -dev: frontend-build - @echo "Starting backend development server with bacon..." - @echo "Frontend is served from ./public (built from frontend/)" - bacon run +# Build demo executables (debug mode for faster dev builds) +build-demo: + #!/usr/bin/env bash + set -euo pipefail + + echo "Building demo executables..." + + # Always build Linux demo + echo "Building Linux demo..." + cargo build --bin demo + cp target/debug/demo ./demo-linux + echo " [OK] Linux demo built" + + # Try to build Windows demo if cross-compilation is available + if rustup target list --installed | grep -q x86_64-pc-windows-gnu; then + echo "Building Windows demo..." + if cargo build --bin demo --target x86_64-pc-windows-gnu 2>/dev/null; then + cp target/x86_64-pc-windows-gnu/debug/demo.exe ./demo.exe + echo " [OK] Windows demo built" + else + echo " [!] Windows build failed (mingw-w64 toolchain may not be installed)" + echo " Continuing without Windows demo..." + fi + else + echo " [SKIP] Windows target not installed" + echo " Install with: rustup target add x86_64-pc-windows-gnu" + echo " Also requires: sudo apt install mingw-w64" + fi + + echo "Demo executables ready!" + +# Development server with hot reload (backend + frontend using Overmind) +dev: build-demo + @echo "Starting development servers with Overmind..." + @echo "" + @echo "Backend will run on: http://localhost:5800" + @echo "Frontend will run on: http://localhost:4321" + @echo "" + @echo "Overmind multiplexes logs with prefixes:" + @echo " [backend] - Bacon watching Rust backend" + @echo " [frontend] - Astro dev server" + @echo "" + @echo "Overmind shortcuts:" + @echo " Ctrl+C - Stop all processes" + @echo " 'overmind connect ' - Attach to a specific process" + @echo "" + overmind start -f Procfile.dev # Watch backend only (for when frontend is already built) -dev-backend: +dev-backend: build-demo @echo "Starting backend watch with bacon..." bacon run # Watch and serve frontend only dev-frontend: @echo "Starting frontend dev server..." + @echo "Make sure the backend is running on port 5800!" pnpm --dir frontend dev # Simple development run (no hot reload) @@ -119,3 +162,30 @@ quick: format @echo "Running quick clippy check..." cargo clippy --workspace --all-targets --all-features -- -D warnings @echo "Quick check completed!" + +# Verify dev setup is ready (builds demo executables and checks dependencies) +smoke: build-demo + @echo "Verifying development setup..." + @echo "" + @echo "Checking for overmind (required for 'just dev')..." + @command -v overmind >/dev/null 2>&1 || { echo " [!] overmind not found. Install from: https://github.com/DarthSim/overmind#installation"; exit 1; } + @echo " [OK] overmind found" + @echo "" + @echo "Checking for bacon..." + @command -v bacon >/dev/null 2>&1 || { echo " [!] bacon not found. Install with: cargo install bacon"; exit 1; } + @echo " [OK] bacon found" + @echo "" + @echo "Checking for pnpm..." + @command -v pnpm >/dev/null 2>&1 || { echo " [!] pnpm not found. Install from: https://pnpm.io/installation"; exit 1; } + @echo " [OK] pnpm found" + @echo "" + @echo "Checking demo executables..." + @test -f ./demo-linux || { echo " [!] demo-linux not found"; exit 1; } + @echo " [OK] demo-linux exists" + @if [ -f ./demo.exe ]; then \ + echo " [OK] demo.exe exists"; \ + else \ + echo " [SKIP] demo.exe not found (Windows builds not available)"; \ + fi + @echo "" + @echo "[OK] Development setup is ready! Run 'just dev' to start." diff --git a/Procfile.dev b/Procfile.dev new file mode 100644 index 0000000..181b5a2 --- /dev/null +++ b/Procfile.dev @@ -0,0 +1,5 @@ +# Procfile for Overmind development workflow +# Start with: overmind start -f Procfile.dev + +backend: PORT=5800 bacon run --headless +frontend: pnpm --dir frontend dev diff --git a/backend/src/main.rs b/backend/src/main.rs index 88199d7..f805001 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -66,6 +66,16 @@ async fn main() { // ("MacOS", "./demo-macos"), ] { if let Err(e) = store.add_executable(exe_type, exe_path) { + // In debug mode, allow missing Windows executable for dev convenience + if cfg!(debug_assertions) && exe_type == "Windows" { + tracing::warn!( + "Windows executable not found at {} (skipping - cross-compilation not set up)", + exe_path + ); + tracing::warn!("To enable Windows builds: rustup target add x86_64-pc-windows-gnu && sudo apt install mingw-w64"); + continue; + } + tracing::error!("{}", e); std::process::exit(1); } @@ -105,6 +115,15 @@ async fn main() { let service = Service::new(router).hoop(cors).hoop(Logger::new()); - let acceptor = TcpListener::new(config.bind_addr()).bind().await; + let bind_addr = config.bind_addr(); + tracing::info!("Server starting on http://{}", bind_addr); + tracing::info!("WebSocket endpoint: ws://{}/ws", bind_addr); + + if cfg!(debug_assertions) { + tracing::info!("Development mode - CORS allows all origins"); + tracing::info!("Access the app at http://localhost:4321 (Astro dev server)"); + } + + let acceptor = TcpListener::new(&bind_addr).bind().await; Server::new(acceptor).serve(service).await; }