486 lines
13 KiB
Bash
486 lines
13 KiB
Bash
#!/bin/bash
|
|
# ============================================
|
|
# Sistema de ADAN - Script de Actualizacion
|
|
# ============================================
|
|
# Actualiza la aplicacion a la ultima version
|
|
#
|
|
# Uso: ./update.sh [--branch BRANCH] [--force] [--no-backup]
|
|
#
|
|
# Opciones:
|
|
# --branch Branch a usar (default: main)
|
|
# --force Forzar actualizacion (descartar cambios locales)
|
|
# --no-backup No crear backup antes de actualizar
|
|
# --backend Solo actualizar backend
|
|
# --frontend Solo actualizar frontend
|
|
# ============================================
|
|
|
|
set -e
|
|
set -o pipefail
|
|
|
|
# ---------------------------------------------
|
|
# Colores
|
|
# ---------------------------------------------
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
# ---------------------------------------------
|
|
# Variables
|
|
# ---------------------------------------------
|
|
INSTALL_DIR="${INSTALL_DIR:-/opt/adan}"
|
|
REPO_BRANCH="${REPO_BRANCH:-main}"
|
|
BACKUP_BEFORE_UPDATE=true
|
|
FORCE_UPDATE=false
|
|
UPDATE_BACKEND=true
|
|
UPDATE_FRONTEND=true
|
|
|
|
# Cargar variables de entorno
|
|
if [[ -f "$INSTALL_DIR/.env" ]]; then
|
|
export $(grep -v '^#' "$INSTALL_DIR/.env" | xargs)
|
|
fi
|
|
|
|
# ---------------------------------------------
|
|
# Funciones
|
|
# ---------------------------------------------
|
|
log_info() {
|
|
echo -e "${BLUE}[$(date '+%H:%M:%S')] [INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[$(date '+%H:%M:%S')] [OK]${NC} $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[$(date '+%H:%M:%S')] [WARN]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[$(date '+%H:%M:%S')] [ERROR]${NC} $1"
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Parsear argumentos
|
|
# ---------------------------------------------
|
|
parse_args() {
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--branch)
|
|
REPO_BRANCH="$2"
|
|
shift 2
|
|
;;
|
|
--force)
|
|
FORCE_UPDATE=true
|
|
shift
|
|
;;
|
|
--no-backup)
|
|
BACKUP_BEFORE_UPDATE=false
|
|
shift
|
|
;;
|
|
--backend)
|
|
UPDATE_FRONTEND=false
|
|
shift
|
|
;;
|
|
--frontend)
|
|
UPDATE_BACKEND=false
|
|
shift
|
|
;;
|
|
--help|-h)
|
|
echo "Uso: $0 [--branch BRANCH] [--force] [--no-backup]"
|
|
echo ""
|
|
echo "Opciones:"
|
|
echo " --branch Branch a usar (default: main)"
|
|
echo " --force Forzar (descartar cambios locales)"
|
|
echo " --no-backup No crear backup antes de actualizar"
|
|
echo " --backend Solo actualizar backend"
|
|
echo " --frontend Solo actualizar frontend"
|
|
exit 0
|
|
;;
|
|
*)
|
|
log_error "Opcion desconocida: $1"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Verificar requisitos
|
|
# ---------------------------------------------
|
|
check_requirements() {
|
|
log_info "Verificando requisitos..."
|
|
|
|
# Verificar directorio
|
|
if [[ ! -d "$INSTALL_DIR" ]]; then
|
|
log_error "Directorio de instalacion no encontrado: $INSTALL_DIR"
|
|
exit 1
|
|
fi
|
|
|
|
# Verificar git
|
|
if [[ ! -d "$INSTALL_DIR/.git" ]]; then
|
|
log_error "No es un repositorio git"
|
|
exit 1
|
|
fi
|
|
|
|
# Verificar conexion
|
|
if ! ping -c 1 github.com &> /dev/null; then
|
|
log_error "Sin conexion a internet"
|
|
exit 1
|
|
fi
|
|
|
|
log_success "Requisitos OK"
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Crear backup
|
|
# ---------------------------------------------
|
|
create_backup() {
|
|
if [[ "$BACKUP_BEFORE_UPDATE" != "true" ]]; then
|
|
log_warn "Saltando backup (--no-backup)"
|
|
return
|
|
fi
|
|
|
|
log_info "Creando backup antes de actualizar..."
|
|
|
|
if [[ -f "$INSTALL_DIR/deploy/scripts/backup.sh" ]]; then
|
|
bash "$INSTALL_DIR/deploy/scripts/backup.sh" || log_warn "Backup fallo, continuando..."
|
|
else
|
|
log_warn "Script de backup no encontrado"
|
|
fi
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Obtener version actual
|
|
# ---------------------------------------------
|
|
get_current_version() {
|
|
cd "$INSTALL_DIR"
|
|
|
|
# Intentar obtener version de git tag
|
|
local version=$(git describe --tags --always 2>/dev/null || echo "unknown")
|
|
|
|
# O del commit
|
|
local commit=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
|
|
|
echo "${version} (${commit})"
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Verificar cambios locales
|
|
# ---------------------------------------------
|
|
check_local_changes() {
|
|
cd "$INSTALL_DIR"
|
|
|
|
if [[ -n $(git status --porcelain) ]]; then
|
|
if [[ "$FORCE_UPDATE" == "true" ]]; then
|
|
log_warn "Descartando cambios locales..."
|
|
git reset --hard HEAD
|
|
git clean -fd
|
|
else
|
|
log_error "Hay cambios locales sin commitear"
|
|
log_error "Usa --force para descartarlos"
|
|
git status --short
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Actualizar codigo
|
|
# ---------------------------------------------
|
|
update_code() {
|
|
log_info "Actualizando codigo desde repositorio..."
|
|
|
|
cd "$INSTALL_DIR"
|
|
|
|
# Guardar version actual
|
|
local old_version=$(get_current_version)
|
|
|
|
# Fetch
|
|
log_info "Obteniendo cambios..."
|
|
git fetch origin
|
|
|
|
# Verificar si hay actualizaciones
|
|
local local_hash=$(git rev-parse HEAD)
|
|
local remote_hash=$(git rev-parse origin/${REPO_BRANCH})
|
|
|
|
if [[ "$local_hash" == "$remote_hash" ]]; then
|
|
log_success "Ya estas en la version mas reciente"
|
|
return 0
|
|
fi
|
|
|
|
# Mostrar cambios pendientes
|
|
log_info "Cambios disponibles:"
|
|
git log --oneline HEAD..origin/${REPO_BRANCH} | head -10
|
|
|
|
# Actualizar
|
|
log_info "Aplicando cambios..."
|
|
git reset --hard origin/${REPO_BRANCH}
|
|
|
|
local new_version=$(get_current_version)
|
|
|
|
log_success "Codigo actualizado: $old_version -> $new_version"
|
|
|
|
return 1 # Indica que hubo cambios
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Actualizar backend
|
|
# ---------------------------------------------
|
|
update_backend() {
|
|
if [[ "$UPDATE_BACKEND" != "true" ]]; then
|
|
log_info "Saltando actualizacion de backend"
|
|
return
|
|
fi
|
|
|
|
log_info "Actualizando backend..."
|
|
|
|
cd "$INSTALL_DIR/backend"
|
|
|
|
# Activar entorno virtual
|
|
source venv/bin/activate
|
|
|
|
# Actualizar dependencias
|
|
log_info "Instalando dependencias Python..."
|
|
|
|
if [[ -f "requirements.txt" ]]; then
|
|
pip install -r requirements.txt -q --upgrade
|
|
elif [[ -f "pyproject.toml" ]]; then
|
|
pip install -e . -q --upgrade
|
|
fi
|
|
|
|
# Ejecutar migraciones
|
|
log_info "Ejecutando migraciones..."
|
|
|
|
if [[ -d "alembic" ]]; then
|
|
alembic upgrade head 2>/dev/null || log_warn "Sin migraciones pendientes"
|
|
fi
|
|
|
|
deactivate
|
|
|
|
log_success "Backend actualizado"
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Actualizar frontend
|
|
# ---------------------------------------------
|
|
update_frontend() {
|
|
if [[ "$UPDATE_FRONTEND" != "true" ]]; then
|
|
log_info "Saltando actualizacion de frontend"
|
|
return
|
|
fi
|
|
|
|
log_info "Actualizando frontend..."
|
|
|
|
cd "$INSTALL_DIR/frontend"
|
|
|
|
# Verificar package.json
|
|
if [[ ! -f "package.json" ]]; then
|
|
log_warn "No hay package.json en frontend"
|
|
return
|
|
fi
|
|
|
|
# Instalar dependencias
|
|
log_info "Instalando dependencias Node.js..."
|
|
|
|
if command -v pnpm &> /dev/null; then
|
|
pnpm install --frozen-lockfile 2>/dev/null || pnpm install
|
|
else
|
|
npm ci 2>/dev/null || npm install
|
|
fi
|
|
|
|
# Build
|
|
log_info "Compilando frontend..."
|
|
|
|
if command -v pnpm &> /dev/null; then
|
|
pnpm build
|
|
else
|
|
npm run build
|
|
fi
|
|
|
|
log_success "Frontend actualizado"
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Reiniciar servicios
|
|
# ---------------------------------------------
|
|
restart_services() {
|
|
log_info "Reiniciando servicios..."
|
|
|
|
if [[ "$UPDATE_BACKEND" == "true" ]]; then
|
|
systemctl restart adan-api 2>/dev/null && log_success "adan-api reiniciado" || log_warn "adan-api no existe"
|
|
fi
|
|
|
|
if [[ "$UPDATE_FRONTEND" == "true" ]]; then
|
|
systemctl restart adan-web 2>/dev/null && log_success "adan-web reiniciado" || log_warn "adan-web no existe"
|
|
fi
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Verificar servicios
|
|
# ---------------------------------------------
|
|
verify_services() {
|
|
log_info "Verificando servicios..."
|
|
|
|
local all_ok=true
|
|
|
|
# Esperar a que inicien
|
|
sleep 3
|
|
|
|
if [[ "$UPDATE_BACKEND" == "true" ]]; then
|
|
if systemctl is-active --quiet adan-api; then
|
|
log_success "adan-api: activo"
|
|
else
|
|
log_error "adan-api: inactivo"
|
|
all_ok=false
|
|
fi
|
|
fi
|
|
|
|
if [[ "$UPDATE_FRONTEND" == "true" ]]; then
|
|
if systemctl is-active --quiet adan-web; then
|
|
log_success "adan-web: activo"
|
|
else
|
|
log_error "adan-web: inactivo"
|
|
all_ok=false
|
|
fi
|
|
fi
|
|
|
|
# Verificar API health
|
|
if [[ "$UPDATE_BACKEND" == "true" ]]; then
|
|
local api_port="${API_PORT:-8000}"
|
|
if curl -s "http://localhost:${api_port}/health" > /dev/null 2>&1; then
|
|
log_success "API health check: OK"
|
|
else
|
|
log_warn "API health check: no responde (puede estar iniciando)"
|
|
fi
|
|
fi
|
|
|
|
if [[ "$all_ok" == "false" ]]; then
|
|
log_error "Algunos servicios fallaron. Revisa los logs:"
|
|
echo " journalctl -u adan-api -n 50"
|
|
echo " journalctl -u adan-web -n 50"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Limpiar cache
|
|
# ---------------------------------------------
|
|
clean_cache() {
|
|
log_info "Limpiando cache..."
|
|
|
|
# Python cache
|
|
find "$INSTALL_DIR/backend" -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
|
find "$INSTALL_DIR/backend" -type f -name "*.pyc" -delete 2>/dev/null || true
|
|
|
|
# Node cache
|
|
rm -rf "$INSTALL_DIR/frontend/.next/cache" 2>/dev/null || true
|
|
|
|
log_success "Cache limpiado"
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Rollback
|
|
# ---------------------------------------------
|
|
rollback() {
|
|
local previous_commit="$1"
|
|
|
|
log_warn "Ejecutando rollback a: $previous_commit"
|
|
|
|
cd "$INSTALL_DIR"
|
|
git reset --hard "$previous_commit"
|
|
|
|
update_backend
|
|
update_frontend
|
|
restart_services
|
|
|
|
log_success "Rollback completado"
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Mostrar resumen
|
|
# ---------------------------------------------
|
|
show_summary() {
|
|
echo ""
|
|
echo -e "${GREEN}========================================${NC}"
|
|
echo -e "${GREEN} ACTUALIZACION COMPLETADA${NC}"
|
|
echo -e "${GREEN}========================================${NC}"
|
|
echo ""
|
|
echo "Version actual: $(get_current_version)"
|
|
echo "Branch: $REPO_BRANCH"
|
|
echo ""
|
|
echo "Servicios:"
|
|
systemctl is-active adan-api 2>/dev/null && echo " - adan-api: activo" || echo " - adan-api: inactivo"
|
|
systemctl is-active adan-web 2>/dev/null && echo " - adan-web: activo" || echo " - adan-web: inactivo"
|
|
echo ""
|
|
}
|
|
|
|
# ---------------------------------------------
|
|
# Main
|
|
# ---------------------------------------------
|
|
main() {
|
|
parse_args "$@"
|
|
|
|
echo ""
|
|
echo -e "${BLUE}========================================${NC}"
|
|
echo -e "${BLUE} ACTUALIZANDO SISTEMA DE ADAN${NC}"
|
|
echo -e "${BLUE}========================================${NC}"
|
|
echo ""
|
|
echo "Branch: $REPO_BRANCH"
|
|
echo "Force: $FORCE_UPDATE"
|
|
echo "Backup: $BACKUP_BEFORE_UPDATE"
|
|
echo ""
|
|
|
|
# Guardar commit actual para posible rollback
|
|
cd "$INSTALL_DIR"
|
|
PREVIOUS_COMMIT=$(git rev-parse HEAD)
|
|
|
|
check_requirements
|
|
create_backup
|
|
check_local_changes
|
|
|
|
# Intentar actualizar
|
|
if update_code; then
|
|
log_info "No hay actualizaciones disponibles"
|
|
exit 0
|
|
fi
|
|
|
|
# Actualizar componentes
|
|
update_backend || {
|
|
log_error "Fallo en backend, haciendo rollback..."
|
|
rollback "$PREVIOUS_COMMIT"
|
|
exit 1
|
|
}
|
|
|
|
update_frontend || {
|
|
log_error "Fallo en frontend, haciendo rollback..."
|
|
rollback "$PREVIOUS_COMMIT"
|
|
exit 1
|
|
}
|
|
|
|
clean_cache
|
|
restart_services
|
|
|
|
# Verificar
|
|
if ! verify_services; then
|
|
echo ""
|
|
read -p "Hacer rollback? (y/N): " -n 1 -r
|
|
echo
|
|
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
rollback "$PREVIOUS_COMMIT"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
show_summary
|
|
}
|
|
|
|
# Manejo de errores
|
|
trap 'log_error "Error en linea $LINENO"; exit 1' ERR
|
|
|
|
# Ejecutar
|
|
main "$@"
|