From fd751f02f83ba71b769d4e7a45a980044fb1ce58 Mon Sep 17 00:00:00 2001 From: poduck Date: Wed, 3 Dec 2025 15:46:01 -0500 Subject: [PATCH] refactor(deploy): Use git pull instead of rsync for deployments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Requires changes to be committed and pushed before deploying - Clones repo on first deploy, then uses git fetch/reset - Preserves .envs secrets which are not in git - Better for multi-developer workflows 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- deploy.sh | 122 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 73 insertions(+), 49 deletions(-) diff --git a/deploy.sh b/deploy.sh index f84abb7..58ac17a 100755 --- a/deploy.sh +++ b/deploy.sh @@ -2,6 +2,9 @@ # SmoothSchedule Production Deployment Script # Usage: ./deploy.sh [server_user@server_host] # Example: ./deploy.sh poduck@smoothschedule.com +# +# This script deploys from git repository, not local files. +# Changes must be committed and pushed before deploying. set -e @@ -12,7 +15,8 @@ YELLOW='\033[1;33m' NC='\033[0m' # No Color SERVER=${1:-"poduck@smoothschedule.com"} -PROJECT_DIR="/home/poduck/Desktop/smoothschedule2" +REPO_URL="https://git.talova.net/poduck/smoothschedule.git" +REMOTE_DIR="/home/poduck/smoothschedule" echo -e "${GREEN}===================================" echo "SmoothSchedule Deployment" @@ -33,57 +37,80 @@ print_error() { echo -e "${RED}>>> $1${NC}" } -# Step 1: Build frontend -print_status "Step 1: Skipping local build (building on server)..." -# cd "$PROJECT_DIR/frontend" -# if [ ! -d "node_modules" ]; then -# print_warning "Installing frontend dependencies..." -# npm install -# fi -# npm run build -# print_status "Frontend build complete!" +# Step 1: Check for uncommitted changes +print_status "Step 1: Checking for uncommitted changes..." +if [[ -n $(git status --porcelain) ]]; then + print_error "You have uncommitted changes. Please commit and push before deploying." + git status --short + exit 1 +fi -# Step 2: Prepare deployment package -print_status "Step 2: Preparing deployment package..." -cd "$PROJECT_DIR" -mkdir -p /tmp/smoothschedule-deploy +# Check if local is ahead of remote +LOCAL_COMMIT=$(git rev-parse HEAD) +REMOTE_COMMIT=$(git rev-parse @{u} 2>/dev/null || echo "") -# Copy backend -rsync -av --exclude='.venv' --exclude='__pycache__' --exclude='*.pyc' \ - --exclude='.git' --exclude='node_modules' \ - "$PROJECT_DIR/smoothschedule/" /tmp/smoothschedule-deploy/backend/ +if [[ -z "$REMOTE_COMMIT" ]]; then + print_error "No upstream branch configured. Please push your changes first." + exit 1 +fi -# Copy frontend source -rsync -av --exclude='node_modules' --exclude='dist' --exclude='.git' \ - "$PROJECT_DIR/frontend/" /tmp/smoothschedule-deploy/frontend/ +if [[ "$LOCAL_COMMIT" != "$REMOTE_COMMIT" ]]; then + print_warning "Local branch differs from remote. Checking if ahead..." + AHEAD=$(git rev-list --count @{u}..HEAD) + if [[ "$AHEAD" -gt 0 ]]; then + print_error "You have $AHEAD unpushed commit(s). Please push before deploying." + exit 1 + fi +fi -print_status "Deployment package prepared!" +print_status "All changes committed and pushed!" -# Step 3: Upload to server -print_status "Step 3: Uploading to server..." -ssh "$SERVER" "mkdir -p ~/smoothschedule" +# Step 2: Deploy on server +print_status "Step 2: Deploying on server..." -# Upload backend -rsync -avz --delete /tmp/smoothschedule-deploy/backend/ "$SERVER:~/smoothschedule/" - -# Upload nginx config -scp "$PROJECT_DIR/frontend/nginx.conf" "$SERVER:~/smoothschedule/nginx.conf" - -# Upload frontend -rsync -avz --delete /tmp/smoothschedule-deploy/frontend/ "$SERVER:~/smoothschedule-frontend/" - -print_status "Files uploaded!" - -# Step 4: Deploy on server -print_status "Step 4: Deploying on server..." - -ssh "$SERVER" 'bash -s' << 'ENDSSH' +ssh "$SERVER" "bash -s" << ENDSSH set -e -echo ">>> Navigating to project directory..." -cd ~/smoothschedule +echo ">>> Setting up project directory..." + +# Backup .envs if they exist (secrets not in git) +if [ -d "$REMOTE_DIR/smoothschedule/.envs" ]; then + echo ">>> Backing up .envs secrets..." + cp -r "$REMOTE_DIR/smoothschedule/.envs" /tmp/.envs-backup +elif [ -d "$REMOTE_DIR/.envs" ]; then + # Old structure - .envs was at root level + echo ">>> Backing up .envs secrets (old location)..." + cp -r "$REMOTE_DIR/.envs" /tmp/.envs-backup +fi + +if [ ! -d "$REMOTE_DIR/.git" ]; then + echo ">>> Cloning repository for the first time..." + # Remove old non-git deployment if exists + if [ -d "$REMOTE_DIR" ]; then + rm -rf "$REMOTE_DIR" + fi + git clone "$REPO_URL" "$REMOTE_DIR" +else + echo ">>> Repository exists, pulling latest changes..." + cd "$REMOTE_DIR" + git fetch origin + git reset --hard origin/main +fi + +cd "$REMOTE_DIR" + +# Restore .envs secrets +if [ -d /tmp/.envs-backup ]; then + echo ">>> Restoring .envs secrets..." + cp -r /tmp/.envs-backup "$REMOTE_DIR/smoothschedule/.envs" + rm -rf /tmp/.envs-backup +fi + +echo ">>> Current commit:" +git log -1 --oneline echo ">>> Building Docker images..." +cd smoothschedule docker compose -f docker-compose.production.yml build echo ">>> Starting containers..." @@ -93,10 +120,10 @@ echo ">>> Waiting for containers to start..." sleep 10 echo ">>> Running database migrations..." -docker compose -f docker-compose.production.yml exec -T django sh -c 'export DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} && python manage.py migrate' +docker compose -f docker-compose.production.yml exec -T django sh -c 'export DATABASE_URL=postgres://\${POSTGRES_USER}:\${POSTGRES_PASSWORD}@\${POSTGRES_HOST}:\${POSTGRES_PORT}/\${POSTGRES_DB} && python manage.py migrate' echo ">>> Collecting static files..." -docker compose -f docker-compose.production.yml exec -T django sh -c 'export DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} && python manage.py collectstatic --noinput' +docker compose -f docker-compose.production.yml exec -T django sh -c 'export DATABASE_URL=postgres://\${POSTGRES_USER}:\${POSTGRES_PASSWORD}@\${POSTGRES_HOST}:\${POSTGRES_PORT}/\${POSTGRES_DB} && python manage.py collectstatic --noinput' echo ">>> Seeding/updating platform plugins for all tenants..." docker compose -f docker-compose.production.yml exec -T django python -c " @@ -115,9 +142,6 @@ docker compose -f docker-compose.production.yml ps echo ">>> Deployment complete!" ENDSSH -# Cleanup -rm -rf /tmp/smoothschedule-deploy - echo "" print_status "===================================" print_status "Deployment Complete!" @@ -129,7 +153,7 @@ echo " - https://platform.smoothschedule.com" echo " - https://*.smoothschedule.com (tenant subdomains)" echo "" echo "To view logs:" -echo " ssh $SERVER 'cd ~/smoothschedule && docker compose -f docker-compose.production.yml logs -f'" +echo " ssh $SERVER 'cd ~/smoothschedule/smoothschedule && docker compose -f docker-compose.production.yml logs -f'" echo "" echo "To check status:" -echo " ssh $SERVER 'cd ~/smoothschedule && docker compose -f docker-compose.production.yml ps'" +echo " ssh $SERVER 'cd ~/smoothschedule/smoothschedule && docker compose -f docker-compose.production.yml ps'"