chore: import upstream snapshot with attribution
Publish Docker Image / publish (push) Has been cancelled
Publish Docker Image / publish (push) Has been cancelled
This commit is contained in:
+255
@@ -0,0 +1,255 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
BOLD='\033[1m'
|
||||
|
||||
# Internal port configuration for single-port deployment.
|
||||
FRONTEND_PORT="3000"
|
||||
BACKEND_PORT="8000"
|
||||
|
||||
# Print banner
|
||||
print_banner() {
|
||||
echo -e "${CYAN}"
|
||||
cat << 'EOF'
|
||||
|
||||
██████╗ ███████╗███████╗██╗ ██╗███╗ ███╗███████╗
|
||||
██╔══██╗██╔════╝██╔════╝██║ ██║████╗ ████║██╔════╝
|
||||
██████╔╝█████╗ ███████╗██║ ██║██╔████╔██║█████╗
|
||||
██╔══██╗██╔══╝ ╚════██║██║ ██║██║╚██╔╝██║██╔══╝
|
||||
██║ ██║███████╗███████║╚██████╔╝██║ ╚═╝ ██║███████╗
|
||||
╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
|
||||
|
||||
███╗ ███╗ █████╗ ████████╗ ██████╗██╗ ██╗███████╗██████╗
|
||||
████╗ ████║██╔══██╗╚══██╔══╝██╔════╝██║ ██║██╔════╝██╔══██╗
|
||||
██╔████╔██║███████║ ██║ ██║ ███████║█████╗ ██████╔╝
|
||||
██║╚██╔╝██║██╔══██║ ██║ ██║ ██╔══██║██╔══╝ ██╔══██╗
|
||||
██║ ╚═╝ ██║██║ ██║ ██║ ╚██████╗██║ ██║███████╗██║ ██║
|
||||
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
|
||||
|
||||
EOF
|
||||
echo -e "${NC}"
|
||||
echo -e "${BOLD} Crazy Stuff with Resumes and Cover letters${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Print status message
|
||||
status() {
|
||||
echo -e "${GREEN}[✓]${NC} $1" >&2
|
||||
}
|
||||
|
||||
# Print info message
|
||||
info() {
|
||||
echo -e "${BLUE}[i]${NC} $1" >&2
|
||||
}
|
||||
|
||||
# Print warning message
|
||||
warn() {
|
||||
echo -e "${YELLOW}[!]${NC} $1" >&2
|
||||
}
|
||||
|
||||
# Print error message
|
||||
error() {
|
||||
echo -e "${RED}[✗]${NC} $1" >&2
|
||||
}
|
||||
|
||||
# Docker-style secret loader: supports VAR or VAR_FILE
|
||||
file_env() {
|
||||
local var="$1"
|
||||
local def="${2:-}"
|
||||
local file_var="${var}_FILE"
|
||||
|
||||
if [ -n "${!var:-}" ] && [ -n "${!file_var:-}" ]; then
|
||||
error "Both $var and $file_var are set (but are exclusive)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local val="$def"
|
||||
if [ -n "${!var:-}" ]; then
|
||||
val="${!var}"
|
||||
elif [ -n "${!file_var:-}" ]; then
|
||||
if [ ! -r "${!file_var}" ]; then
|
||||
error "Cannot read ${!file_var} for $file_var"
|
||||
exit 1
|
||||
fi
|
||||
val="$(< "${!file_var}")"
|
||||
fi
|
||||
|
||||
export "$var"="$val"
|
||||
unset "$file_var"
|
||||
}
|
||||
|
||||
normalize_log_level() {
|
||||
local value="${1^^}"
|
||||
local fallback="${2}"
|
||||
local name="${3}"
|
||||
|
||||
case "$value" in
|
||||
CRITICAL|ERROR|WARNING|INFO|DEBUG)
|
||||
echo "$value"
|
||||
;;
|
||||
*)
|
||||
warn "Invalid ${name}='$1', using ${fallback}"
|
||||
echo "$fallback"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Exit code to propagate from failed child processes
|
||||
EXIT_CODE=0
|
||||
|
||||
# Cleanup function for graceful shutdown
|
||||
cleanup() {
|
||||
# Prevent re-entry from signals during cleanup
|
||||
trap '' SIGTERM SIGINT SIGQUIT
|
||||
|
||||
echo "" >&2
|
||||
info "Shutting down Resume Matcher..."
|
||||
|
||||
# Kill frontend if running
|
||||
if [ -n "$FRONTEND_PID" ] && kill -0 "$FRONTEND_PID" 2>/dev/null; then
|
||||
kill "$FRONTEND_PID" 2>/dev/null || true
|
||||
wait "$FRONTEND_PID" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Kill backend if running
|
||||
if [ -n "$BACKEND_PID" ] && kill -0 "$BACKEND_PID" 2>/dev/null; then
|
||||
kill "$BACKEND_PID" 2>/dev/null || true
|
||||
wait "$BACKEND_PID" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
status "Shutdown complete"
|
||||
exit "${EXIT_CODE}"
|
||||
}
|
||||
|
||||
# Initialize PIDs so cleanup doesn't fail on early exit
|
||||
BACKEND_PID=""
|
||||
FRONTEND_PID=""
|
||||
|
||||
# Set up signal handlers
|
||||
trap cleanup SIGTERM SIGINT SIGQUIT
|
||||
|
||||
# Print banner
|
||||
print_banner
|
||||
|
||||
# Display routing configuration
|
||||
info "Routing configuration:"
|
||||
echo -e " Public port: ${BOLD}${FRONTEND_PORT}${NC}"
|
||||
echo -e " Internal API: ${BOLD}${BACKEND_PORT}${NC} (proxied at /api)"
|
||||
echo ""
|
||||
|
||||
# Resolve env vars and optional *_FILE secret mounts
|
||||
info "Loading configuration from environment and *_FILE secrets..."
|
||||
file_env "LOG_LEVEL" "INFO"
|
||||
file_env "LOG_LLM" "WARNING"
|
||||
|
||||
file_env "LLM_PROVIDER" "openai"
|
||||
|
||||
# Only resolve optional LLM_* vars if they (or their *_FILE variants) are provided,
|
||||
# so we don't override backend defaults with empty strings.
|
||||
if [ -n "${LLM_MODEL:-}" ] || [ -n "${LLM_MODEL_FILE:-}" ]; then
|
||||
file_env "LLM_MODEL"
|
||||
fi
|
||||
|
||||
if [ -n "${LLM_API_KEY:-}" ] || [ -n "${LLM_API_KEY_FILE:-}" ]; then
|
||||
file_env "LLM_API_KEY"
|
||||
fi
|
||||
|
||||
if [ -n "${LLM_API_BASE:-}" ] || [ -n "${LLM_API_BASE_FILE:-}" ]; then
|
||||
file_env "LLM_API_BASE"
|
||||
fi
|
||||
APP_LOG_LEVEL="$(normalize_log_level "${LOG_LEVEL}" "INFO" "LOG_LEVEL")"
|
||||
LLM_LOG_LEVEL="$(normalize_log_level "${LOG_LLM}" "WARNING" "LOG_LLM")"
|
||||
export LOG_LEVEL="${APP_LOG_LEVEL}"
|
||||
export LOG_LLM="${LLM_LOG_LEVEL}"
|
||||
UVICORN_LOG_LEVEL="$(echo "${APP_LOG_LEVEL}" | tr '[:upper:]' '[:lower:]')"
|
||||
info "Application log level: ${BOLD}${LOG_LEVEL}${NC}"
|
||||
info "LiteLLM log level: ${BOLD}${LOG_LLM}${NC}"
|
||||
if [ "${LOG_LLM}" = "DEBUG" ]; then
|
||||
warn "LOG_LLM=DEBUG may log API keys in plaintext. Do not use in production."
|
||||
fi
|
||||
status "Configuration loaded"
|
||||
|
||||
# Check and create data directory
|
||||
info "Checking data directory..."
|
||||
DATA_DIR="/app/backend/data"
|
||||
if [ ! -d "$DATA_DIR" ]; then
|
||||
mkdir -p "$DATA_DIR"
|
||||
status "Created data directory: $DATA_DIR"
|
||||
else
|
||||
status "Data directory exists: $DATA_DIR"
|
||||
fi
|
||||
|
||||
# Check for Playwright browsers
|
||||
info "Checking Playwright browsers..."
|
||||
if [ -d "/root/.cache/ms-playwright" ] || [ -d "/home/appuser/.cache/ms-playwright" ]; then
|
||||
status "Playwright browsers found"
|
||||
else
|
||||
warn "Installing Playwright Chromium (this may take a moment)..."
|
||||
python -m playwright install chromium || {
|
||||
warn "Playwright install failed — PDF export may not work"
|
||||
}
|
||||
status "Playwright setup complete"
|
||||
fi
|
||||
|
||||
# Start backend
|
||||
echo ""
|
||||
info "Starting backend server on internal port ${BACKEND_PORT}..."
|
||||
cd /app/backend
|
||||
trap '' SIGTERM SIGINT SIGQUIT
|
||||
python -m uvicorn app.main:app --host 0.0.0.0 --port "${BACKEND_PORT}" --log-level "${UVICORN_LOG_LEVEL}" &
|
||||
BACKEND_PID=$!
|
||||
trap cleanup SIGTERM SIGINT SIGQUIT
|
||||
|
||||
# Wait for backend to be ready
|
||||
info "Waiting for backend to be ready..."
|
||||
for i in {1..30}; do
|
||||
if curl -s "http://127.0.0.1:${BACKEND_PORT}/api/v1/health" > /dev/null 2>&1; then
|
||||
status "Backend is ready (PID: $BACKEND_PID)"
|
||||
break
|
||||
fi
|
||||
if ! kill -0 "$BACKEND_PID" 2>/dev/null; then
|
||||
error "Backend process (PID: $BACKEND_PID) died during startup"
|
||||
exit 1
|
||||
fi
|
||||
if [ $i -eq 30 ]; then
|
||||
error "Backend failed to start within 30 seconds"
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Start frontend
|
||||
echo ""
|
||||
info "Starting frontend server on port ${FRONTEND_PORT}..."
|
||||
cd /app/frontend
|
||||
|
||||
# Next.js uses PORT environment variable
|
||||
export HOSTNAME="0.0.0.0"
|
||||
export PORT="${FRONTEND_PORT}"
|
||||
if [ ! -f "server.js" ]; then
|
||||
error "Missing frontend standalone server.js. Rebuild the Docker image."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap '' SIGTERM SIGINT SIGQUIT
|
||||
node server.js "$@" &
|
||||
FRONTEND_PID=$!
|
||||
trap cleanup SIGTERM SIGINT SIGQUIT
|
||||
status "Frontend is running (PID: $FRONTEND_PID)"
|
||||
|
||||
# Wait for either process to exit, but ignore errexit for this wait
|
||||
set +e
|
||||
wait -n "$BACKEND_PID" "$FRONTEND_PID" 2>/dev/null
|
||||
EXIT_CODE=$?
|
||||
set -e
|
||||
warn "A process exited unexpectedly (exit code: ${EXIT_CODE}), shutting down..."
|
||||
cleanup
|
||||
Reference in New Issue
Block a user