Fix web/ startup errors and sync with boilerplate
- Load .env via python-dotenv in core.py - Skip analytics DB open if file doesn't exist - Guard dashboard analytics calls when DB not available - Namespace admin templates under admin/ to avoid blueprint conflicts - Add dev-login routes for user and admin (DEBUG only) - Update .copier-answers.yml src_path to GitLab remote Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
131
web/scripts/dev_run.sh
Normal file
131
web/scripts/dev_run.sh
Normal file
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env bash
|
||||
# Start all BeanFlows dev processes with colored, labeled output.
|
||||
#
|
||||
# Usage: ./scripts/dev_run.sh
|
||||
#
|
||||
# On each start: runs migrations (idempotent), builds CSS, optionally starts
|
||||
# ngrok for Paddle webhook forwarding, then starts app (port 5000),
|
||||
# background worker, and CSS watcher.
|
||||
# Ctrl-C stops everything cleanly.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
# -- Colors & helpers --------------------------------------------------------
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
COLOR_APP='\033[0;36m' # cyan
|
||||
COLOR_WORKER='\033[0;33m' # yellow
|
||||
COLOR_CSS='\033[0;35m' # magenta
|
||||
|
||||
info() { echo -e "${BLUE}==>${NC} ${BOLD}$1${NC}"; }
|
||||
ok() { echo -e "${GREEN} ✓${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW} !${NC} $1"; }
|
||||
fail() { echo -e "${RED} ✗${NC} $1"; exit 1; }
|
||||
|
||||
# -- Preflight ---------------------------------------------------------------
|
||||
|
||||
if [ ! -f .env ]; then
|
||||
fail ".env not found. Run ./scripts/dev_setup.sh first."
|
||||
fi
|
||||
|
||||
# Load config from .env
|
||||
PADDLE_API_KEY=$(grep '^PADDLE_API_KEY=' .env 2>/dev/null | cut -d= -f2- || true)
|
||||
PADDLE_NOTIFICATION_SETTING_ID=$(grep '^PADDLE_NOTIFICATION_SETTING_ID=' .env 2>/dev/null | cut -d= -f2- || true)
|
||||
|
||||
# -- Preparation -------------------------------------------------------------
|
||||
|
||||
info "Running migrations"
|
||||
uv run --package beanflows python -m beanflows.migrations.migrate
|
||||
ok "Migrations applied"
|
||||
|
||||
info "Building CSS"
|
||||
make css-build
|
||||
ok "CSS built"
|
||||
|
||||
# -- Process management ------------------------------------------------------
|
||||
|
||||
PIDS=()
|
||||
|
||||
cleanup() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Stopping all processes...${NC}"
|
||||
for pid in "${PIDS[@]}"; do
|
||||
pkill -P "$pid" 2>/dev/null || true
|
||||
kill "$pid" 2>/dev/null || true
|
||||
done
|
||||
wait 2>/dev/null || true
|
||||
echo "Done."
|
||||
exit 0
|
||||
}
|
||||
|
||||
trap cleanup SIGINT SIGTERM
|
||||
|
||||
# Prefix each line of a command's output with a colored label.
|
||||
run_with_label() {
|
||||
local color="$1" label="$2"
|
||||
shift 2
|
||||
"$@" > >(while IFS= read -r line; do echo -e "${color}[${label}]${NC} ${line}"; done) 2>&1 &
|
||||
PIDS+=($!)
|
||||
}
|
||||
|
||||
# -- Ngrok tunnel (if Paddle is configured) ----------------------------------
|
||||
|
||||
TUNNEL_URL=""
|
||||
|
||||
if [ -n "$PADDLE_API_KEY" ] && [ -n "$PADDLE_NOTIFICATION_SETTING_ID" ]; then
|
||||
if command -v ngrok >/dev/null 2>&1; then
|
||||
info "Starting ngrok tunnel for Paddle webhooks"
|
||||
ngrok http 5001 --log=stdout --log-level=warn > /tmp/beanflows-ngrok.log 2>&1 &
|
||||
NGROK_PID=$!
|
||||
PIDS+=($NGROK_PID)
|
||||
|
||||
# Wait for ngrok to be ready (up to 10 seconds)
|
||||
WAIT_SECONDS=10
|
||||
for i in $(seq 1 $WAIT_SECONDS); do
|
||||
TUNNEL_URL=$(curl -s http://localhost:4040/api/tunnels 2>/dev/null \
|
||||
| python3 -c "import sys,json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])" 2>/dev/null) \
|
||||
&& break
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [ -n "$TUNNEL_URL" ]; then
|
||||
ok "ngrok tunnel: $TUNNEL_URL"
|
||||
else
|
||||
warn "ngrok started but tunnel URL not available — webhooks won't reach localhost"
|
||||
fi
|
||||
else
|
||||
warn "ngrok not installed — Paddle webhooks won't reach localhost"
|
||||
warn "Install: https://ngrok.com/download"
|
||||
fi
|
||||
elif [ -n "$PADDLE_API_KEY" ]; then
|
||||
warn "PADDLE_NOTIFICATION_SETTING_ID not set — webhook forwarding disabled"
|
||||
fi
|
||||
|
||||
# -- Start processes ---------------------------------------------------------
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}Starting BeanFlows dev environment${NC}"
|
||||
echo ""
|
||||
echo " app: http://localhost:5001"
|
||||
echo " dev-login: http://localhost:5001/auth/dev-login"
|
||||
echo " admin: http://localhost:5001/admin/dev-login"
|
||||
if [ -n "$TUNNEL_URL" ]; then
|
||||
echo " tunnel: $TUNNEL_URL"
|
||||
fi
|
||||
echo ""
|
||||
echo "Press Ctrl-C to stop all processes."
|
||||
echo ""
|
||||
|
||||
run_with_label "$COLOR_APP" "app " uv run --package beanflows python -m beanflows.app
|
||||
run_with_label "$COLOR_WORKER" "worker" uv run --package beanflows python -m beanflows.worker
|
||||
run_with_label "$COLOR_CSS" "css " make css-watch
|
||||
|
||||
wait
|
||||
108
web/scripts/dev_setup.sh
Normal file
108
web/scripts/dev_setup.sh
Normal file
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env bash
|
||||
# Bootstrap a local dev environment for BeanFlows.
|
||||
#
|
||||
# Usage: ./scripts/dev_setup.sh
|
||||
#
|
||||
# Checks prerequisites, installs deps, creates .env, runs migrations,
|
||||
# and builds CSS.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
# -- Colors & helpers -------------------------------------------------------
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
info() { echo -e "${BLUE}==>${NC} ${BOLD}$1${NC}"; }
|
||||
ok() { echo -e "${GREEN} ✓${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW} !${NC} $1"; }
|
||||
fail() { echo -e "${RED} ✗${NC} $1"; exit 1; }
|
||||
|
||||
# -- Prerequisites -----------------------------------------------------------
|
||||
|
||||
info "Checking prerequisites"
|
||||
|
||||
command -v python3 >/dev/null 2>&1 || fail "python3 not found. Install Python 3.13+."
|
||||
command -v uv >/dev/null 2>&1 || fail "uv not found. Install: https://docs.astral.sh/uv/getting-started/installation/"
|
||||
|
||||
PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
|
||||
ok "python3 ${PYTHON_VERSION}"
|
||||
ok "uv $(uv --version 2>/dev/null | head -1)"
|
||||
|
||||
# -- Install dependencies ----------------------------------------------------
|
||||
|
||||
info "Installing Python dependencies"
|
||||
# Sync from workspace root to get all packages
|
||||
(cd .. && uv sync --all-packages --all-groups)
|
||||
ok "Dependencies installed"
|
||||
|
||||
# -- .env --------------------------------------------------------------------
|
||||
|
||||
if [ -f .env ]; then
|
||||
warn ".env already exists — skipping creation"
|
||||
else
|
||||
info "Creating .env from .env.example"
|
||||
cp .env.example .env
|
||||
|
||||
# Auto-generate SECRET_KEY
|
||||
SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
|
||||
sed -i "s/^SECRET_KEY=.*/SECRET_KEY=${SECRET_KEY}/" .env
|
||||
ok "SECRET_KEY generated"
|
||||
|
||||
# Prompt for optional keys
|
||||
echo ""
|
||||
echo -e "${BOLD}Optional API keys${NC} (press Enter to skip — everything works without them)"
|
||||
echo ""
|
||||
|
||||
read -rp " Paddle API key (for checkout testing): " PADDLE_API_KEY
|
||||
if [ -n "$PADDLE_API_KEY" ]; then
|
||||
sed -i "s/^PADDLE_API_KEY=.*/PADDLE_API_KEY=${PADDLE_API_KEY}/" .env
|
||||
ok "PADDLE_API_KEY set"
|
||||
fi
|
||||
|
||||
read -rp " Resend API key (for email testing): " RESEND_API_KEY
|
||||
if [ -n "$RESEND_API_KEY" ]; then
|
||||
sed -i "s/^RESEND_API_KEY=.*/RESEND_API_KEY=${RESEND_API_KEY}/" .env
|
||||
ok "RESEND_API_KEY set"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
ok ".env created"
|
||||
fi
|
||||
|
||||
# -- Migrations ---------------------------------------------------------------
|
||||
|
||||
info "Running database migrations"
|
||||
uv run --package beanflows python -m beanflows.migrations.migrate
|
||||
ok "Migrations applied"
|
||||
|
||||
# -- CSS build ----------------------------------------------------------------
|
||||
|
||||
info "Building CSS"
|
||||
make css-build
|
||||
ok "CSS built"
|
||||
|
||||
# -- Summary ------------------------------------------------------------------
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}${BOLD}Setup complete!${NC}"
|
||||
echo ""
|
||||
echo " Start all services: ./scripts/dev_run.sh"
|
||||
echo ""
|
||||
echo " URLs:"
|
||||
echo " App: http://localhost:5001"
|
||||
echo " Admin: http://localhost:5001/admin (password: admin)"
|
||||
echo ""
|
||||
echo " Email:"
|
||||
if grep -q '^RESEND_API_KEY=.\+' .env 2>/dev/null; then
|
||||
echo " Resend configured — emails sent via API"
|
||||
else
|
||||
echo " No Resend key — emails print to console"
|
||||
fi
|
||||
echo ""
|
||||
Reference in New Issue
Block a user