File size: 14,096 Bytes
5b6f681
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
#!/bin/bash

# πŸš€ Script de Deployment Completo para Transformer Web Interface
# Autor: AI Assistant
# VersiΓ³n: 1.0

set -e  # Salir en caso de error

# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# ConfiguraciΓ³n por defecto
PROJECT_NAME="transformer-sentiment"
WEB_PORT=8080
API_PORT=8000
PYTHON_ENV="venv"
BROWSER_OPEN=true
KILL_EXISTING=true

# Funciones de utilidad
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

print_banner() {
    echo -e "${BLUE}"
    echo "╔══════════════════════════════════════════════════════════════════╗"
    echo "β•‘                πŸ€– TRANSFORMER WEB DEPLOYMENT 🌐                 β•‘"
    echo "β•‘                                                                  β•‘"
    echo "β•‘  Desplegando interfaz web completa para anΓ‘lisis de sentimientos β•‘"
    echo "β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•"
    echo -e "${NC}"
}

show_help() {
    echo "Uso: $0 [OPCIONES]"
    echo ""
    echo "Opciones:"
    echo "  -w, --web-port PORT     Puerto para la interfaz web (default: 8080)"
    echo "  -a, --api-port PORT     Puerto para la API (default: 8000)"
    echo "  -e, --env ENV_NAME      Nombre del entorno virtual (default: venv)"
    echo "  --no-browser           No abrir browser automΓ‘ticamente"
    echo "  --no-kill              No matar procesos existentes"
    echo "  --api-only             Solo iniciar API"
    echo "  --web-only             Solo iniciar interfaz web"
    echo "  --full                 Deployment completo (API + Web + Tests)"
    echo "  --docker               Usar Docker para deployment"
    echo "  --production           ConfiguraciΓ³n de producciΓ³n"
    echo "  -h, --help             Mostrar esta ayuda"
    echo ""
    echo "Ejemplos:"
    echo "  $0                     # Deployment estΓ‘ndar"
    echo "  $0 --full             # Deployment completo con tests"
    echo "  $0 --web-only -w 3000 # Solo web en puerto 3000"
    echo "  $0 --production       # Deployment de producciΓ³n"
}

check_dependencies() {
    log_info "Verificando dependencias..."
    
    # Python
    if ! command -v python3 &> /dev/null; then
        log_error "Python3 no estΓ‘ instalado"
        exit 1
    fi
    
    # pip
    if ! command -v pip3 &> /dev/null; then
        log_error "pip3 no estΓ‘ instalado"
        exit 1
    fi
    
    log_success "Dependencias bΓ‘sicas verificadas"
}

check_ports() {
    log_info "Verificando disponibilidad de puertos..."
    
    if lsof -Pi :$WEB_PORT -sTCP:LISTEN -t >/dev/null 2>&1; then
        if [ "$KILL_EXISTING" = true ]; then
            log_warning "Puerto $WEB_PORT ocupado. Matando proceso..."
            lsof -ti:$WEB_PORT | xargs kill -9 2>/dev/null || true
        else
            log_error "Puerto $WEB_PORT ya estΓ‘ en uso"
            exit 1
        fi
    fi
    
    if lsof -Pi :$API_PORT -sTCP:LISTEN -t >/dev/null 2>&1; then
        if [ "$KILL_EXISTING" = true ]; then
            log_warning "Puerto $API_PORT ocupado. Matando proceso..."
            lsof -ti:$API_PORT | xargs kill -9 2>/dev/null || true
        else
            log_error "Puerto $API_PORT ya estΓ‘ en uso"
            exit 1
        fi
    fi
    
    log_success "Puertos disponibles"
}

setup_environment() {
    log_info "Configurando entorno Python..."
    
    # Activar entorno virtual si existe
    if [ -d "$PYTHON_ENV" ]; then
        source $PYTHON_ENV/bin/activate
        log_success "Entorno virtual activado: $PYTHON_ENV"
    else
        log_warning "Entorno virtual no encontrado: $PYTHON_ENV"
        log_info "Creando nuevo entorno virtual..."
        python3 -m venv $PYTHON_ENV
        source $PYTHON_ENV/bin/activate
        log_success "Nuevo entorno virtual creado y activado"
    fi
    
    # Instalar/actualizar dependencias
    if [ -f "requirements.txt" ]; then
        log_info "Instalando dependencias..."
        pip install -r requirements.txt
        log_success "Dependencias instaladas"
    else
        log_warning "requirements.txt no encontrado"
    fi
}

