File size: 10,373 Bytes
dd4248f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
#!/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