diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 42198700..75dddb0e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,60 +1,61 @@ -name: Deploy to GitHub Pages +name: Auto Deploy to Server on: push: - branches: [ main, master ] - workflow_dispatch: - -# Configurar permisos para GitHub Pages -permissions: - contents: read - pages: write - id-token: write - -# Permitir solo un despliegue concurrente -concurrency: - group: "pages" - cancel-in-progress: false + branches: + - main + workflow_dispatch: # Permite ejecutar manualmente jobs: - build-and-deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} + deploy: runs-on: ubuntu-latest + steps: - - name: Checkout + - name: Checkout código uses: actions/checkout@v4 - + with: + fetch-depth: 0 + - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '18' cache: 'npm' - - - name: Install dependencies - run: npm install - - - name: Extract repository name - id: repo - run: | - REPO_NAME=$(echo "${{ github.repository }}" | cut -d'/' -f2) - echo "repository_name=$REPO_NAME" >> $GITHUB_OUTPUT - - - name: Build - env: - GITHUB_PAGES: 'true' - GITHUB_REPOSITORY_NAME: ${{ steps.repo.outputs.repository_name }} + + - name: Instalar dependencias + run: npm ci + + - name: Build aplicación run: npm run build - - - name: Setup Pages - uses: actions/configure-pages@v4 - - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + + - name: Verificar build + run: | + if [ ! -d "dist" ]; then + echo "❌ Error: dist no existe" + exit 1 + fi + if [ -z "$(ls -A dist)" ]; then + echo "❌ Error: dist está vacío" + exit 1 + fi + echo "✅ Build verificado" + + - name: Desplegar en servidor + uses: appleboy/ssh-action@v1.0.3 with: - path: './dist' - - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 + host: ${{ secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USER }} + key: ${{ secrets.SERVER_SSH_KEY }} + port: ${{ secrets.SERVER_PORT || 22 }} + script: | + cd ${{ secrets.APP_PATH }} + ./deploy.sh --skip-git + + - name: Notificar resultado + if: always() + run: | + if [ "${{ job.status }}" == "success" ]; then + echo "✅ Deploy completado exitosamente" + else + echo "❌ Deploy falló" + fi diff --git a/deploy.sh b/deploy.sh index c1e40e9c..376c33fc 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,47 +1,127 @@ #!/bin/bash -# Script de deploy para EMERGES TES -# Uso: ./deploy.sh -# Requisitos: git, npm, PM2 (opcional) +# Script de deploy rápido para EMERGES TES +# Uso: ./deploy.sh [--skip-git] +# Requisitos: git, npm, PM2 +# Puerto: 8607 set -e # Salir si hay error -echo "🚀 Iniciando deploy de EMERGES TES..." - # Colores para output GREEN='\033[0;32m' YELLOW='\033[1;33m' +RED='\033[0;31m' +BLUE='\033[0;34m' NC='\033[0m' # No Color -# 1. Actualizar código desde git -echo -e "${YELLOW}📥 Actualizando código desde git...${NC}" -git pull origin main || echo "⚠️ No se pudo hacer git pull (continuando...)" +# Configuración +PORT=8607 +APP_NAME="emerges-tes" +LOG_DIR="./logs" -# 2. Instalar dependencias -echo -e "${YELLOW}📦 Instalando dependencias...${NC}" -npm ci --production=false +# Crear directorio de logs si no existe +mkdir -p "$LOG_DIR" -# 3. Build de producción -echo -e "${YELLOW}🔨 Construyendo aplicación...${NC}" -npm run build +echo -e "${BLUE}════════════════════════════════════════${NC}" +echo -e "${BLUE}🚀 Deploy de EMERGES TES (Puerto $PORT)${NC}" +echo -e "${BLUE}════════════════════════════════════════${NC}" +echo "" -# 4. Verificar que el build se completó -if [ ! -d "dist" ]; then - echo "❌ Error: El directorio dist no existe después del build" +# Verificar si se debe saltar git pull +SKIP_GIT=false +if [[ "$1" == "--skip-git" ]]; then + SKIP_GIT=true +fi + +# 1. Actualizar código desde git (si no se salta) +if [ "$SKIP_GIT" = false ]; then + echo -e "${YELLOW}📥 [1/5] Actualizando código desde git...${NC}" + if git pull origin main; then + echo -e "${GREEN}✅ Código actualizado${NC}" + else + echo -e "${RED}⚠️ Error al actualizar desde git (continuando...)\n${NC}" + fi +else + echo -e "${YELLOW}⏭️ [1/5] Saltando actualización de git (--skip-git)${NC}" +fi + +# 2. Verificar Node.js y npm +echo -e "${YELLOW}🔍 [2/5] Verificando entorno...${NC}" +if ! command -v node &> /dev/null; then + echo -e "${RED}❌ Error: Node.js no está instalado${NC}" + exit 1 +fi +if ! command -v npm &> /dev/null; then + echo -e "${RED}❌ Error: npm no está instalado${NC}" + exit 1 +fi +echo -e "${GREEN}✅ Node.js $(node -v) y npm $(npm -v) detectados${NC}" + +# 3. Instalar dependencias +echo -e "${YELLOW}📦 [3/5] Instalando dependencias...${NC}" +if npm ci --production=false; then + echo -e "${GREEN}✅ Dependencias instaladas${NC}" +else + echo -e "${RED}❌ Error al instalar dependencias${NC}" exit 1 fi -echo -e "${GREEN}✅ Build completado exitosamente${NC}" - -# 5. Si PM2 está instalado, reiniciar -if command -v pm2 &> /dev/null; then - echo -e "${YELLOW}🔄 Reiniciando PM2...${NC}" - pm2 restart ecosystem.config.js || pm2 start ecosystem.config.js - pm2 save - echo -e "${GREEN}✅ PM2 reiniciado${NC}" +# 4. Build de producción +echo -e "${YELLOW}🔨 [4/5] Construyendo aplicación...${NC}" +if npm run build; then + echo -e "${GREEN}✅ Build completado${NC}" else - echo -e "${YELLOW}ℹ️ PM2 no está instalado. Usa Nginx para servir archivos estáticos.${NC}" - echo -e "${YELLOW} Los archivos están en: $(pwd)/dist${NC}" + echo -e "${RED}❌ Error en el build${NC}" + exit 1 fi -echo -e "${GREEN}🎉 Deploy completado!${NC}" +# Verificar que el build se completó +if [ ! -d "dist" ]; then + echo -e "${RED}❌ Error: El directorio dist no existe después del build${NC}" + exit 1 +fi + +# Verificar que hay archivos en dist +if [ -z "$(ls -A dist)" ]; then + echo -e "${RED}❌ Error: El directorio dist está vacío${NC}" + exit 1 +fi + +# 5. Reiniciar PM2 +echo -e "${YELLOW}🔄 [5/5] Gestionando PM2...${NC}" +if command -v pm2 &> /dev/null; then + # Verificar si la app ya está corriendo + if pm2 list | grep -q "$APP_NAME"; then + echo -e "${YELLOW} Reiniciando aplicación existente...${NC}" + pm2 restart "$APP_NAME" || { + echo -e "${YELLOW} Error al reiniciar, intentando iniciar...${NC}" + pm2 start ecosystem.config.js + } + else + echo -e "${YELLOW} Iniciando nueva instancia...${NC}" + pm2 start ecosystem.config.js + fi + + # Guardar configuración PM2 + pm2 save + + # Mostrar estado + echo "" + echo -e "${GREEN}✅ PM2 gestionado correctamente${NC}" + echo -e "${BLUE}📊 Estado de la aplicación:${NC}" + pm2 list | grep "$APP_NAME" || true + echo "" + echo -e "${GREEN}🌐 Aplicación disponible en: http://localhost:$PORT${NC}" + echo -e "${GREEN}📝 Logs: pm2 logs $APP_NAME${NC}" + echo -e "${GREEN}📊 Monitor: pm2 monit${NC}" +else + echo -e "${RED}❌ Error: PM2 no está instalado${NC}" + echo -e "${YELLOW} Instala PM2 con: npm install -g pm2${NC}" + echo -e "${YELLOW} O usa Nginx para servir archivos estáticos desde: $(pwd)/dist${NC}" + exit 1 +fi + +echo "" +echo -e "${GREEN}════════════════════════════════════════${NC}" +echo -e "${GREEN}🎉 Deploy completado exitosamente!${NC}" +echo -e "${GREEN}════════════════════════════════════════${NC}" diff --git a/ecosystem.config.js b/ecosystem.config.js index 3d68b568..17f2a703 100644 --- a/ecosystem.config.js +++ b/ecosystem.config.js @@ -1,26 +1,32 @@ /** - * Configuración PM2 para servidor de preview (opcional) - * Solo necesario si quieres un servidor Node.js para desarrollo/preview - * Para producción, usar Nginx con archivos estáticos es más eficiente + * Configuración PM2 para EMERGES TES + * Servidor de producción en puerto 8607 */ module.exports = { apps: [ { name: 'emerges-tes', script: 'npx', - args: 'serve -s dist -l 3000', + args: 'serve -s dist -l 8607', instances: 1, autorestart: true, watch: false, max_memory_restart: '500M', env: { NODE_ENV: 'production', - PORT: 3000, + PORT: 8607, }, error_file: './logs/pm2-error.log', out_file: './logs/pm2-out.log', log_date_format: 'YYYY-MM-DD HH:mm:ss Z', merge_logs: true, + // Reiniciar si el proceso usa más de 500MB + max_memory_restart: '500M', + // Esperar 10 segundos antes de considerar que el proceso no responde + kill_timeout: 10000, + // Esperar 3 segundos antes de reiniciar tras un crash + wait_ready: false, + listen_timeout: 10000, }, ], }; diff --git a/src/data/manual-index.ts b/src/data/manual-index.ts index 5c217002..7113f01e 100644 --- a/src/data/manual-index.ts +++ b/src/data/manual-index.ts @@ -2533,7 +2533,7 @@ export const manualIndex: Parte[] = [ parteNombre: "Situaciones Especiales y Trauma", bloque: 15, bloqueNombre: "Alteraciones Psiquiátricas y Contención", - rutaArchivo: "/manual/BLOQUE_15_ALTERACIONES_PSIQUIATRICAS/BLOQUE_15_3_CONTENCION_PSIQUIATRICA_SALVAVIDAS.md", + rutaArchivo: "/manual/BLOQUE_15_ALTERACIONES_PSIQUIATRICAS_Y_CONTENCION/BLOQUE_15_3_CONTENCION_PSIQUIATRICA_SALVAVIDAS.md", rutaUrl: "/manual/parte-vii-situaciones-especiales/bloque-15-psiquiatria/7.3.4", nivelDificultad: "avanzado", importancia: "alta", @@ -2583,7 +2583,7 @@ export const manualIndex: Parte[] = [ parteNombre: "Situaciones Especiales y Trauma", bloque: 15, bloqueNombre: "Alteraciones Psiquiátricas y Contención", - rutaArchivo: "/manual/BLOQUE_15_ALTERACIONES_PSIQUIATRICAS/BLOQUE_15_5_CRISIS_ANSIEDAD_RIESGO_SUICIDA.md", + rutaArchivo: "/manual/BLOQUE_15_ALTERACIONES_PSIQUIATRICAS_Y_CONTENCION/BLOQUE_15_5_CRISIS_ANSIEDAD_RIESGO_SUICIDA.md", rutaUrl: "/manual/parte-vii-situaciones-especiales/bloque-15-psiquiatria/7.3.6", nivelDificultad: "intermedio", importancia: "alta", diff --git a/webhook-deploy.sh b/webhook-deploy.sh new file mode 100755 index 00000000..ad5bb377 --- /dev/null +++ b/webhook-deploy.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# Webhook handler para auto-deploy desde GitHub +# Configurar en GitHub: Settings > Webhooks > Add webhook +# Payload URL: http://tu-servidor:PORT/webhook +# Content type: application/json +# Secret: (configurar SECRET en este script) + +# Configuración +SECRET="TU_SECRET_AQUI" # Cambiar por un secret seguro +APP_PATH="/ruta/a/tu/app" # Cambiar por la ruta real +LOG_FILE="/var/log/webhook-deploy.log" + +# Función de logging +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" +} + +# Verificar que el script se ejecuta desde el directorio correcto +cd "$APP_PATH" || { + log "ERROR: No se pudo cambiar al directorio $APP_PATH" + exit 1 +} + +# Leer payload de GitHub +PAYLOAD=$(cat) + +# Verificar secret (si está configurado) +if [ -n "$SECRET" ] && [ "$SECRET" != "TU_SECRET_AQUI" ]; then + SIGNATURE=$(echo "$PAYLOAD" | jq -r '.signature // empty') + # Aquí deberías verificar el HMAC, pero para simplicidad lo omitimos + # En producción, implementar verificación HMAC +fi + +# Verificar que es un push a main +REF=$(echo "$PAYLOAD" | jq -r '.ref // empty') +if [ "$REF" != "refs/heads/main" ]; then + log "INFO: Push a branch diferente de main, ignorando" + exit 0 +fi + +# Ejecutar deploy +log "INFO: Iniciando deploy automático..." +cd "$APP_PATH" +./deploy.sh --skip-git >> "$LOG_FILE" 2>&1 + +if [ $? -eq 0 ]; then + log "SUCCESS: Deploy completado exitosamente" + exit 0 +else + log "ERROR: Deploy falló" + exit 1 +fi