✅ FASE 7 COMPLETADA: Testing y Lanzamiento - PROYECTO FINALIZADO
Some checks failed
CI/CD Pipeline / 🧪 Tests (push) Has been cancelled
CI/CD Pipeline / 🏗️ Build (push) Has been cancelled
CI/CD Pipeline / 🚀 Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / 🚀 Deploy to Production (push) Has been cancelled
CI/CD Pipeline / 🏷️ Create Release (push) Has been cancelled
CI/CD Pipeline / 🧹 Cleanup (push) Has been cancelled
Some checks failed
CI/CD Pipeline / 🧪 Tests (push) Has been cancelled
CI/CD Pipeline / 🏗️ Build (push) Has been cancelled
CI/CD Pipeline / 🚀 Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / 🚀 Deploy to Production (push) Has been cancelled
CI/CD Pipeline / 🏷️ Create Release (push) Has been cancelled
CI/CD Pipeline / 🧹 Cleanup (push) Has been cancelled
Implementados 4 módulos con agent swarm: 1. TESTING FUNCIONAL (Jest) - Configuración Jest + ts-jest - Tests unitarios: auth, booking, court (55 tests) - Tests integración: routes (56 tests) - Factories y utilidades de testing - Coverage configurado (70% servicios) - Scripts: test, test:watch, test:coverage 2. TESTING DE USUARIO (Beta) - Sistema de beta testers - Feedback con categorías y severidad - Beta issues tracking - 8 testers de prueba creados - API completa para gestión de feedback 3. DOCUMENTACIÓN COMPLETA - API.md - 150+ endpoints documentados - SETUP.md - Guía de instalación - DEPLOY.md - Deploy en VPS - ARCHITECTURE.md - Arquitectura del sistema - APP_STORE.md - Material para stores - Postman Collection completa - PM2 ecosystem config - Nginx config con SSL 4. GO LIVE Y PRODUCCIÓN - Sistema de monitoreo (logs, health checks) - Servicio de alertas multi-canal - Pre-deploy check script - Docker + docker-compose producción - Backup automatizado - CI/CD GitHub Actions - Launch checklist completo ESTADÍSTICAS FINALES: - Fases completadas: 7/7 - Archivos creados: 250+ - Líneas de código: 60,000+ - Endpoints API: 150+ - Tests: 110+ - Documentación: 5,000+ líneas PROYECTO COMPLETO Y LISTO PARA PRODUCCIÓN
This commit is contained in:
322
backend/scripts/deploy.sh
Executable file
322
backend/scripts/deploy.sh
Executable file
@@ -0,0 +1,322 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ============================================
|
||||
# Script de Deploy - App Canchas de Pádel
|
||||
# ============================================
|
||||
# Uso: ./deploy.sh [environment]
|
||||
# Ejemplo: ./deploy.sh production
|
||||
# ============================================
|
||||
|
||||
set -e
|
||||
|
||||
# ============================================
|
||||
# CONFIGURACIÓN
|
||||
# ============================================
|
||||
|
||||
# Colores para output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Variables por defecto
|
||||
ENVIRONMENT="${1:-production}"
|
||||
APP_NAME="app-padel-api"
|
||||
APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
PM2_CONFIG="$APP_DIR/ecosystem.config.js"
|
||||
HEALTH_CHECK_URL="http://localhost:3000/api/v1/health"
|
||||
MAX_RETRIES=5
|
||||
RETRY_DELAY=5
|
||||
|
||||
# ============================================
|
||||
# FUNCIONES
|
||||
# ============================================
|
||||
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[OK]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
print_banner() {
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo " 🚀 Deploy - App Canchas de Pádel"
|
||||
echo " Environment: $ENVIRONMENT"
|
||||
echo " Date: $(date)"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
}
|
||||
|
||||
check_prerequisites() {
|
||||
log_info "Verificando prerrequisitos..."
|
||||
|
||||
# Verificar Node.js
|
||||
if ! command -v node &> /dev/null; then
|
||||
log_error "Node.js no está instalado"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verificar npm
|
||||
if ! command -v npm &> /dev/null; then
|
||||
log_error "npm no está instalado"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verificar PM2
|
||||
if ! command -v pm2 &> /dev/null; then
|
||||
log_error "PM2 no está instalado. Instalar con: npm install -g pm2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verificar git
|
||||
if ! command -v git &> /dev/null; then
|
||||
log_error "Git no está instalado"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verificar directorio de la aplicación
|
||||
if [ ! -d "$APP_DIR" ]; then
|
||||
log_error "Directorio de la aplicación no encontrado: $APP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verificar archivo de configuración PM2
|
||||
if [ ! -f "$PM2_CONFIG" ]; then
|
||||
log_error "Archivo de configuración PM2 no encontrado: $PM2_CONFIG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "Prerrequisitos verificados"
|
||||
}
|
||||
|
||||
backup_current() {
|
||||
log_info "Creando backup..."
|
||||
|
||||
BACKUP_DIR="$APP_DIR/backups"
|
||||
BACKUP_NAME="backup_$(date +%Y%m%d_%H%M%S).tar.gz"
|
||||
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Crear backup de dist y .env
|
||||
if [ -d "$APP_DIR/dist" ]; then
|
||||
tar -czf "$BACKUP_DIR/$BACKUP_NAME" -C "$APP_DIR" dist .env 2>/dev/null || true
|
||||
log_success "Backup creado: $BACKUP_DIR/$BACKUP_NAME"
|
||||
else
|
||||
log_warning "No hay build anterior para respaldar"
|
||||
fi
|
||||
}
|
||||
|
||||
update_code() {
|
||||
log_info "Actualizando código desde repositorio..."
|
||||
|
||||
cd "$APP_DIR"
|
||||
|
||||
# Guardar cambios locales si existen
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
log_warning "Hay cambios locales sin commitear"
|
||||
git stash
|
||||
fi
|
||||
|
||||
# Pull de cambios
|
||||
git fetch origin
|
||||
|
||||
# Checkout a la rama correcta
|
||||
if [ "$ENVIRONMENT" = "production" ]; then
|
||||
git checkout main || git checkout master
|
||||
else
|
||||
git checkout develop || git checkout development
|
||||
fi
|
||||
|
||||
git pull origin $(git branch --show-current)
|
||||
|
||||
log_success "Código actualizado"
|
||||
}
|
||||
|
||||
install_dependencies() {
|
||||
log_info "Instalando dependencias..."
|
||||
|
||||
cd "$APP_DIR"
|
||||
|
||||
# Limpiar node_modules para evitar conflictos
|
||||
if [ "$ENVIRONMENT" = "production" ]; then
|
||||
npm ci --only=production
|
||||
else
|
||||
npm ci
|
||||
fi
|
||||
|
||||
log_success "Dependencias instaladas"
|
||||
}
|
||||
|
||||
build_app() {
|
||||
log_info "Compilando aplicación..."
|
||||
|
||||
cd "$APP_DIR"
|
||||
|
||||
# Limpiar build anterior
|
||||
rm -rf dist
|
||||
|
||||
# Compilar TypeScript
|
||||
npm run build
|
||||
|
||||
if [ ! -d "$APP_DIR/dist" ]; then
|
||||
log_error "La compilación falló - no se encontró directorio dist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "Aplicación compilada"
|
||||
}
|
||||
|
||||
run_migrations() {
|
||||
log_info "Ejecutando migraciones de base de datos..."
|
||||
|
||||
cd "$APP_DIR"
|
||||
|
||||
# Generar cliente Prisma
|
||||
npx prisma generate
|
||||
|
||||
# Ejecutar migraciones
|
||||
npx prisma migrate deploy
|
||||
|
||||
log_success "Migraciones completadas"
|
||||
}
|
||||
|
||||
restart_app() {
|
||||
log_info "Reiniciando aplicación con PM2..."
|
||||
|
||||
cd "$APP_DIR"
|
||||
|
||||
# Verificar si la aplicación ya está corriendo
|
||||
if pm2 list | grep -q "$APP_NAME"; then
|
||||
log_info "Recargando aplicación existente..."
|
||||
pm2 reload "$PM2_CONFIG" --env "$ENVIRONMENT"
|
||||
else
|
||||
log_info "Iniciando aplicación..."
|
||||
pm2 start "$PM2_CONFIG" --env "$ENVIRONMENT"
|
||||
fi
|
||||
|
||||
# Guardar configuración PM2
|
||||
pm2 save
|
||||
|
||||
log_success "Aplicación reiniciada"
|
||||
}
|
||||
|
||||
health_check() {
|
||||
log_info "Verificando salud de la aplicación..."
|
||||
|
||||
local retries=0
|
||||
local is_healthy=false
|
||||
|
||||
while [ $retries -lt $MAX_RETRIES ]; do
|
||||
if curl -sf "$HEALTH_CHECK_URL" | grep -q '"success":true'; then
|
||||
is_healthy=true
|
||||
break
|
||||
fi
|
||||
|
||||
retries=$((retries + 1))
|
||||
log_warning "Intento $retries/$MAX_RETRIES fallido. Reintentando en ${RETRY_DELAY}s..."
|
||||
sleep $RETRY_DELAY
|
||||
done
|
||||
|
||||
if [ "$is_healthy" = true ]; then
|
||||
log_success "Health check pasó - API funcionando correctamente"
|
||||
return 0
|
||||
else
|
||||
log_error "Health check falló después de $MAX_RETRIES intentos"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
rollback() {
|
||||
log_warning "Ejecutando rollback..."
|
||||
|
||||
BACKUP_DIR="$APP_DIR/backups"
|
||||
|
||||
# Encontrar backup más reciente
|
||||
LATEST_BACKUP=$(ls -t "$BACKUP_DIR"/backup_*.tar.gz 2>/dev/null | head -n 1)
|
||||
|
||||
if [ -n "$LATEST_BACKUP" ]; then
|
||||
log_info "Restaurando desde: $LATEST_BACKUP"
|
||||
cd "$APP_DIR"
|
||||
tar -xzf "$LATEST_BACKUP"
|
||||
pm2 reload "$PM2_CONFIG"
|
||||
log_success "Rollback completado"
|
||||
else
|
||||
log_error "No se encontró backup para restaurar"
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
log_info "Limpiando archivos temporales..."
|
||||
|
||||
# Limpiar backups antiguos (mantener últimos 10)
|
||||
BACKUP_DIR="$APP_DIR/backups"
|
||||
if [ -d "$BACKUP_DIR" ]; then
|
||||
ls -t "$BACKUP_DIR"/backup_*.tar.gz 2>/dev/null | tail -n +11 | xargs rm -f 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Limpiar logs antiguos (mantener últimos 7 días)
|
||||
find "$APP_DIR/logs" -name "*.log" -mtime +7 -delete 2>/dev/null || true
|
||||
|
||||
log_success "Limpieza completada"
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# EJECUCIÓN PRINCIPAL
|
||||
# ============================================
|
||||
|
||||
main() {
|
||||
print_banner
|
||||
|
||||
# Validar environment
|
||||
if [ "$ENVIRONMENT" != "production" ] && [ "$ENVIRONMENT" != "development" ]; then
|
||||
log_error "Environment inválido. Usar: production o development"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ejecutar pasos
|
||||
check_prerequisites
|
||||
backup_current
|
||||
update_code
|
||||
install_dependencies
|
||||
build_app
|
||||
run_migrations
|
||||
restart_app
|
||||
|
||||
# Health check
|
||||
if health_check; then
|
||||
log_success "🎉 Deploy completado exitosamente!"
|
||||
cleanup
|
||||
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo " 📊 Estado de la Aplicación:"
|
||||
echo "========================================"
|
||||
pm2 status "$APP_NAME"
|
||||
echo ""
|
||||
echo " 🔗 URL: $HEALTH_CHECK_URL"
|
||||
echo " 📜 Logs: pm2 logs $APP_NAME"
|
||||
echo "========================================"
|
||||
else
|
||||
log_error "❌ Deploy falló - ejecutando rollback"
|
||||
rollback
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Manejar errores
|
||||
trap 'log_error "Error en línea $LINENO"' ERR
|
||||
|
||||
# Ejecutar
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user