| #!/bin/bash |
|
|
| |
| |
|
|
| set -e |
|
|
| |
| PROJECT_NAME="transformer-sentiment" |
| DOCKER_IMAGE="${PROJECT_NAME}:latest" |
| BACKUP_DIR="./backups" |
| LOG_DIR="./logs" |
|
|
| |
| RED='\033[0;31m' |
| GREEN='\033[0;32m' |
| YELLOW='\033[1;33m' |
| NC='\033[0m' |
|
|
| |
| log_info() { |
| echo -e "${GREEN}[INFO]${NC} $1" |
| } |
|
|
| log_warn() { |
| echo -e "${YELLOW}[WARN]${NC} $1" |
| } |
|
|
| log_error() { |
| echo -e "${RED}[ERROR]${NC} $1" |
| } |
|
|
| |
| check_dependencies() { |
| log_info "Checking dependencies..." |
| |
| if ! command -v docker &> /dev/null; then |
| log_error "Docker is not installed" |
| exit 1 |
| fi |
| |
| if ! command -v docker-compose &> /dev/null; then |
| log_error "Docker Compose is not installed" |
| exit 1 |
| fi |
| |
| log_info "Dependencies check passed" |
| } |
|
|
| |
| setup_directories() { |
| log_info "Setting up directories..." |
| mkdir -p $BACKUP_DIR |
| mkdir -p $LOG_DIR |
| mkdir -p ./monitoring |
| } |
|
|
| |
| build_image() { |
| log_info "Building Docker image..." |
| docker build -t $DOCKER_IMAGE . |
| log_info "Docker image built successfully" |
| } |
|
|
| |
| run_tests() { |
| log_info "Running tests..." |
| |
| |
| docker run --rm -v $(pwd):/app -w /app $DOCKER_IMAGE pytest tests/ -v |
| |
| if [ $? -eq 0 ]; then |
| log_info "All tests passed" |
| else |
| log_error "Tests failed" |
| exit 1 |
| fi |
| } |
|
|
| |
| backup_deployment() { |
| if [ -f "docker-compose.yml" ]; then |
| log_info "Creating backup..." |
| TIMESTAMP=$(date +%Y%m%d_%H%M%S) |
| cp docker-compose.yml $BACKUP_DIR/docker-compose_$TIMESTAMP.yml |
| log_info "Backup created: $BACKUP_DIR/docker-compose_$TIMESTAMP.yml" |
| fi |
| } |
|
|
| |
| deploy() { |
| local environment=${1:-production} |
| |
| log_info "Deploying to $environment environment..." |
| |
| |
| case $environment in |
| "production") |
| export MODEL_PATH="./results" |
| export WORKERS=4 |
| ;; |
| "staging") |
| export MODEL_PATH="distilbert-base-uncased-finetuned-sst-2-english" |
| export WORKERS=2 |
| ;; |
| "development") |
| export MODEL_PATH="distilbert-base-uncased-finetuned-sst-2-english" |
| export WORKERS=1 |
| ;; |
| *) |
| log_error "Unknown environment: $environment" |
| exit 1 |
| ;; |
| esac |
| |
| |
| log_info "Stopping existing containers..." |
| docker-compose down || true |
| |
| |
| log_info "Starting new deployment..." |
| docker-compose up -d |
| |
| |
| log_info "Waiting for health check..." |
| sleep 30 |
| |
| |
| for i in {1..10}; do |
| if curl -f http://localhost:8000/health &> /dev/null; then |
| log_info "Deployment successful! API is responding" |
| return 0 |
| fi |
| log_warn "Attempt $i: API not responding yet, waiting..." |
| sleep 10 |
| done |
| |
| log_error "Deployment failed: API not responding after 100 seconds" |
| docker-compose logs |
| exit 1 |
| } |
|
|
| |
| rollback() { |
| log_warn "Rolling back deployment..." |
| |
| |
| LATEST_BACKUP=$(ls -t $BACKUP_DIR/docker-compose_*.yml 2>/dev/null | head -n1) |
| |
| if [ -z "$LATEST_BACKUP" ]; then |
| log_error "No backup found for rollback" |
| exit 1 |
| fi |
| |
| log_info "Rolling back to: $LATEST_BACKUP" |
| |
| |
| docker-compose down |
| |
| |
| cp $LATEST_BACKUP docker-compose.yml |
| |
| |
| docker-compose up -d |
| |
| log_info "Rollback completed" |
| } |
|
|
| |
| show_status() { |
| log_info "Deployment Status:" |
| docker-compose ps |
| |
| echo "" |
| log_info "API Health:" |
| curl -s http://localhost:8000/health | python -m json.tool || echo "API not responding" |
| |
| echo "" |
| log_info "Container Logs (last 20 lines):" |
| docker-compose logs --tail=20 |
| } |
|
|
| |
| monitor() { |
| log_info "Monitoring deployment..." |
| docker-compose logs -f |
| } |
|
|
| |
| update_model() { |
| local model_path=$1 |
| |
| if [ -z "$model_path" ]; then |
| log_error "Model path required" |
| exit 1 |
| fi |
| |
| log_info "Updating model to: $model_path" |
| |
| |
| export MODEL_PATH=$model_path |
| |
| |
| docker-compose restart transformer-api |
| |
| log_info "Model updated successfully" |
| } |
|
|
| |
| cleanup() { |
| log_info "Cleaning up old resources..." |
| |
| |
| docker image prune -f |
| |
| |
| ls -t $BACKUP_DIR/docker-compose_*.yml 2>/dev/null | tail -n +11 | xargs rm -f |
| |
| |
| find $LOG_DIR -name "*.log" -mtime +7 -delete 2>/dev/null || true |
| |
| log_info "Cleanup completed" |
| } |
|
|
| |
| main() { |
| local command=${1:-deploy} |
| local environment=${2:-production} |
| |
| case $command in |
| "deploy") |
| check_dependencies |
| setup_directories |
| build_image |
| run_tests |
| backup_deployment |
| deploy $environment |
| ;; |
| "rollback") |
| rollback |
| ;; |
| "status") |
| show_status |
| ;; |
| "monitor") |
| monitor |
| ;; |
| "update-model") |
| update_model $2 |
| ;; |
| "cleanup") |
| cleanup |
| ;; |
| "build") |
| build_image |
| ;; |
| "test") |
| run_tests |
| ;; |
| *) |
| echo "Usage: $0 {deploy|rollback|status|monitor|update-model|cleanup|build|test} [environment|model_path]" |
| echo "" |
| echo "Commands:" |
| echo " deploy [env] - Deploy application (env: production|staging|development)" |
| echo " rollback - Rollback to previous deployment" |
| echo " status - Show deployment status" |
| echo " monitor - Monitor deployment logs" |
| echo " update-model - Update model path" |
| echo " cleanup - Clean up old resources" |
| echo " build - Build Docker image only" |
| echo " test - Run tests only" |
| echo "" |
| echo "Examples:" |
| echo " $0 deploy production" |
| echo " $0 update-model ./new-model" |
| echo " $0 status" |
| exit 1 |
| ;; |
| esac |
| } |
|
|
| |
| main "$@" |