feat(deploy): integrar orquestacion de despliegue con SIAX Monitor y vincular dominio soporte.sigmac.app
This commit is contained in:
+190
-105
@@ -3,16 +3,20 @@
|
||||
# Help Desk — Script de Despliegue a Producción
|
||||
# Ecosistema Telcotronics
|
||||
# ==============================================================================
|
||||
# Servidor: server-webapps (192.168.10.160, CT 132 en Proxmox)
|
||||
# Usuario remoto: user_apps
|
||||
# Directorio: /home/user_apps/apps/help_desk
|
||||
# Servicio systemd: siax-app-HELPDESK.service
|
||||
# Puerto producción: 3008
|
||||
# Convención del ecosistema (proyecto webapp Node.js):
|
||||
# 1. Lee servers.conf (creado desde servers.conf.example, no commiteado).
|
||||
# 2. Sincroniza código vía rsync hacia el servidor remoto.
|
||||
# 3. Instala dependencias y ejecuta setup de BD en el servidor.
|
||||
# 4. Solicita reinicio y supervisión a SIAX Monitor (API REST en :8080).
|
||||
# - No requiere sudo interactivo ni contraseñas.
|
||||
# - SIAX Monitor gestiona la unidad siax-app-HELPDESK.service.
|
||||
# 5. Verifica estado de salud y métricas de proceso vía SIAX Monitor y HTTP.
|
||||
# 6. Actualiza ficha del servicio en el MCP de Infraestructura (:3007).
|
||||
# ==============================================================================
|
||||
|
||||
set -e
|
||||
set -euo pipefail
|
||||
|
||||
# Colores para salida en consola
|
||||
# Colores para la salida
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
@@ -20,125 +24,206 @@ RED='\033[0;31m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
SERVER="${DEPLOY_SERVER:-192.168.10.160}"
|
||||
USER="${DEPLOY_USER:-user_apps}"
|
||||
DEST="${DEPLOY_DEST:-/home/user_apps/apps/help_desk}"
|
||||
SERVICE_NAME="siax-app-HELPDESK"
|
||||
SUDO_PASS="${DEPLOY_SUDO_PASS:-Microbot%}"
|
||||
REMOTE_PORT="${DEPLOY_PORT:-3008}"
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
APP_NAME="HELPDESK"
|
||||
APP_PORT="3008"
|
||||
MCP_SERVICE_ID="35"
|
||||
CONF_FILE="${SERVERS_CONF:-$SCRIPT_DIR/servers.conf}"
|
||||
|
||||
mostrar_ayuda() {
|
||||
echo -e "${BLUE}Help Desk — Script de Despliegue a Producción${NC}"
|
||||
echo "Uso: ./desplegar.sh [opciones]"
|
||||
echo ""
|
||||
echo "Opciones:"
|
||||
echo " --help Muestra esta ayuda y termina."
|
||||
echo " --check Solo verifica estado de servidores y SIAX Monitor."
|
||||
echo " --skip-git Omite la advertencia de cambios locales no commiteados."
|
||||
echo ""
|
||||
echo "Configuración:"
|
||||
echo " Los destinos se leen de servers.conf con formato: usuario@host:puerto_ssh:ruta_remota"
|
||||
exit 0
|
||||
}
|
||||
|
||||
CHECK_ONLY=false
|
||||
SKIP_GIT=false
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--help|-h)
|
||||
mostrar_ayuda
|
||||
;;
|
||||
--check|-c)
|
||||
CHECK_ONLY=true
|
||||
;;
|
||||
--skip-git)
|
||||
SKIP_GIT=true
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Opción desconocida: $arg${NC}"
|
||||
mostrar_ayuda
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo -e "${BLUE}=====================================================${NC}"
|
||||
echo -e "${BLUE}🚀 Help Desk — Despliegue a Producción (CT 132)${NC}"
|
||||
echo -e "${BLUE}🚀 Help Desk — Despliegue con SIAX Monitor${NC}"
|
||||
echo -e "${BLUE}=====================================================${NC}"
|
||||
echo -e "Servidor: ${YELLOW}$SERVER${NC}"
|
||||
echo -e "Usuario: ${YELLOW}$USER${NC}"
|
||||
echo -e "Destino: ${YELLOW}$DEST${NC}"
|
||||
echo -e "Servicio: ${YELLOW}$SERVICE_NAME${NC}"
|
||||
echo -e "Puerto: ${YELLOW}$REMOTE_PORT${NC}"
|
||||
echo -e "-----------------------------------------------------"
|
||||
|
||||
# 1. Verificaciones previas
|
||||
echo -e "${YELLOW}🔍 [1/6] Verificando requisitos locales y conectividad SSH...${NC}"
|
||||
if [ ! -f "app.js" ]; then
|
||||
# 1. Validar existencia de servers.conf
|
||||
if [ ! -f "$CONF_FILE" ]; then
|
||||
echo -e "${RED}❌ Error: Falta archivo de configuración $CONF_FILE${NC}"
|
||||
echo -e "${YELLOW}👉 Crea uno copiando la plantilla:${NC} cp servers.conf.example servers.conf"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. Validar estructura del proyecto local
|
||||
if [ ! -f "app.js" ] || [ ! -f "package.json" ]; then
|
||||
echo -e "${RED}❌ Error: Ejecuta el script desde la raíz del proyecto help_desk.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "siax-app-HELPDESK.service" ]; then
|
||||
echo -e "${RED}❌ Error: No se encontró siax-app-HELPDESK.service en la raíz.${NC}"
|
||||
exit 1
|
||||
# 3. Advertencia de cambios sin commitear
|
||||
if [ "$SKIP_GIT" = false ] && command -v git >/dev/null 2>&1; then
|
||||
if [ -n "$(git status --porcelain 2>/dev/null || true)" ]; then
|
||||
echo -e "${YELLOW}⚠️ Aviso: Existen cambios locales no commiteados en Git.${NC}"
|
||||
echo -e " Continuando despliegue de archivos actuales..."
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! ssh -o BatchMode=yes -o ConnectTimeout=5 "$USER@$SERVER" echo "OK" >/dev/null 2>&1; then
|
||||
echo -e "${RED}❌ Error: No se pudo conectar vía SSH a $USER@$SERVER.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✓ Conectividad SSH y archivos locales validados.${NC}"
|
||||
# 4. Procesar cada servidor definido en servers.conf
|
||||
grep -vE '^\s*(#|$)' "$CONF_FILE" | while IFS=: read -r DESTINO PUERTO_SSH RUTA_REMOTA; do
|
||||
HOST="${DESTINO#*@}"
|
||||
PUERTO_SSH="${PUERTO_SSH:-22}"
|
||||
|
||||
# 2. Sincronización con el servidor vía rsync
|
||||
echo -e "${YELLOW}📡 [2/6] Sincronizando archivos con el servidor remoto vía rsync...${NC}"
|
||||
rsync -avz \
|
||||
-e "ssh -o IdentitiesOnly=yes" \
|
||||
--exclude 'node_modules/' \
|
||||
--exclude '.git/' \
|
||||
--exclude 'scratch/' \
|
||||
--exclude '.env' \
|
||||
./ "$USER@$SERVER:$DEST/"
|
||||
echo -e "\n${CYAN}-----------------------------------------------------${NC}"
|
||||
echo -e "🎯 Destino: ${YELLOW}$DESTINO${NC} (SSH :$PUERTO_SSH) -> ${YELLOW}$RUTA_REMOTA${NC}"
|
||||
echo -e "${CYAN}-----------------------------------------------------${NC}"
|
||||
|
||||
# Asegurar sincronización segura de configuración .env
|
||||
if [ -f .env ]; then
|
||||
echo -e "${CYAN}Sincronizando archivo .env de configuración a producción...${NC}"
|
||||
scp -o IdentitiesOnly=yes .env "$USER@$SERVER:$DEST/.env"
|
||||
fi
|
||||
# Verificación previa de conectividad SSH
|
||||
echo -e "${YELLOW}🔍 [1/5] Verificando conectividad SSH con $HOST...${NC}"
|
||||
if ! ssh -o BatchMode=yes -o ConnectTimeout=5 -o IdentitiesOnly=yes -p "$PUERTO_SSH" "$DESTINO" echo "OK" >/dev/null 2>&1; then
|
||||
echo -e "${RED}❌ Error: No se pudo conectar vía SSH a $DESTINO en el puerto $PUERTO_SSH.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✓ Conexión SSH establecida.${NC}"
|
||||
|
||||
echo -e "${GREEN}✓ Archivos sincronizados exitosamente en $DEST.${NC}"
|
||||
if [ "$CHECK_ONLY" = true ]; then
|
||||
echo -e "${YELLOW}Auditoría de estado actual en SIAX Monitor ($HOST:8080)...${NC}"
|
||||
curl -s "http://$HOST:8080/api/apps/$APP_NAME/status" || true
|
||||
echo ""
|
||||
continue
|
||||
fi
|
||||
|
||||
# 3. Preparación de dependencias y migraciones remotas
|
||||
echo -e "${YELLOW}⚙️ [3/6] Instalando dependencias y ejecutando setup en el servidor...${NC}"
|
||||
ssh -o IdentitiesOnly=yes "$USER@$SERVER" "bash -s" << EOF
|
||||
set -e
|
||||
export PATH="\$HOME/.nvm/versions/node/v24.12.0/bin:/usr/local/bin:/usr/bin:\$PATH"
|
||||
# Sincronización de código vía rsync
|
||||
echo -e "${YELLOW}📡 [2/5] Sincronizando código a $RUTA_REMOTA vía rsync...${NC}"
|
||||
rsync -avz \
|
||||
-e "ssh -o IdentitiesOnly=yes -p $PUERTO_SSH" \
|
||||
--exclude 'node_modules/' \
|
||||
--exclude '.git/' \
|
||||
--exclude 'scratch/' \
|
||||
--exclude '.env' \
|
||||
--exclude 'servers.conf' \
|
||||
--exclude '*.log' \
|
||||
./ "$DESTINO:$RUTA_REMOTA/"
|
||||
|
||||
cd "$DEST"
|
||||
# Sincronizar .env seguro si existe localmente
|
||||
if [ -f .env ]; then
|
||||
echo -e " Sincronizando .env de configuración..."
|
||||
scp -o IdentitiesOnly=yes -P "$PUERTO_SSH" .env "$DESTINO:$RUTA_REMOTA/.env"
|
||||
fi
|
||||
echo -e "${GREEN}✓ Archivos sincronizados exitosamente.${NC}"
|
||||
|
||||
# Instalar dependencias en modo producción
|
||||
echo "Instalando paquetes npm (sin devDependencies)..."
|
||||
npm install --omit=dev --no-audit
|
||||
|
||||
# Verificar / migrar esquema de Base de Datos
|
||||
echo "Ejecutando setup y migraciones multi-tenant..."
|
||||
node config/setup.js
|
||||
# Instalación de dependencias y migraciones remotas
|
||||
echo -e "${YELLOW}⚙️ [3/5] Instalando dependencias y setup de BD en el servidor...${NC}"
|
||||
ssh -o IdentitiesOnly=yes -p "$PUERTO_SSH" "$DESTINO" "bash -s" << EOF
|
||||
set -e
|
||||
export PATH="\$HOME/.nvm/versions/node/v24.12.0/bin:/usr/local/bin:/usr/bin:\$PATH"
|
||||
cd "$RUTA_REMOTA"
|
||||
npm install --omit=dev --no-audit --no-fund
|
||||
node config/setup.js
|
||||
EOF
|
||||
echo -e "${GREEN}✓ Dependencias y base de datos verificadas en el servidor.${NC}"
|
||||
echo -e "${GREEN}✓ Dependencias y esquema MariaDB verificados en el servidor.${NC}"
|
||||
|
||||
# 4. Configurar e instalar servicio systemd
|
||||
echo -e "${YELLOW}🔄 [4/6] Configurando e instalando servicio systemd ($SERVICE_NAME)...${NC}"
|
||||
ssh -o IdentitiesOnly=yes "$USER@$SERVER" "bash -s" << EOF
|
||||
set -e
|
||||
echo "$SUDO_PASS" | sudo -S cp "$DEST/siax-app-HELPDESK.service" /etc/systemd/system/${SERVICE_NAME}.service
|
||||
echo "$SUDO_PASS" | sudo -S systemctl daemon-reload
|
||||
echo "$SUDO_PASS" | sudo -S systemctl enable ${SERVICE_NAME}
|
||||
echo "$SUDO_PASS" | sudo -S systemctl restart ${SERVICE_NAME}
|
||||
EOF
|
||||
echo -e "${GREEN}✓ Servicio systemd configurado y reiniciado.${NC}"
|
||||
# Reinicio coordinado con SIAX Monitor
|
||||
echo -e "${YELLOW}🔄 [4/5] Coordinando reinicio vía SIAX Monitor ($HOST:8080)...${NC}"
|
||||
RESTART_RES=$(curl -s -m 15 -X POST "http://$HOST:8080/api/apps/$APP_NAME/restart" || true)
|
||||
|
||||
# 5. Verificación de salud HTTP
|
||||
echo -e "${YELLOW}🩺 [5/6] Verificando salud del servicio HTTP en el puerto $REMOTE_PORT...${NC}"
|
||||
sleep 2
|
||||
ssh -o IdentitiesOnly=yes "$USER@$SERVER" "bash -s" << EOF
|
||||
set -e
|
||||
systemctl is-active ${SERVICE_NAME}
|
||||
curl -fsS -m 10 -o /dev/null -w "HTTP Status: %{http_code}\n" "http://127.0.0.1:$REMOTE_PORT/login"
|
||||
EOF
|
||||
echo -e "${GREEN}✓ Aplicación respondiendo exitosamente en producción.${NC}"
|
||||
if echo "$RESTART_RES" | grep -q '"success":true'; then
|
||||
echo -e "${GREEN}✓ SIAX Monitor confirmó el reinicio exitoso de $APP_NAME.${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ SIAX Monitor restart retornó:${NC} $RESTART_RES"
|
||||
echo -e " Intentando registrar app en SIAX Monitor si no estaba creada..."
|
||||
curl -s -m 15 -X POST "http://$HOST:8080/api/apps" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"app_name\": \"$APP_NAME\",
|
||||
\"app_type\": \"nodejs\",
|
||||
\"working_directory\": \"$RUTA_REMOTA\",
|
||||
\"script_path\": \"app.js\",
|
||||
\"user\": \"${DESTINO%@*}\",
|
||||
\"use_npm_start\": false,
|
||||
\"restart_policy\": \"always\",
|
||||
\"environment\": { \"PORT\": \"$APP_PORT\" }
|
||||
}" >/dev/null 2>&1 || true
|
||||
sleep 1
|
||||
curl -s -m 15 -X POST "http://$HOST:8080/api/apps/$APP_NAME/restart" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
# 6. Actualización en MCP de Infraestructura
|
||||
echo -e "${YELLOW}🌐 [6/6] Actualizando estado a ACTIVE en el MCP de Infraestructura...${NC}"
|
||||
node -e "
|
||||
const http = require('http');
|
||||
const payload = JSON.stringify({ status: 'ACTIVE' });
|
||||
const req = http.request({
|
||||
hostname: '$SERVER',
|
||||
port: 3007,
|
||||
path: '/api/services/35',
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
# Espera breve para estabilización de socket
|
||||
sleep 2
|
||||
|
||||
# Verificación de salud y métricas de SIAX Monitor
|
||||
echo -e "${YELLOW}🩺 [5/5] Auditando salud, PID y métricas operativas...${NC}"
|
||||
STATUS_JSON=$(curl -s "http://$HOST:8080/api/apps/$APP_NAME/status" || echo "{}")
|
||||
PID_ACTUAL=$(echo "$STATUS_JSON" | grep -o '"pid":[0-9]*' | cut -d: -f2 || echo "desconocido")
|
||||
RAM_ACTUAL=$(echo "$STATUS_JSON" | grep -o '"memory_usage":"[^"]*"' | cut -d'"' -f4 || echo "desconocido")
|
||||
SYS_STATUS=$(echo "$STATUS_JSON" | grep -o '"systemd_status":"[^"]*"' | cut -d'"' -f4 || echo "desconocido")
|
||||
|
||||
echo -e " • Estado SIAX Monitor: ${GREEN}$SYS_STATUS${NC}"
|
||||
echo -e " • PID autoritativo: ${GREEN}$PID_ACTUAL${NC}"
|
||||
echo -e " • Consumo de RAM: ${GREEN}$RAM_ACTUAL${NC}"
|
||||
|
||||
# Test HTTP directo en el puerto de la aplicación
|
||||
HTTP_CODE=$(curl -fsS -m 10 -o /dev/null -w "%{http_code}" "http://$HOST:$APP_PORT/login" || echo "000")
|
||||
if [ "$HTTP_CODE" = "200" ]; then
|
||||
echo -e " • Verificación HTTP: ${GREEN}HTTP 200 OK (http://$HOST:$APP_PORT/login)${NC}"
|
||||
else
|
||||
echo -e " • Verificación HTTP: ${RED}HTTP $HTTP_CODE${NC} (revisar logs en SIAX Monitor)"
|
||||
fi
|
||||
|
||||
# Actualizar estado y URL en el MCP de Infraestructura
|
||||
echo -e "\n${YELLOW}🌐 Notificando estado al MCP de Infraestructura (:3007)...${NC}"
|
||||
node -e "
|
||||
const http = require('http');
|
||||
const payload = JSON.stringify({
|
||||
status: 'ACTIVE',
|
||||
url: 'https://soporte.sigmac.app'
|
||||
});
|
||||
const req = http.request({
|
||||
hostname: '$HOST',
|
||||
port: 3007,
|
||||
path: '/api/services/$MCP_SERVICE_ID',
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': Buffer.byteLength(payload)
|
||||
}
|
||||
}, (res) => {
|
||||
let d = '';
|
||||
res.on('data', chunk => d += chunk);
|
||||
res.on('end', () => console.log('MCP Update Status:', res.statusCode));
|
||||
});
|
||||
req.on('error', err => console.warn('Aviso MCP:', err.message));
|
||||
req.write(payload);
|
||||
req.end();
|
||||
" || true
|
||||
}
|
||||
}, res => {
|
||||
console.log(' ✓ Ficha MCP #$MCP_SERVICE_ID sincronizada (HTTP ' + res.statusCode + ')');
|
||||
});
|
||||
req.on('error', err => console.warn(' ⚠️ MCP aviso:', err.message));
|
||||
req.write(payload);
|
||||
req.end();
|
||||
" || true
|
||||
|
||||
echo -e "-----------------------------------------------------"
|
||||
echo -e "${GREEN}🎉 ¡Despliegue a Producción completado exitosamente!${NC}"
|
||||
echo -e "Acceso en red local: ${CYAN}http://$SERVER:$REMOTE_PORT${NC}"
|
||||
echo -e "Servicio: ${CYAN}${SERVICE_NAME}.service${NC}"
|
||||
echo -e "Ficha MCP: ${CYAN}ID 35 (Status: ACTIVE)${NC}"
|
||||
done
|
||||
|
||||
echo -e "\n${BLUE}=====================================================${NC}"
|
||||
echo -e "${GREEN}🎉 ¡Despliegue a Producción finalizado con éxito!${NC}"
|
||||
echo -e "🌐 Dominio público: ${CYAN}https://soporte.sigmac.app${NC}"
|
||||
echo -e "🎯 Upstream interno: ${CYAN}http://192.168.10.160:$APP_PORT${NC}"
|
||||
echo -e "👁️ SIAX Monitor: ${CYAN}http://192.168.10.160:8080/#/apps/$APP_NAME${NC}"
|
||||
echo -e "📋 Ficha MCP: ${CYAN}ID $MCP_SERVICE_ID (Status: ACTIVE)${NC}"
|
||||
echo -e "${BLUE}=====================================================${NC}"
|
||||
|
||||
Reference in New Issue
Block a user