From 834de7d74c44742ad76c9842a37ef9ddcd43d0b1 Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 15 Dec 2025 14:50:49 -0600 Subject: [PATCH] Add deployment script for Ubuntu server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add deploy.sh for automated deployment (idempotent) - Add .env.deploy.example template for server configuration - Update .gitignore to exclude .env.deploy The script handles both first-time install and updates: - Pulls latest code from git - Builds frontend with production URLs - Deploys to Apache document root - Rebuilds and restarts Docker backend - Includes health check verification 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .env.deploy.example | 14 ++++ .gitignore | 1 + deploy.sh | 159 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 .env.deploy.example create mode 100755 deploy.sh diff --git a/.env.deploy.example b/.env.deploy.example new file mode 100644 index 0000000..d4a9f4a --- /dev/null +++ b/.env.deploy.example @@ -0,0 +1,14 @@ +# ModComms Deployment Configuration +# Copy this file to .env.deploy and update with your server values + +# Frontend deployment directory (Apache document root) +FRONTEND_DEPLOY_DIR=/var/www/html/modcomms + +# Backend URLs (used during frontend build) +# These should match your production domain +VITE_BACKEND_WS_URL=wss://your-domain.com/ws/analyze +VITE_BACKEND_URL=https://your-domain.com + +# CORS origins (should match your frontend domain) +# Multiple origins can be comma-separated +CORS_ORIGINS=https://your-domain.com diff --git a/.gitignore b/.gitignore index c4d9188..21a5211 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .env.local .env.*.local *.local +.env.deploy # Python __pycache__/ diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..e606826 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,159 @@ +#!/bin/bash +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" + +echo "=== ModComms Deployment ===" +echo "Working directory: $SCRIPT_DIR" + +# --- Check prerequisites --- +echo "" +echo "[Prerequisites] Checking required tools..." + +check_command() { + if ! command -v "$1" &> /dev/null; then + echo "Error: $1 is not installed" + exit 1 + fi + echo " ✓ $1" +} + +check_command git +check_command node +check_command npm +check_command docker + +# --- Load deployment configuration --- +if [ -f .env.deploy ]; then + source .env.deploy + echo " ✓ .env.deploy loaded" +else + echo "" + echo "Error: .env.deploy not found" + echo "Create it from the template:" + echo " cp .env.deploy.example .env.deploy" + echo " nano .env.deploy" + exit 1 +fi + +# Validate required variables +if [ -z "$FRONTEND_DEPLOY_DIR" ]; then + echo "Error: FRONTEND_DEPLOY_DIR not set in .env.deploy" + exit 1 +fi + +# --- Check backend/.env exists (required for GEMINI_API_KEY) --- +if [ ! -f backend/.env ]; then + if [ -f backend/.env.example ]; then + echo "" + echo "Error: backend/.env not found" + echo "Create it from the template:" + echo " cp backend/.env.example backend/.env" + echo " nano backend/.env # Add your GEMINI_API_KEY" + exit 1 + else + echo "Error: backend/.env not found and no template available" + exit 1 + fi +fi +echo " ✓ backend/.env exists" + +# --- 1. Pull latest code (skip if not a git repo or no remote) --- +echo "" +echo "[1/5] Updating code..." +if [ -d .git ]; then + if git remote -v | grep -q origin; then + git pull || echo "Warning: git pull failed, continuing with local code" + else + echo " No remote configured, skipping git pull" + fi +else + echo " Not a git repository, skipping git pull" +fi + +# --- 2. Build frontend --- +echo "" +echo "[2/5] Building frontend..." +cd frontend + +# Install dependencies (npm install is idempotent) +npm install + +# Create/update .env.local with production URLs +cat > .env.local << EOF +VITE_BACKEND_WS_URL=${VITE_BACKEND_WS_URL:-ws://localhost:8000/ws/analyze} +VITE_BACKEND_URL=${VITE_BACKEND_URL:-http://localhost:8000} +EOF +echo " Frontend environment configured" + +npm run build +cd "$SCRIPT_DIR" + +# --- 3. Deploy frontend to Apache --- +echo "" +echo "[3/5] Deploying frontend to ${FRONTEND_DEPLOY_DIR}..." + +# Create directory if it doesn't exist +sudo mkdir -p "$FRONTEND_DEPLOY_DIR" + +# Clear existing files (safe deletion with variable check) +if [ -n "$FRONTEND_DEPLOY_DIR" ] && [ -d "$FRONTEND_DEPLOY_DIR" ]; then + sudo find "$FRONTEND_DEPLOY_DIR" -mindepth 1 -delete 2>/dev/null || true +fi + +# Copy new build +sudo cp -r frontend/dist/* "$FRONTEND_DEPLOY_DIR/" +sudo chown -R www-data:www-data "$FRONTEND_DEPLOY_DIR" +echo " ✓ Frontend deployed" + +# --- 4. Update backend configuration --- +echo "" +echo "[4/5] Updating backend configuration..." + +# Update CORS_ORIGINS if specified +if [ -n "$CORS_ORIGINS" ]; then + if grep -q "^CORS_ORIGINS=" backend/.env; then + sed -i "s|^CORS_ORIGINS=.*|CORS_ORIGINS=${CORS_ORIGINS}|" backend/.env + else + echo "CORS_ORIGINS=${CORS_ORIGINS}" >> backend/.env + fi + echo " ✓ CORS_ORIGINS updated" +fi + +# --- 5. Build and start/restart backend containers --- +echo "" +echo "[5/5] Building and starting backend..." + +# Build image (always rebuild to pick up code changes) +docker compose build + +# Start or restart containers (docker compose up -d is idempotent) +docker compose up -d + +# Wait for health check +echo " Waiting for backend to be healthy..." +for i in {1..30}; do + if curl -sf http://localhost:8000/health > /dev/null 2>&1; then + echo " ✓ Backend is healthy" + break + fi + if [ $i -eq 30 ]; then + echo " Warning: Backend health check timed out" + fi + sleep 1 +done + +# --- Deployment summary --- +echo "" +echo "=========================================" +echo " Deployment Complete!" +echo "=========================================" +echo "" +echo "Frontend: ${FRONTEND_DEPLOY_DIR}" +echo "Backend: http://localhost:8000" +echo "" +docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}" +echo "" +echo "Health check:" +curl -s http://localhost:8000/health && echo "" || echo "Warning: Backend not responding"