MogensR's picture
Create scripts/deploy.sh
dd4248f
raw
history blame
10.4 kB
#!/bin/bash
# Deployment script for BackgroundFX Pro
# Handles deployment to various environments
set -e
# Configuration
SCRIPT_DIR=$(dirname $(realpath $0))
PROJECT_ROOT=$(dirname $SCRIPT_DIR)
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Default values
ENVIRONMENT="production"
DEPLOY_METHOD="docker"
REGISTRY=""
VERSION="latest"
BACKUP=true
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--env)
ENVIRONMENT="$2"
shift 2
;;
--method)
DEPLOY_METHOD="$2"
shift 2
;;
--registry)
REGISTRY="$2"
shift 2
;;
--version)
VERSION="$2"
shift 2
;;
--no-backup)
BACKUP=false
shift
;;
--help)
show_help
exit 0
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
show_help
exit 1
;;
esac
done
show_help() {
cat << EOF
Usage: $0 [OPTIONS]
Deploy BackgroundFX Pro to various environments
Options:
--env ENV Environment (development, staging, production) [default: production]
--method METHOD Deployment method (docker, kubernetes, server) [default: docker]
--registry REGISTRY Container registry URL
--version VERSION Version to deploy [default: latest]
--no-backup Skip backup before deployment
--help Show this help message
Examples:
$0 --env production --method docker
$0 --env staging --registry myregistry.com --version 1.0.0
$0 --env development --no-backup
EOF
}
# Deployment functions
deploy_docker() {
echo -e "${BLUE}Deploying with Docker to ${ENVIRONMENT}...${NC}"
cd "$PROJECT_ROOT"
# Build images
echo "Building Docker images..."
if [ "$ENVIRONMENT" = "production" ]; then
docker build -f docker/Dockerfile.prod -t backgroundfx-pro:$VERSION .
else
docker build -f docker/Dockerfile -t backgroundfx-pro:$VERSION .
fi
# Tag for registry if specified
if [ -n "$REGISTRY" ]; then
docker tag backgroundfx-pro:$VERSION $REGISTRY/backgroundfx-pro:$VERSION
docker push $REGISTRY/backgroundfx-pro:$VERSION
echo -e "${GREEN}βœ“ Pushed to registry: $REGISTRY${NC}"
fi
# Deploy with docker-compose
if [ "$ENVIRONMENT" = "production" ]; then
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
else
docker-compose up -d
fi
echo -e "${GREEN}βœ“ Docker deployment complete${NC}"
}
deploy_kubernetes() {
echo -e "${BLUE}Deploying to Kubernetes cluster...${NC}"
cd "$PROJECT_ROOT/kubernetes"
# Check kubectl
if ! command -v kubectl &> /dev/null; then
echo -e "${RED}kubectl not found${NC}"
exit 1
fi
# Apply configurations
echo "Applying Kubernetes configurations..."
# Create namespace if not exists
kubectl create namespace backgroundfx --dry-run=client -o yaml | kubectl apply -f -
# Apply configs based on environment
if [ "$ENVIRONMENT" = "production" ]; then
kubectl apply -f configmap-prod.yaml
kubectl apply -f secret-prod.yaml
kubectl apply -f deployment-prod.yaml
kubectl apply -f service-prod.yaml
kubectl apply -f ingress-prod.yaml
else
kubectl apply -f configmap.yaml
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
fi
# Wait for deployment
echo "Waiting for deployment to be ready..."
kubectl rollout status deployment/backgroundfx-pro -n backgroundfx
# Get service info
echo -e "\n${GREEN}Deployment complete!${NC}"
kubectl get services -n backgroundfx
kubectl get pods -n backgroundfx
}
deploy_server() {
echo -e "${BLUE}Deploying to server...${NC}"
# Check for required environment variables
if [ -z "$DEPLOY_HOST" ] || [ -z "$DEPLOY_USER" ]; then
echo -e "${RED}Error: DEPLOY_HOST and DEPLOY_USER must be set${NC}"
exit 1
fi
cd "$PROJECT_ROOT"
# Create deployment package
echo "Creating deployment package..."
PACKAGE_NAME="backgroundfx_${VERSION}_${TIMESTAMP}.tar.gz"
tar -czf "/tmp/$PACKAGE_NAME" \
--exclude="*.pyc" \
--exclude="__pycache__" \
--exclude=".git" \
--exclude="venv" \
--exclude="*.log" \
--exclude="outputs/*" \
--exclude="uploads/*" \
.
# Upload to server
echo "Uploading to $DEPLOY_HOST..."
scp "/tmp/$PACKAGE_NAME" "$DEPLOY_USER@$DEPLOY_HOST:/tmp/"
# Deploy on server
echo "Deploying on server..."
ssh "$DEPLOY_USER@$DEPLOY_HOST" << EOF
# Create deployment directory
mkdir -p /opt/backgroundfx/releases/$VERSION
# Extract package
tar -xzf /tmp/$PACKAGE_NAME -C /opt/backgroundfx/releases/$VERSION
# Stop current service
sudo systemctl stop backgroundfx || true
# Update symlink
rm -f /opt/backgroundfx/current
ln -s /opt/backgroundfx/releases/$VERSION /opt/backgroundfx/current
# Install dependencies
cd /opt/backgroundfx/current
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# Start service
sudo systemctl start backgroundfx
sudo systemctl status backgroundfx
EOF
# Cleanup
rm "/tmp/$PACKAGE_NAME"
echo -e "${GREEN}βœ“ Server deployment complete${NC}"
}
# Health check
health_check() {
echo -e "\n${BLUE}Running health check...${NC}"
# Determine URL based on environment
if [ "$ENVIRONMENT" = "production" ]; then
URL="https://app.backgroundfx.com/health"
elif [ "$ENVIRONMENT" = "staging" ]; then
URL="https://staging.backgroundfx.com/health"
else
URL="http://localhost:7860/health"
fi
# Check health endpoint
if curl -f -s "$URL" > /dev/null; then
echo -e "${GREEN}βœ“ Application is healthy${NC}"
curl -s "$URL" | python -m json.tool
else
echo -e "${RED}βœ— Health check failed${NC}"
return 1
fi
}
# Backup function
create_backup() {
if [ "$BACKUP" = false ]; then
return
fi
echo -e "${BLUE}Creating backup...${NC}"
BACKUP_DIR="$PROJECT_ROOT/backups/$TIMESTAMP"
mkdir -p "$BACKUP_DIR"
# Backup database if exists
if [ -f "$PROJECT_ROOT/database.db" ]; then
cp "$PROJECT_ROOT/database.db" "$BACKUP_DIR/"
fi
# Backup configurations
cp -r "$PROJECT_ROOT/config" "$BACKUP_DIR/" 2>/dev/null || true
# Backup docker volumes if using Docker
if [ "$DEPLOY_METHOD" = "docker" ]; then
docker run --rm \
-v backgroundfx-pro_model-cache:/data \
-v "$BACKUP_DIR":/backup \
alpine tar czf /backup/models.tar.gz -C /data . 2>/dev/null || true
fi
echo -e "${GREEN}βœ“ Backup created: $BACKUP_DIR${NC}"
}
# Rollback function
rollback() {
echo -e "${YELLOW}Rolling back deployment...${NC}"
if [ "$DEPLOY_METHOD" = "docker" ]; then
# Docker rollback
docker-compose down
docker tag backgroundfx-pro:previous backgroundfx-pro:$VERSION
docker-compose up -d
elif [ "$DEPLOY_METHOD" = "kubernetes" ]; then
# Kubernetes rollback
kubectl rollout undo deployment/backgroundfx-pro -n backgroundfx
elif [ "$DEPLOY_METHOD" = "server" ]; then
# Server rollback
ssh "$DEPLOY_USER@$DEPLOY_HOST" << EOF
rm /opt/backgroundfx/current
ln -s /opt/backgroundfx/releases/previous /opt/backgroundfx/current
sudo systemctl restart backgroundfx
EOF
fi
echo -e "${GREEN}βœ“ Rollback complete${NC}"
}
# Pre-deployment checks
pre_deploy_checks() {
echo -e "${BLUE}Running pre-deployment checks...${NC}"
# Check git status
if [ -d .git ]; then
if [ -n "$(git status --porcelain)" ]; then
echo -e "${YELLOW}Warning: Uncommitted changes detected${NC}"
read -p "Continue anyway? (y/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
fi
# Run tests
echo "Running tests..."
if command -v pytest &> /dev/null; then
pytest tests/ -m "not slow" --quiet || {
echo -e "${RED}Tests failed${NC}"
read -p "Deploy anyway? (y/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
}
else
echo -e "${YELLOW}pytest not found, skipping tests${NC}"
fi
echo -e "${GREEN}βœ“ Pre-deployment checks passed${NC}"
}
# Main deployment flow
main() {
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}BackgroundFX Pro Deployment${NC}"
echo -e "${BLUE}========================================${NC}"
echo "Environment: $ENVIRONMENT"
echo "Method: $DEPLOY_METHOD"
echo "Version: $VERSION"
echo
# Run pre-deployment checks
pre_deploy_checks
# Create backup
create_backup
# Deploy based on method
case $DEPLOY_METHOD in
docker)
deploy_docker
;;
kubernetes)
deploy_kubernetes
;;
server)
deploy_server
;;
*)
echo -e "${RED}Invalid deployment method: $DEPLOY_METHOD${NC}"
exit 1
;;
esac
# Run health check
sleep 5
if health_check; then
echo -e "\n${GREEN}========================================${NC}"
echo -e "${GREEN}Deployment Successful!${NC}"
echo -e "${GREEN}========================================${NC}"
else
echo -e "\n${RED}Deployment may have issues${NC}"
read -p "Rollback? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
rollback
fi
fi
}
# Trap errors
trap 'echo -e "${RED}Deployment failed!${NC}"; exit 1' ERR
# Run main function
main