start_api() {
    log_info "Iniciando API en puerto $API_PORT..."
    
    # Verificar que el mΓ³dulo API existe
    if [ ! -f "src/api.py" ]; then
        log_error "API no encontrada en src/api.py"
        return 1
    fi
    
    # Iniciar API en background
    nohup python -m src.api --host 127.0.0.1 --port $API_PORT > api.log 2>&1 &
    API_PID=$!
    echo $API_PID > api.pid
    
    # Esperar a que la API estΓ© lista
    log_info "Esperando a que la API estΓ© lista..."
    for i in {1..30}; do
        if curl -s http://127.0.0.1:$API_PORT/health > /dev/null 2>&1; then
            log_success "API iniciada correctamente (PID: $API_PID)"
            return 0
        fi
        sleep 1
    done
    
    log_error "La API no pudo iniciarse en 30 segundos"
    return 1
}

start_web() {
    log_info "Iniciando interfaz web en puerto $WEB_PORT..."
    
    # Verificar que los archivos web existen
    if [ ! -f "web/index.html" ]; then
        log_error "Interfaz web no encontrada en web/index.html"
        return 1
    fi
    
    # Hacer ejecutable el servidor si no lo es
    if [ -f "serve_web.py" ]; then
        chmod +x serve_web.py
        
        # Iniciar servidor web personalizado
        if [ "$BROWSER_OPEN" = true ]; then
            nohup python serve_web.py --port $WEB_PORT > web.log 2>&1 &
        else
            nohup python serve_web.py --port $WEB_PORT --no-browser > web.log 2>&1 &
        fi
    else
        # Usar servidor HTTP bΓ‘sico de Python
        cd web
        if [ "$BROWSER_OPEN" = true ]; then
            nohup python -m http.server $WEB_PORT > ../web.log 2>&1 &
            open http://localhost:$WEB_PORT 2>/dev/null || true
        else
            nohup python -m http.server $WEB_PORT > ../web.log 2>&1 &
        fi
        cd ..
    fi
    
    WEB_PID=$!
    echo $WEB_PID > web.pid
    
    # Verificar que el servidor web estΓ‘ funcionando
    sleep 2
    if curl -s http://localhost:$WEB_PORT > /dev/null 2>&1; then
        log_success "Interfaz web iniciada correctamente (PID: $WEB_PID)"
        return 0
    else
        log_error "La interfaz web no pudo iniciarse"
        return 1
    fi
}

run_tests() {
    log_info "Ejecutando tests del proyecto..."
    
    # Tests de API
    if [ -d "tests" ]; then
        python -m pytest tests/ -v
    else
        log_warning "Directorio de tests no encontrado"
    fi
    
    # Test de health check
    if curl -s http://127.0.0.1:$API_PORT/health | grep -q "healthy"; then
        log_success "API health check: βœ… PASS"
    else
        log_error "API health check: ❌ FAIL"
    fi
    
    # Test de interfaz web
    if curl -s http://localhost:$WEB_PORT | grep -q "Transformer"; then
        log_success "Web interface check: βœ… PASS"
    else
        log_error "Web interface check: ❌ FAIL"
    fi
}

show_status() {
    echo ""
    echo -e "${GREEN}╔══════════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${GREEN}β•‘                    πŸŽ‰ DEPLOYMENT COMPLETADO πŸŽ‰                  β•‘${NC}"
    echo -e "${GREEN}β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•${NC}"
    echo ""
    echo -e "${BLUE}πŸ“Š Estado de servicios:${NC}"
    
    # Verificar API
    if curl -s http://127.0.0.1:$API_PORT/health > /dev/null 2>&1; then
        echo -e "  🟒 API: ${GREEN}RUNNING${NC} en http://127.0.0.1:$API_PORT"
        echo -e "     πŸ“š Docs: http://127.0.0.1:$API_PORT/docs"
    else
        echo -e "  πŸ”΄ API: ${RED}DOWN${NC}"
    fi
    
    # Verificar Web
    if curl -s http://localhost:$WEB_PORT > /dev/null 2>&1; then
        echo -e "  🟒 Web: ${GREEN}RUNNING${NC} en http://localhost:$WEB_PORT"
    else
        echo -e "  πŸ”΄ Web: ${RED}DOWN${NC}"
    fi
    
    echo ""
    echo -e "${BLUE}πŸ”§ Comandos ΓΊtiles:${NC}"
    echo -e "  ${YELLOW}Ver logs API:${NC}     tail -f api.log"
    echo -e "  ${YELLOW}Ver logs Web:${NC}     tail -f web.log"
    echo -e "  ${YELLOW}Parar servicios:${NC}  $0 --stop"
    echo -e "  ${YELLOW}Reiniciar:${NC}        $0 --restart"
    echo ""
    
    if [ "$BROWSER_OPEN" = true ]; then
        echo -e "${GREEN}🌐 Abriendo navegador...${NC}"
        if command -v open &> /dev/null; then
            open http://localhost:$WEB_PORT
        elif command -v xdg-open &> /dev/null; then
            xdg-open http://localhost:$WEB_PORT
        fi
    fi
}

