From 86947ab2067179630f19e46f5083ef29e6806ec5 Mon Sep 17 00:00:00 2001 From: poduck Date: Wed, 3 Dec 2025 17:27:17 -0500 Subject: [PATCH] feat(deploy): Add selective service rebuild and --no-migrate option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add support for specifying services to rebuild (e.g., ./deploy.sh traefik) - Add --no-migrate flag to skip migrations for config-only changes - Reduce wait time from 10s to 5s Usage examples: ./deploy.sh # Build all, run migrations ./deploy.sh traefik --no-migrate # Only rebuild traefik, skip migrations ./deploy.sh django nginx # Build django and nginx, run migrations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- deploy.sh | 68 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/deploy.sh b/deploy.sh index d27238f..ce6b2a3 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,7 +1,12 @@ #!/bin/bash # SmoothSchedule Production Deployment Script -# Usage: ./deploy.sh [server_user@server_host] -# Example: ./deploy.sh poduck@smoothschedule.com +# Usage: ./deploy.sh [server_user@server_host] [services...] +# Example: ./deploy.sh poduck@smoothschedule.com # Build all +# Example: ./deploy.sh poduck@smoothschedule.com traefik # Build only traefik +# Example: ./deploy.sh poduck@smoothschedule.com django nginx # Build django and nginx +# +# Available services: django, traefik, nginx, postgres, celeryworker, celerybeat, flower, awscli +# Use --no-migrate to skip migrations (useful for config-only changes like traefik) # # This script deploys from git repository, not local files. # Changes must be committed and pushed before deploying. @@ -14,7 +19,23 @@ GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color -SERVER=${1:-"poduck@smoothschedule.com"} +# Parse arguments +SERVER="" +SERVICES="" +SKIP_MIGRATE=false + +for arg in "$@"; do + if [[ "$arg" == "--no-migrate" ]]; then + SKIP_MIGRATE=true + elif [[ -z "$SERVER" ]]; then + SERVER="$arg" + else + SERVICES="$SERVICES $arg" + fi +done + +SERVER=${SERVER:-"poduck@smoothschedule.com"} +SERVICES=$(echo "$SERVICES" | xargs) # Trim whitespace REPO_URL="https://git.talova.net/poduck/smoothschedule.git" REMOTE_DIR="/home/poduck/smoothschedule" @@ -22,6 +43,14 @@ echo -e "${GREEN}===================================" echo "SmoothSchedule Deployment" echo "===================================${NC}" echo "Target server: $SERVER" +if [[ -n "$SERVICES" ]]; then + echo "Services to rebuild: $SERVICES" +else + echo "Services to rebuild: ALL" +fi +if [[ "$SKIP_MIGRATE" == "true" ]]; then + echo "Migrations: SKIPPED" +fi echo "" # Function to print status @@ -128,24 +157,33 @@ fi echo ">>> Current commit:" git log -1 --oneline -echo ">>> Building Docker images..." cd smoothschedule -docker compose -f docker-compose.production.yml build + +# Build images (all or specific services) +if [[ -n "$SERVICES" ]]; then + echo ">>> Building Docker images: $SERVICES..." + docker compose -f docker-compose.production.yml build $SERVICES +else + echo ">>> Building all Docker images..." + docker compose -f docker-compose.production.yml build +fi echo ">>> Starting containers..." docker compose -f docker-compose.production.yml up -d echo ">>> Waiting for containers to start..." -sleep 10 +sleep 5 -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' +# Run migrations unless skipped +if [[ "$SKIP_MIGRATE" != "true" ]]; then + 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' -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' + 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' -echo ">>> Seeding/updating platform plugins for all tenants..." -docker compose -f docker-compose.production.yml exec -T django python -c " + echo ">>> Seeding/updating platform plugins for all tenants..." + docker compose -f docker-compose.production.yml exec -T django python -c " from django_tenants.utils import get_tenant_model from django.core.management import call_command Tenant = get_tenant_model() @@ -154,9 +192,9 @@ for tenant in Tenant.objects.exclude(schema_name='public'): call_command('tenant_command', 'seed_platform_plugins', schema=tenant.schema_name, verbosity=0) print(' Done!') " - -echo ">>> Checking container status..." -docker compose -f docker-compose.production.yml ps +else + echo ">>> Skipping migrations (--no-migrate flag used)" +fi echo ">>> Deployment complete!" ENDSSH