- Fix missing await on FocusGroup.get_messages() (N-L1) - Replace time.sleep with asyncio.sleep in key_theme_service and focus_group_service (N-P10) - Replace flask import with quart in focus_groups.py (N-S3) - Add logger.error before all 500 returns in focus_groups.py (N-P6) - Add logging to silent except blocks across routes (N-M10, N-M11) - Add @rate_limit to 6 remaining AI endpoints (N-H4) - Add --confirm flag to populate scripts before delete_many (S-H2) - Remove hardcoded Azure ID fallbacks from msal_service.py and msalConfig.ts (A-M2, F-H4) - Centralize make_serializable() in utils.py, remove duplicates from 3 route files (N-P7) - Replace all datetime.utcnow() with datetime.now(timezone.utc) across entire backend (M-L2) - AuthContext.tsx: only mark token validated on 200 success, not on non-401 errors (F-H2) - Rename authType → auth_type in auth.py (N-S4) - Add security_report.md and security_report.pdf with full 92-finding status Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
95 lines
3.7 KiB
Bash
Executable file
95 lines
3.7 KiB
Bash
Executable file
#!/bin/bash
|
|
set -e # Exit on any error
|
|
|
|
# Configuration — source of truth for all paths
|
|
DEPLOY_DIR="/opt/semblance"
|
|
FRONTEND_DEST="/var/www/html/semblance"
|
|
BACKEND_DIR="$DEPLOY_DIR/backend"
|
|
PYTHON_CMD="python3.13"
|
|
|
|
echo "======================================"
|
|
echo "Starting deployment..."
|
|
echo "======================================"
|
|
|
|
# ── Pre-flight checks ─────────────────────────────────────────────────────────
|
|
|
|
# Verify backend/.env exists (it is gitignored — must be provisioned manually)
|
|
if [ ! -f "$BACKEND_DIR/.env" ]; then
|
|
echo ""
|
|
echo "ERROR: $BACKEND_DIR/.env not found."
|
|
echo "This file is not tracked in git and must be created manually on the server."
|
|
echo "Copy backend/.env.example and fill in real values:"
|
|
echo " cp $BACKEND_DIR/.env.example $BACKEND_DIR/.env"
|
|
echo " nano $BACKEND_DIR/.env"
|
|
exit 1
|
|
fi
|
|
|
|
# Verify required env vars are set in backend/.env
|
|
for VAR in SECRET_KEY JWT_SECRET_KEY OPENAI_API_KEY GEMINI_API_KEY; do
|
|
if ! grep -q "^${VAR}=.\+" "$BACKEND_DIR/.env" 2>/dev/null; then
|
|
echo ""
|
|
echo "ERROR: $VAR is not set in $BACKEND_DIR/.env"
|
|
exit 1
|
|
fi
|
|
done
|
|
echo "✓ backend/.env present and required vars set"
|
|
|
|
# ── Step 1: Pull latest changes ───────────────────────────────────────────────
|
|
echo ""
|
|
echo "[1/7] Pulling latest changes from git..."
|
|
cd "$DEPLOY_DIR"
|
|
git pull
|
|
|
|
# ── Step 2: Set up frontend environment ──────────────────────────────────────
|
|
echo ""
|
|
echo "[2/7] Setting up frontend environment..."
|
|
cp .env.production .env
|
|
|
|
# ── Step 3: Set up Python virtual environment ─────────────────────────────────
|
|
echo ""
|
|
echo "[3/7] Setting up Python virtual environment..."
|
|
cd "$BACKEND_DIR"
|
|
if [ ! -d "venv" ]; then
|
|
echo "Creating new virtual environment with $PYTHON_CMD..."
|
|
$PYTHON_CMD -m venv venv
|
|
else
|
|
echo "Virtual environment already exists."
|
|
fi
|
|
|
|
# ── Step 4: Install Python dependencies ──────────────────────────────────────
|
|
echo ""
|
|
echo "[4/7] Installing Python dependencies..."
|
|
source venv/bin/activate
|
|
pip install -r requirements.txt --quiet
|
|
|
|
# ── Step 5: Build and deploy frontend ────────────────────────────────────────
|
|
echo ""
|
|
echo "[5/7] Building and deploying frontend..."
|
|
cd "$DEPLOY_DIR"
|
|
npm install --silent
|
|
npm run build
|
|
|
|
echo "Cleaning deployment directory..."
|
|
rm -rf "$FRONTEND_DEST"/*
|
|
echo "Copying new build..."
|
|
cp -r dist/* "$FRONTEND_DEST/"
|
|
|
|
# ── Step 6: Ensure backend directories exist with correct ownership ───────────
|
|
echo ""
|
|
echo "[6/7] Creating backend directories..."
|
|
mkdir -p "$BACKEND_DIR/uploads"
|
|
mkdir -p "$BACKEND_DIR/temp"
|
|
sudo chown -R www-data:www-data "$BACKEND_DIR/uploads" "$BACKEND_DIR/temp"
|
|
|
|
# ── Step 7: Restart backend service ──────────────────────────────────────────
|
|
echo ""
|
|
echo "[7/7] Restarting backend service..."
|
|
sudo systemctl restart semblance.service
|
|
|
|
echo ""
|
|
echo "======================================"
|
|
echo "Deployment complete!"
|
|
echo "======================================"
|
|
echo ""
|
|
# Use || true so a non-active status doesn't cause set -e to abort with a confusing error
|
|
systemctl status semblance.service --no-pager || true
|