stop_services() {
    log_info "Deteniendo servicios..."
    
    # Parar API
    if [ -f "api.pid" ]; then
        API_PID=$(cat api.pid)
        kill $API_PID 2>/dev/null || true
        rm api.pid
        log_success "API detenida"
    fi
    
    # Parar Web
    if [ -f "web.pid" ]; then
        WEB_PID=$(cat web.pid)
        kill $WEB_PID 2>/dev/null || true
        rm web.pid
        log_success "Interfaz web detenida"
    fi
    
    # Limpiar puertos por si acaso
    lsof -ti:$API_PORT | xargs kill -9 2>/dev/null || true
    lsof -ti:$WEB_PORT | xargs kill -9 2>/dev/null || true
}

create_production_config() {
    log_info "Creando configuraciΓ³n de producciΓ³n..."
    
    # Nginx config
    cat > nginx.conf << EOF
server {
    listen 80;
    server_name localhost;
    
    # Interfaz web
    location / {
        root $(pwd)/web;
        index index.html;
        try_files \$uri \$uri/ /index.html;
    }
    
    # API proxy
    location /api/ {
        proxy_pass http://127.0.0.1:$API_PORT/;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
    }
}
EOF
    
    # Docker compose para producciΓ³n
    cat > docker-compose.prod.yml << EOF
version: '3.8'
services:
  api:
    build: .
    ports:
      - "$API_PORT:$API_PORT"
    environment:
      - ENV=production
    restart: unless-stopped
    
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./web:/usr/share/nginx/html
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - api
    restart: unless-stopped
EOF
    
    log_success "ConfiguraciΓ³n de producciΓ³n creada"
}

docker_deployment() {
    log_info "Iniciando deployment con Docker..."
    
    if ! command -v docker &> /dev/null; then
        log_error "Docker no estΓ‘ instalado"
        exit 1
    fi
    
    # Build imagen
    docker build -t $PROJECT_NAME .
    
    # Run con docker-compose
    if [ -f "docker-compose.yml" ]; then
        docker-compose up -d
        log_success "Servicios iniciados con Docker"
    else
        log_error "docker-compose.yml no encontrado"
        exit 1
    fi
}

# Procesar argumentos
while [[ $# -gt 0 ]]; do
    case $1 in
        -w|--web-port)
            WEB_PORT="$2"
            shift 2
            ;;
        -a|--api-port)
            API_PORT="$2"
            shift 2
            ;;
        -e|--env)
            PYTHON_ENV="$2"
            shift 2
            ;;
        --no-browser)
            BROWSER_OPEN=false
            shift
            ;;
        --no-kill)
            KILL_EXISTING=false
            shift
            ;;
        --api-only)
            MODE="api-only"
            shift
            ;;
        --web-only)
            MODE="web-only"
            shift
            ;;
        --full)
            MODE="full"
            shift
            ;;
        --docker)
            MODE="docker"
            shift
            ;;
        --production)
            MODE="production"
            shift
            ;;
        --stop)
            stop_services
            exit 0
            ;;
        --restart)
            stop_services
            sleep 2
            # Continuar con el deployment normal
            shift
            ;;
        -h|--help)
            show_help
            exit 0
            ;;
        *)
            log_error "OpciΓ³n desconocida: $1"
            show_help
            exit 1
            ;;
    esac
done

# Banner de inicio
print_banner

# Verificaciones iniciales
check_dependencies
check_ports

# Deployment segΓΊn modo
case ${MODE:-"standard"} in
    "api-only")
        setup_environment
        start_api
        ;;
    "web-only")
        start_web
        ;;
    "docker")
        docker_deployment
        ;;
    "production")
        create_production_config
        setup_environment
        start_api
        start_web
        ;;
    "full")
        setup_environment
        start_api
        start_web
        run_tests
        ;;
    *)
        setup_environment
        start_api
        start_web
        ;;
esac

# Mostrar estado final
show_status

# Cleanup en exit
trap 'log_info "Limpiando..."; stop_services' EXIT

# Mantener script corriendo
log_info "Presiona Ctrl+C para detener todos los servicios..."
while true; do
    sleep 10
    
    # Verificar que los servicios siguen corriendo
    if [ "${MODE:-"standard"}" != "web-only" ]; then
        if ! curl -s http://127.0.0.1:$API_PORT/health > /dev/null 2>&1; then
            log_error "API caΓ­da. Reiniciando..."
            start_api
        fi
    fi
    
    if [ "${MODE:-"standard"}" != "api-only" ]; then
        if ! curl -s http://localhost:$WEB_PORT > /dev/null 2>&1; then
            log_error "Interfaz web caΓ­da. Reiniciando..."
            start_web
        fi
    fi
done