docs: añadir plan de conversión SCORM y scripts de deploy

- Plan completo de conversión progresiva a SCORM
- Guía rápida de inicio SCORM
- Scripts de despliegue automático mejorados
This commit is contained in:
planetazuzu 2026-01-02 10:28:38 +01:00
parent 1e50a72c8e
commit f3f2ab3c55
12 changed files with 2150 additions and 0 deletions

View file

@ -0,0 +1,629 @@
# 📦 Plan de Conversión Progresiva a SCORM
**Fecha:** 2024-12-30
**Estado:** Planificación
**Objetivo:** Convertir guías de refuerzo a SCORM sin romper la app actual
---
## 🎯 Resumen Ejecutivo
**Objetivo:** Convertir progresivamente las guías de refuerzo (actualmente en Markdown) a paquetes SCORM 1.2/2004, manteniendo la funcionalidad actual intacta y permitiendo que ambas versiones coexistan.
**Estrategia:** Arquitectura paralela que permite:
- ✅ Mantener guías actuales funcionando (Markdown)
- ✅ Generar paquetes SCORM progresivamente
- ✅ No modificar código existente
- ✅ Migración guía por guía
- ✅ Reversibilidad completa
---
## 📊 Situación Actual
### Estructura de Guías Actual
```
src/
├── data/
│ └── guides-index.ts # Índice de guías (2 guías actualmente)
├── views/formativo/
│ ├── GuideIndex.tsx # Lista de guías
│ ├── GuideViewer.tsx # Visualizador con tabs
│ └── GuideSectionViewer.tsx # Visualizador de sección individual
├── components/guide/
│ ├── GuideCard.tsx
│ ├── GuideHeader.tsx
│ ├── GuideNavigation.tsx
│ └── GuideMarkdownViewer.tsx # Wrapper de MarkdownViewer
└── layouts/
└── GuideLayout.tsx
docs/consolidado/
├── SECCION_01_ABCDE_OPERATIVO.md
├── SECCION_02_ABCDE_OPERATIVO.md
├── ... (8 secciones por guía)
├── SECCION_01_RCP_ADULTO_SVB.md
└── ... (8 secciones por guía)
public/docs/consolidado/
└── [81 archivos .md copiados]
```
### Características Actuales
- ✅ 8 secciones fijas por guía
- ✅ Navegación por tabs y URLs directas
- ✅ Contenido en Markdown
- ✅ Enlaces a protocolos operativos
- ✅ Badge "Modo Formación"
- ✅ Layout diferenciado (sin BottomNav)
### Guías Existentes
1. **ABCDE Operativo** (`abcde-operativo`)
- 8 secciones
- Protocolo operativo relacionado: `/manual/parte-i-fundamentos/bloque-1-procedimientos-basicos/1.2.2`
2. **RCP Adulto SVB** (`rcp-adulto-svb`)
- 8 secciones
- Protocolo operativo relacionado: `/rcp`
---
## 📚 Requisitos SCORM
### ¿Qué es SCORM?
**SCORM (Sharable Content Object Reference Model)** es un estándar para contenido e-learning que permite:
- Interoperabilidad entre LMS (Moodle, Blackboard, Canvas, etc.)
- Tracking de progreso (completado, tiempo, puntuación)
- Reutilización de contenido
- Portabilidad entre plataformas
### Versiones SCORM
- **SCORM 1.2** (más compatible, recomendado para empezar)
- **SCORM 2004** (más avanzado, mejor tracking)
### Estructura de un Paquete SCORM
```
paquete-scorm/
├── imsmanifest.xml # Manifest principal (obligatorio)
├── [carpeta-contenido]/
│ ├── index.html # Punto de entrada
│ ├── assets/
│ │ ├── css/
│ │ ├── js/
│ │ └── images/
│ └── sections/ # Secciones del curso
│ ├── section-01.html
│ ├── section-02.html
│ └── ...
└── [archivos SCORM API]
├── APIWrapper.js # Wrapper SCORM API
└── SCORM_API_1484_11.js # API SCORM 2004 (opcional)
```
### Funcionalidades SCORM Necesarias
1. **Tracking Básico:**
- `cmi.core.lesson_status` (completed, incomplete, passed, failed)
- `cmi.core.score.raw` (puntuación 0-100)
- `cmi.core.total_time` (tiempo total)
- `cmi.core.lesson_location` (última posición)
2. **Navegación:**
- Progreso entre secciones
- Botones anterior/siguiente
- Indicador de progreso
3. **Contenido:**
- HTML estático (no React)
- CSS embebido o externo
- JavaScript para SCORM API
- Imágenes y assets
---
## 🏗️ Arquitectura Propuesta
### Principios de Diseño
1. **No romper nada existente**
- Las guías actuales siguen funcionando
- No modificar `GuideViewer`, `GuideMarkdownViewer`, etc.
2. **Arquitectura paralela**
- Nueva carpeta `scorm/` para paquetes SCORM
- Scripts de generación separados
- Build independiente
3. **Migración progresiva**
- Convertir guía por guía
- Marcar en `guides-index.ts` si tiene versión SCORM
- Permitir elegir formato (Markdown o SCORM)
4. **Reutilización de contenido**
- Convertir Markdown → HTML
- Reutilizar estilos Tailwind (compilados)
- Mantener estructura de 8 secciones
### Estructura de Carpetas Propuesta
```
proyecto/
├── src/ # App React (NO TOCAR)
│ └── [estructura actual]
├── scorm/ # 🆕 NUEVA: Paquetes SCORM
│ ├── generator/ # Scripts de generación
│ │ ├── markdown-to-html.ts # Convertir MD → HTML
│ │ ├── scorm-builder.ts # Generar paquete SCORM
│ │ ├── manifest-generator.ts # Generar imsmanifest.xml
│ │ └── package-builder.ts # Empaquetar ZIP
│ │
│ ├── templates/ # Plantillas SCORM
│ │ ├── index.html # Template principal
│ │ ├── section.html # Template de sección
│ │ ├── scorm-api.js # SCORM API wrapper
│ │ └── styles.css # Estilos compilados
│ │
│ ├── packages/ # Paquetes SCORM generados
│ │ ├── abcde-operativo/
│ │ │ ├── imsmanifest.xml
│ │ │ ├── index.html
│ │ │ └── ...
│ │ └── rcp-adulto-svb/
│ │ └── ...
│ │
│ └── dist/ # Paquetes ZIP listos para LMS
│ ├── abcde-operativo-scorm-1.2.zip
│ └── rcp-adulto-svb-scorm-1.2.zip
├── docs/consolidado/ # Markdown original (NO TOCAR)
│ └── [archivos .md]
└── scripts/
└── generate-scorm.ts # Script principal de generación
```
---
## 🔄 Flujo de Conversión
### Proceso de Generación
```
1. Leer guides-index.ts
2. Para cada guía marcada como "convertible a SCORM":
3. Leer 8 archivos Markdown de docs/consolidado/
4. Convertir Markdown → HTML (usando remark/rehype)
5. Aplicar template HTML con estilos Tailwind
6. Generar imsmanifest.xml con metadatos
7. Inyectar SCORM API JavaScript
8. Copiar assets (imágenes, etc.)
9. Generar paquete ZIP
10. Guardar en scorm/dist/
```
### Tracking SCORM
```javascript
// Ejemplo de tracking básico
SCORM.setValue("cmi.core.lesson_status", "incomplete");
SCORM.setValue("cmi.core.score.raw", "0");
SCORM.setValue("cmi.core.total_time", "00:00:00");
// Al completar una sección
SCORM.setValue("cmi.core.lesson_location", "section-3");
SCORM.setValue("cmi.core.score.raw", "37.5"); // 3/8 secciones
// Al completar todo
SCORM.setValue("cmi.core.lesson_status", "completed");
SCORM.setValue("cmi.core.score.raw", "100");
```
---
## 📋 Plan de Implementación por Fases
### FASE 1: Infraestructura Base (Sin tocar app actual)
**Objetivo:** Crear estructura y herramientas de generación
**Tareas:**
1. ✅ Crear carpeta `scorm/` y subcarpetas
2. ✅ Instalar dependencias necesarias:
- `remark` / `rehype` (ya existen)
- `jszip` (para generar ZIP)
- `xml2js` o `fast-xml-parser` (para XML)
3. ✅ Crear templates HTML básicos
4. ✅ Crear SCORM API wrapper (JavaScript vanilla)
5. ✅ Script de prueba: convertir 1 sección MD → HTML
**Criterios de éxito:**
- ✅ Script genera HTML válido desde Markdown
- ✅ HTML se ve correctamente en navegador
- ✅ No se modifica código de la app React
**Tiempo estimado:** 2-3 días
---
### FASE 2: Generador de Paquetes SCORM
**Objetivo:** Generar paquete SCORM completo para 1 guía
**Tareas:**
1. ✅ Script para convertir 8 secciones MD → HTML
2. ✅ Generar `imsmanifest.xml` con metadatos correctos
3. ✅ Integrar SCORM API en HTML
4. ✅ Implementar tracking básico (progreso, tiempo)
5. ✅ Copiar assets (imágenes) al paquete
6. ✅ Generar ZIP del paquete
**Criterios de éxito:**
- ✅ Paquete ZIP se puede importar en LMS de prueba (Moodle)
- ✅ Tracking funciona (completado, progreso)
- ✅ Navegación entre secciones funciona
- ✅ Contenido se ve correctamente
**Tiempo estimado:** 3-4 días
---
### FASE 3: Integración Opcional en App (Sin romper actual)
**Objetivo:** Permitir descargar/visualizar SCORM desde la app (opcional)
**Tareas:**
1. ✅ Extender `guides-index.ts` con campo `scormAvailable: boolean`
2. ✅ Añadir botón "Descargar SCORM" en `GuideCard` (solo si disponible)
3. ✅ Servir paquetes ZIP desde `public/scorm/dist/`
4. ✅ Página de información sobre SCORM (opcional)
**Criterios de éxito:**
- ✅ Las guías actuales siguen funcionando igual
- ✅ Nueva funcionalidad es opcional y no afecta flujo actual
- ✅ Descarga de ZIP funciona
**Tiempo estimado:** 1-2 días
---
### FASE 4: Migración Progresiva de Guías
**Objetivo:** Convertir guías una por una
**Tareas:**
1. ✅ Convertir "ABCDE Operativo" a SCORM
2. ✅ Probar en LMS real
3. ✅ Ajustar estilos/tracking según feedback
4. ✅ Convertir "RCP Adulto SVB" a SCORM
5. ✅ Documentar proceso para futuras guías
**Criterios de éxito:**
- ✅ Ambas guías tienen versión SCORM funcional
- ✅ Proceso documentado para nuevas guías
- ✅ App React sigue funcionando igual
**Tiempo estimado:** 2-3 días por guía
---
### FASE 5: Mejoras y Optimización
**Objetivo:** Mejorar calidad y funcionalidades SCORM
**Tareas:**
1. ✅ Añadir tracking avanzado (tiempo por sección)
2. ✅ Mejorar estilos para diferentes LMS
3. ✅ Añadir cuestionarios/evaluaciones (opcional)
4. ✅ Optimizar tamaño de paquetes
5. ✅ Documentación completa
**Tiempo estimado:** 2-3 días
---
## 🛠️ Herramientas y Dependencias
### Dependencias Nuevas Necesarias
```json
{
"devDependencies": {
"jszip": "^3.10.1", // Generar ZIP
"fast-xml-parser": "^4.3.2", // Generar XML
"@types/jszip": "^3.4.1"
}
}
```
### Herramientas Existentes (Reutilizar)
- ✅ `remark` / `rehype` (ya instalados)
- ✅ `react-markdown` (para referencia, pero SCORM usará HTML estático)
- ✅ Tailwind CSS (compilar a CSS estático)
### Scripts NPM Nuevos
```json
{
"scripts": {
"scorm:generate": "tsx scripts/generate-scorm.ts",
"scorm:generate:abcde": "tsx scripts/generate-scorm.ts --guide abcde-operativo",
"scorm:generate:rcp": "tsx scripts/generate-scorm.ts --guide rcp-adulto-svb",
"scorm:build:all": "npm run scorm:generate"
}
}
```
---
## 📐 Diseño Técnico Detallado
### 1. Conversión Markdown → HTML
**Estrategia:**
- Usar `remark` + `rehype` para parsear Markdown
- Convertir a HTML con plugins:
- `remark-gfm` (tablas, strikethrough)
- `rehype-highlight` (syntax highlighting)
- `rehype-raw` (HTML crudo si existe)
- Aplicar clases Tailwind compiladas
**Código ejemplo:**
```typescript
import { remark } from 'remark';
import remarkGfm from 'remark-gfm';
import rehypeHighlight from 'rehype-highlight';
import rehypeStringify from 'rehype-stringify';
import remarkRehype from 'remark-rehype';
async function markdownToHtml(markdown: string): Promise<string> {
const result = await remark()
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeHighlight)
.use(rehypeStringify)
.process(markdown);
return result.toString();
}
```
### 2. Template HTML SCORM
**Estructura:**
```html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Guía de Refuerzo - [Título]</title>
<link rel="stylesheet" href="styles.css">
<script src="scorm-api.js"></script>
</head>
<body>
<div class="scorm-container">
<header>
<h1>[Título Guía]</h1>
<div class="progress">Sección X de 8</div>
</header>
<main>
<div class="section-content">
[HTML de la sección convertida desde Markdown]
</div>
<nav class="section-navigation">
<button id="prev">Anterior</button>
<button id="next">Siguiente</button>
</nav>
</main>
</div>
<script src="scorm-tracker.js"></script>
</body>
</html>
```
### 3. SCORM API Wrapper
**Funcionalidades:**
- Detectar LMS (SCORM 1.2 o 2004)
- Inicializar comunicación
- Guardar progreso
- Manejar errores
**Ejemplo:**
```javascript
// scorm-api.js
const SCORM = {
API: null,
initialized: false,
init() {
// Buscar API del LMS
this.API = this.findAPI();
if (this.API) {
this.initialized = true;
this.setValue("cmi.core.lesson_status", "incomplete");
}
},
setValue(element, value) {
if (!this.initialized) return false;
const result = this.API.LMSSetValue(element, value);
return result === "true";
},
getValue(element) {
if (!this.initialized) return "";
return this.API.LMSGetValue(element);
},
save() {
return this.API.LMSCommit("");
}
};
```
### 4. Generación de imsmanifest.xml
**Estructura básica:**
```xml
<?xml version="1.0" encoding="UTF-8"?>
<manifest identifier="abcde-operativo-scorm" version="1.0"
xmlns="http://www.imsproject.org/xsd/imscp_rootv1p1p2"
xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_rootv1p2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<metadata>
<schema>ADL SCORM</schema>
<schemaversion>1.2</schemaversion>
<title>ABCDE Operativo - Guía de Refuerzo</title>
<description>Guía formativa sobre el enfoque ABCDE</description>
</metadata>
<organizations default="TOC1">
<organization identifier="TOC1">
<title>ABCDE Operativo</title>
<item identifier="ITEM1" identifierref="RES1">
<title>Sección 1: Introducción</title>
</item>
<!-- ... más items ... -->
</organization>
</organizations>
<resources>
<resource identifier="RES1" type="webcontent" adlcp:scormtype="sco"
href="index.html">
<file href="index.html"/>
<file href="section-01.html"/>
<!-- ... más archivos ... -->
</resource>
</resources>
</manifest>
```
---
## ✅ Checklist de Implementación
### Fase 1: Infraestructura
- [ ] Crear carpeta `scorm/` y subcarpetas
- [ ] Instalar dependencias (`jszip`, `fast-xml-parser`)
- [ ] Crear template HTML básico
- [ ] Crear SCORM API wrapper
- [ ] Script de prueba: MD → HTML
### Fase 2: Generador
- [ ] Script convertir 8 secciones MD → HTML
- [ ] Generar `imsmanifest.xml`
- [ ] Integrar SCORM API
- [ ] Implementar tracking
- [ ] Copiar assets
- [ ] Generar ZIP
### Fase 3: Integración (Opcional)
- [ ] Extender `guides-index.ts`
- [ ] Botón "Descargar SCORM" en `GuideCard`
- [ ] Servir paquetes desde `public/`
- [ ] Página información SCORM
### Fase 4: Migración
- [ ] Convertir "ABCDE Operativo"
- [ ] Probar en LMS
- [ ] Convertir "RCP Adulto SVB"
- [ ] Documentar proceso
### Fase 5: Mejoras
- [ ] Tracking avanzado
- [ ] Optimización estilos
- [ ] Documentación completa
---
## 🚨 Riesgos y Mitigaciones
### Riesgo 1: Estilos Tailwind no funcionan en HTML estático
**Mitigación:** Compilar Tailwind a CSS estático antes de generar SCORM
### Riesgo 2: Imágenes no se cargan en SCORM
**Mitigación:** Copiar todas las imágenes al paquete y usar rutas relativas
### Riesgo 3: SCORM no funciona en algunos LMS
**Mitigación:** Probar en múltiples LMS (Moodle, Canvas, Blackboard)
### Riesgo 4: Tamaño de paquetes muy grande
**Mitigación:** Optimizar imágenes, minificar CSS/JS, code splitting
### Riesgo 5: Tracking no se guarda correctamente
**Mitigación:** Implementar logging, probar en LMS real, manejar errores
---
## 📊 Métricas de Éxito
1. **Funcionalidad:**
- ✅ Paquetes SCORM se importan correctamente en LMS
- ✅ Tracking funciona (progreso, completado)
- ✅ Navegación entre secciones funciona
- ✅ Contenido se ve correctamente
2. **Calidad:**
- ✅ HTML válido
- ✅ CSS funciona correctamente
- ✅ JavaScript sin errores
- ✅ Accesibilidad (WCAG básico)
3. **Compatibilidad:**
- ✅ SCORM 1.2 funciona
- ✅ Compatible con Moodle, Canvas, Blackboard
- ✅ Tamaño de paquete < 10MB (ideal)
4. **No regresiones:**
- ✅ App React sigue funcionando igual
- ✅ Guías Markdown siguen accesibles
- ✅ No se rompe nada existente
---
## 📚 Recursos y Referencias
### Documentación SCORM
- [SCORM 1.2 Specification](https://www.adlnet.gov/scorm/scorm-1-2/)
- [SCORM 2004 Specification](https://www.adlnet.gov/scorm/scorm-2004-4th-edition/)
- [Rustici SCORM Cloud (para testing)](https://cloud.scorm.com/)
### Herramientas
- [SCORM Test Suite](https://www.adlnet.gov/adl-research/scorm/)
- [Moodle (LMS de prueba gratuito)](https://moodle.org/)
### Librerías JavaScript
- `jszip` - Generar archivos ZIP
- `fast-xml-parser` - Parsear/generar XML
- `remark` / `rehype` - Procesar Markdown (ya instalados)
---
## 🎯 Próximos Pasos Inmediatos
1. **Revisar y aprobar este plan**
2. **Crear estructura de carpetas `scorm/`**
3. **Instalar dependencias necesarias**
4. **Crear script de prueba básico (Fase 1)**
5. **Iterar y mejorar**
---
**Estado:** ✅ Plan completo listo para implementación
**Última actualización:** 2024-12-30

106
docs/SCORM_QUICK_START.md Normal file
View file

@ -0,0 +1,106 @@
# 🚀 SCORM Quick Start Guide
**Guía rápida para empezar la conversión a SCORM**
---
## 📋 Checklist Rápido
### Antes de Empezar
- [ ] Leer `PLAN_CONVERSION_SCORM.md` completo
- [ ] Entender estructura actual de guías
- [ ] Tener acceso a un LMS de prueba (Moodle, Canvas, etc.)
### Fase 1: Setup Inicial
```bash
# 1. Crear estructura de carpetas
mkdir -p scorm/{generator,templates,packages,dist}
# 2. Instalar dependencias
npm install --save-dev jszip fast-xml-parser @types/jszip
# 3. Crear script base
touch scripts/generate-scorm.ts
```
---
## 🎯 Objetivo de la Primera Iteración
**Convertir 1 sección de Markdown a HTML estático con:**
- ✅ HTML válido
- ✅ Estilos básicos
- ✅ Estructura SCORM básica
---
## 📝 Ejemplo de Código Inicial
### `scripts/generate-scorm.ts` (Esqueleto)
```typescript
import { readFile } from 'fs/promises';
import { remark } from 'remark';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
async function convertMarkdownToHtml(markdownPath: string): Promise<string> {
const markdown = await readFile(markdownPath, 'utf-8');
const result = await remark()
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeStringify)
.process(markdown);
return result.toString();
}
// Uso
const html = await convertMarkdownToHtml('docs/consolidado/SECCION_01_ABCDE_OPERATIVO.md');
console.log(html);
```
---
## 🧪 Testing Inicial
1. **Probar conversión MD → HTML:**
```bash
npm run scorm:test
```
2. **Verificar HTML generado:**
- Abrir en navegador
- Verificar que se ve correctamente
- Verificar que no hay errores
3. **Probar en LMS (cuando tengas paquete):**
- Importar ZIP en Moodle/Canvas
- Verificar que se carga
- Verificar tracking básico
---
## 📚 Recursos Útiles
- **SCORM Test Suite:** https://www.adlnet.gov/adl-research/scorm/
- **Moodle (gratis):** https://moodle.org/
- **SCORM Cloud (testing):** https://cloud.scorm.com/
---
## ⚠️ Recordatorios Importantes
1. **NO modificar código existente** de la app React
2. **NO tocar** `GuideViewer`, `GuideMarkdownViewer`, etc.
3. **Sí crear** nueva carpeta `scorm/` separada
4. **Sí probar** cada paso antes de continuar
---
**Siguiente paso:** Revisar `PLAN_CONVERSION_SCORM.md` y empezar Fase 1

View file

@ -0,0 +1,272 @@
# 🚀 COMANDOS EXACTOS PARA CONFIGURAR DESPLIEGUE
## 📋 CONFIGURACIÓN INICIAL (Ejecutar en el servidor)
### Paso 1: Conectarse al servidor
```bash
ssh root@207.180.226.141
```
### Paso 2: Crear el hook post-receive
```bash
# Variables
GIT_DIR="/var/repos/emerges-tes.git"
APP_DIR="/var/www/emerges-tes"
HOOK_FILE="$GIT_DIR/hooks/post-receive"
LOG_FILE="/var/log/emerges-tes-deploy.log"
# Crear el hook
cat > "$HOOK_FILE" << 'HOOK_EOF'
#!/bin/bash
set -e
APP_DIR="/var/www/emerges-tes"
BRANCH="main"
LOG_FILE="/var/log/emerges-tes-deploy.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "=========================================="
log "🚀 Iniciando despliegue automático"
log "=========================================="
while read oldrev newrev refname; do
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
if [ "$branch" = "$BRANCH" ]; then
log "📦 Actualizando rama: $branch"
log " Commit anterior: $oldrev"
log " Commit nuevo: $newrev"
if [ ! -d "$APP_DIR" ]; then
log "❌ ERROR: Directorio $APP_DIR no existe"
exit 1
fi
cd "$APP_DIR" || {
log "❌ ERROR: No se puede acceder a $APP_DIR"
exit 1
}
log "📥 Obteniendo cambios del repositorio..."
git fetch origin "$BRANCH" || {
log "❌ ERROR: Fallo al hacer fetch"
exit 1
}
log "🔄 Haciendo checkout limpio..."
git reset --hard "origin/$BRANCH" || {
log "❌ ERROR: Fallo al hacer reset"
exit 1
}
log "🧹 Limpiando archivos no rastreados..."
git clean -fd || {
log "⚠️ ADVERTENCIA: Fallo al limpiar archivos"
}
log "📦 Instalando dependencias (npm install)..."
if ! npm install --production=false 2>&1 | tee -a "$LOG_FILE"; then
log "❌ ERROR: Fallo al instalar dependencias"
exit 1
fi
log "✅ Dependencias instaladas correctamente"
log "🔨 Construyendo aplicación (npm run build)..."
if ! npm run build 2>&1 | tee -a "$LOG_FILE"; then
log "❌ ERROR: Fallo al construir la aplicación"
exit 1
fi
log "✅ Build completado correctamente"
if [ ! -d "$APP_DIR/dist" ]; then
log "❌ ERROR: El directorio dist/ no existe después del build"
exit 1
fi
log "✅ Despliegue completado exitosamente"
log " Aplicación disponible en: $APP_DIR/dist"
log "=========================================="
exit 0
else
log "⏭️ Ignorando push en rama: $branch (solo se despliega $BRANCH)"
fi
done
log "⚠️ No se procesó ningún cambio"
exit 0
HOOK_EOF
# Dar permisos de ejecución
chmod +x "$HOOK_FILE"
# Verificar
ls -la "$HOOK_FILE"
```
### Paso 3: Configurar directorio de trabajo
```bash
# Si el directorio no existe, crearlo
if [ ! -d "$APP_DIR" ]; then
mkdir -p "$APP_DIR"
fi
# Si no tiene .git, clonar el repositorio
if [ ! -d "$APP_DIR/.git" ]; then
git clone "$GIT_DIR" "$APP_DIR"
fi
```
### Paso 4: Crear archivo de logs
```bash
# Crear archivo de logs
touch "$LOG_FILE"
chmod 666 "$LOG_FILE"
# Verificar
ls -la "$LOG_FILE"
```
### Paso 5: Verificar Node.js (si no está instalado)
```bash
# Verificar si Node.js está instalado
node --version || {
echo "⚠️ Node.js no está instalado. Instalando..."
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
node --version
npm --version
}
```
---
## 🧪 PROBAR EL DESPLIEGUE
### Desde tu máquina local:
```bash
cd /home/planetazuzu/guia-tes
# Hacer un cambio de prueba
echo "# Test deploy $(date)" >> README.md
git add README.md
git commit -m "test: probar despliegue automático"
# Push (esto activará el hook automáticamente)
git push production main
```
### En el servidor, ver logs:
```bash
# Ver logs en tiempo real
tail -f /var/log/emerges-tes-deploy.log
```
### Verificar build:
```bash
# Verificar que dist/ existe
ls -la /var/www/emerges-tes/dist/
# Ver contenido
ls -la /var/www/emerges-tes/dist/assets/ 2>/dev/null | head -10
```
---
## ✅ VERIFICACIÓN COMPLETA
Ejecutar en el servidor:
```bash
# 1. Hook existe y es ejecutable
test -x /var/repos/emerges-tes.git/hooks/post-receive && echo "✅ Hook OK" || echo "❌ Hook no ejecutable"
# 2. Directorio de trabajo existe
test -d /var/www/emerges-tes && echo "✅ Directorio OK" || echo "❌ Directorio no existe"
# 3. Logs se pueden escribir
test -w /var/log/emerges-tes-deploy.log && echo "✅ Logs OK" || echo "❌ Logs no escribibles"
# 4. Node.js instalado
command -v node >/dev/null && echo "✅ Node.js: $(node --version)" || echo "❌ Node.js no instalado"
# 5. npm instalado
command -v npm >/dev/null && echo "✅ npm: $(npm --version)" || echo "❌ npm no instalado"
```
---
## 🔍 TROUBLESHOOTING RÁPIDO
### El hook no se ejecuta
```bash
# Verificar permisos
ls -la /var/repos/emerges-tes.git/hooks/post-receive
# Debe mostrar: -rwxr-xr-x
# Si no, ejecutar:
chmod +x /var/repos/emerges-tes.git/hooks/post-receive
```
### Ver logs de errores
```bash
# Ver últimos 100 líneas
tail -n 100 /var/log/emerges-tes-deploy.log
# Buscar errores
grep -i error /var/log/emerges-tes-deploy.log
# Ver todo el log
cat /var/log/emerges-tes-deploy.log
```
### Probar manualmente
```bash
# Desde el servidor, probar el proceso manualmente
cd /var/www/emerges-tes
git pull origin main
npm install
npm run build
# Verificar resultado
ls -la dist/
```
---
## 📊 ESTRUCTURA FINAL
```
/var/repos/emerges-tes.git/ # Repositorio bare
└── hooks/
└── post-receive # Hook (ejecutable)
/var/www/emerges-tes/ # Directorio de trabajo
├── .git/ # Clon del repositorio
├── src/ # Código fuente
├── dist/ # Build de producción (generado)
└── node_modules/ # Dependencias (generado)
/var/log/emerges-tes-deploy.log # Logs de despliegue
```
---
**✅ Listo para usar**
Cada `git push production main` desde local actualizará automáticamente la app en el servidor.

View file

@ -0,0 +1,298 @@
# 🚀 Sistema de Despliegue Automático - EMERGES TES
Sistema de despliegue automático usando Git hooks (post-receive) en repositorio bare.
---
## 📋 ARQUITECTURA
```
┌─────────────────┐
│ Máquina Local │
│ (desarrollo) │
└────────┬────────┘
│ git push production main
┌─────────────────┐
│ Servidor │
│ │
│ /var/repos/ │
│ emerges-tes.git│ ◄── Repositorio bare
│ └─ hooks/ │
│ └─ post- │
│ receive│ ◄── Hook que se ejecuta automáticamente
└────────┬────────┘
│ Ejecuta: checkout → npm install → npm run build
┌─────────────────┐
│ /var/www/ │
│ emerges-tes/ │ ◄── Directorio de trabajo
│ ├─ .git/ │
│ ├─ src/ │
│ ├─ dist/ │ ◄── Build de producción (servir con Nginx)
│ └─ ... │
└─────────────────┘
```
---
## 🔧 CONFIGURACIÓN INICIAL (Solo una vez)
### Paso 1: Subir el hook al servidor
Desde tu máquina local:
```bash
cd /home/planetazuzu/guia-tes
# Copiar el hook al servidor
scp scripts/deploy/post-receive root@207.180.226.141:/tmp/post-receive
```
### Paso 2: Configurar en el servidor
Conectarse al servidor:
```bash
ssh root@207.180.226.141
```
En el servidor, ejecutar:
```bash
# Variables
GIT_DIR="/var/repos/emerges-tes.git"
APP_DIR="/var/www/emerges-tes"
HOOK_FILE="$GIT_DIR/hooks/post-receive"
# 1. Copiar el hook
cp /tmp/post-receive "$HOOK_FILE"
# 2. Dar permisos de ejecución
chmod +x "$HOOK_FILE"
# 3. Verificar que el directorio de trabajo existe
if [ ! -d "$APP_DIR" ]; then
mkdir -p "$APP_DIR"
# Si el directorio está vacío, clonar
if [ ! -d "$APP_DIR/.git" ]; then
git clone "$GIT_DIR" "$APP_DIR"
fi
fi
# 4. Crear archivo de logs
touch /var/log/emerges-tes-deploy.log
chmod 666 /var/log/emerges-tes-deploy.log
```
---
## 🧪 PROBAR EL DESPLIEGUE
### Desde tu máquina local:
```bash
cd /home/planetazuzu/guia-tes
# Hacer un cambio pequeño (opcional)
echo "# Test deploy $(date)" >> README.md
git add README.md
git commit -m "test: probar despliegue automático"
# Hacer push (esto activará el hook automáticamente)
git push production main
```
### En el servidor, verificar logs:
```bash
# Ver logs en tiempo real
tail -f /var/log/emerges-tes-deploy.log
# O ver las últimas líneas
tail -n 50 /var/log/emerges-tes-deploy.log
```
### Verificar que el build se creó:
```bash
# Verificar que dist/ existe
ls -la /var/www/emerges-tes/dist/
# Verificar que hay archivos HTML/JS
ls -la /var/www/emerges-tes/dist/assets/
```
---
## 📝 QUÉ HACE EL HOOK
El hook `post-receive` se ejecuta automáticamente después de cada `git push` y realiza:
1. **Detecta el push** en la rama `main`
2. **Hace fetch** de los últimos cambios
3. **Checkout limpio** (`git reset --hard`) para asegurar que el código coincide exactamente con el repositorio
4. **Limpia archivos** no rastreados (`git clean -fd`)
5. **Instala dependencias** (`npm install`)
6. **Construye la aplicación** (`npm run build`)
7. **Verifica** que el directorio `dist/` se creó correctamente
8. **Registra todo** en `/var/log/emerges-tes-deploy.log`
---
## 🔍 TROUBLESHOOTING
### El hook no se ejecuta
```bash
# Verificar que el hook existe y es ejecutable
ls -la /var/repos/emerges-tes.git/hooks/post-receive
# Debe mostrar: -rwxr-xr-x (permisos de ejecución)
# Si no, ejecutar:
chmod +x /var/repos/emerges-tes.git/hooks/post-receive
```
### Error: "npm: command not found"
```bash
# Instalar Node.js y npm en el servidor
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
# Verificar instalación
node --version
npm --version
```
### Error: "Permission denied"
```bash
# Verificar permisos del directorio de trabajo
ls -la /var/www/emerges-tes
# Ajustar propietario si es necesario
sudo chown -R $USER:$USER /var/www/emerges-tes
```
### El build falla
```bash
# Ver logs detallados
tail -f /var/log/emerges-tes-deploy.log
# Probar manualmente en el servidor
cd /var/www/emerges-tes
npm install
npm run build
```
### Verificar que el hook se ejecutó
```bash
# Ver los últimos logs
tail -n 100 /var/log/emerges-tes-deploy.log
# Buscar errores
grep -i error /var/log/emerges-tes-deploy.log
```
---
## 🔄 FLUJO COMPLETO DE DESPLIEGUE
```
1. Desarrollador hace cambios localmente
└─ git add .
└─ git commit -m "mensaje"
└─ git push production main
2. Git envía cambios al servidor
└─ Se activa el hook post-receive
3. Hook ejecuta automáticamente:
├─ git fetch origin main
├─ git reset --hard origin/main
├─ git clean -fd
├─ npm install
├─ npm run build
└─ Verifica dist/
4. Aplicación actualizada en /var/www/emerges-tes/dist/
└─ Servir con Nginx/Apache
```
---
## 📊 CONFIGURACIÓN NGINX (Opcional)
Si quieres servir la app con Nginx:
```nginx
server {
listen 80;
server_name tu-dominio.com;
root /var/www/emerges-tes/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# Cache para assets estáticos
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
```
---
## ✅ VERIFICACIÓN FINAL
Después de configurar, verifica:
```bash
# 1. Hook existe y es ejecutable
test -x /var/repos/emerges-tes.git/hooks/post-receive && echo "✅ Hook OK" || echo "❌ Hook no ejecutable"
# 2. Directorio de trabajo existe
test -d /var/www/emerges-tes && echo "✅ Directorio OK" || echo "❌ Directorio no existe"
# 3. Logs se pueden escribir
test -w /var/log/emerges-tes-deploy.log && echo "✅ Logs OK" || echo "❌ Logs no escribibles"
# 4. Node.js instalado
command -v node >/dev/null && echo "✅ Node.js OK" || echo "❌ Node.js no instalado"
```
---
## 🎯 COMANDOS RÁPIDOS
```bash
# Ver logs en tiempo real
tail -f /var/log/emerges-tes-deploy.log
# Ver último despliegue
tail -n 50 /var/log/emerges-tes-deploy.log
# Forzar despliegue manual (desde servidor)
cd /var/www/emerges-tes
git pull origin main
npm install
npm run build
# Verificar build
ls -la /var/www/emerges-tes/dist/
```
---
**✅ Sistema listo para producción**
Cada `git push production main` desde tu máquina local actualizará automáticamente la aplicación en el servidor.

View file

@ -0,0 +1,129 @@
# ✅ Sistema de Despliegue Automático - CONFIGURADO
**Fecha:** 2024-12-30
**Estado:** ✅ Funcionando correctamente
---
## 📋 Configuración Completada
- ✅ **Repositorio bare:** `/var/repos/emerges-tes.git`
- ✅ **Hook post-receive:** Configurado y ejecutable
- ✅ **Directorio de trabajo:** `/var/www/emerges-tes`
- ✅ **Build de producción:** `/var/www/emerges-tes/dist/`
- ✅ **Logs:** `/var/log/emerges-tes-deploy.log`
- ✅ **Node.js:** v18.19.1 instalado
- ✅ **Despliegue manual:** Probado y funcionando
- ✅ **Despliegue automático:** Probado y funcionando
---
## 🔄 Flujo Automático
```
1. git push production main (desde máquina local)
2. Hook post-receive se ejecuta automáticamente
3. git fetch origin main
4. git reset --hard origin/main (checkout limpio)
5. git clean -fd (limpiar archivos no rastreados)
6. npm install (instalar dependencias)
7. npm run build (construir aplicación)
8. Aplicación actualizada en /var/www/emerges-tes/dist/
```
---
## 📊 Comandos Útiles
### Ver logs
```bash
# Últimas 50 líneas
tail -n 50 /var/log/emerges-tes-deploy.log
# En tiempo real
tail -f /var/log/emerges-tes-deploy.log
# Buscar errores
grep -i error /var/log/emerges-tes-deploy.log
```
### Verificar estado
```bash
# Estado del repositorio
cd /var/www/emerges-tes && git status
# Verificar build
ls -la /var/www/emerges-tes/dist/
# Ver archivos del build
ls -la /var/www/emerges-tes/dist/assets/ | head -10
```
### Despliegue manual (si es necesario)
```bash
cd /var/www/emerges-tes
git pull origin main
npm install
npm run build
```
---
## 🎯 Próximos Pasos (Opcional)
### Configurar Nginx para servir la aplicación
```nginx
server {
listen 80;
server_name tu-dominio.com;
root /var/www/emerges-tes/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# Cache para assets estáticos
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
```
### Configurar SSL (Let's Encrypt)
```bash
# Instalar certbot
apt-get install certbot python3-certbot-nginx
# Obtener certificado
certbot --nginx -d tu-dominio.com
```
---
## ✅ Verificación Final
El sistema está completamente funcional:
- ✅ Cada `git push production main` actualiza automáticamente la app
- ✅ Los logs registran todo el proceso
- ✅ El build se genera correctamente en `dist/`
- ✅ El sistema es robusto y maneja errores
**Sistema listo para producción** 🚀

View file

@ -0,0 +1,36 @@
#!/bin/bash
# Script para actualizar el hook post-receive en el servidor
SERVER="root@207.180.226.141"
HOOK_LOCAL="./scripts/deploy/post-receive"
HOOK_REMOTE="/var/repos/emerges-tes.git/hooks/post-receive"
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ 🔧 ACTUALIZANDO HOOK POST-RECEIVE EN SERVIDOR ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo ""
# Verificar que el archivo local existe
if [ ! -f "$HOOK_LOCAL" ]; then
echo "❌ ERROR: No se encuentra $HOOK_LOCAL"
exit 1
fi
echo "📤 Copiando hook al servidor..."
scp "$HOOK_LOCAL" "$SERVER:$HOOK_REMOTE" || {
echo "❌ ERROR: No se pudo copiar el hook"
exit 1
}
echo "🔐 Configurando permisos de ejecución..."
ssh "$SERVER" "chmod +x $HOOK_REMOTE" || {
echo "❌ ERROR: No se pudieron configurar permisos"
exit 1
}
echo ""
echo "✅ Hook actualizado correctamente"
echo ""
echo "🧪 Para probar, haz un push:"
echo " git push production main"

View file

@ -0,0 +1,81 @@
#!/bin/bash
# Script de corrección rápida para el servidor
# Ejecutar en el servidor: bash corregir-servidor.sh
APP_DIR="/var/www/emerges-tes"
GIT_DIR="/var/repos/emerges-tes.git"
LOG_FILE="/var/log/emerges-tes-deploy.log"
echo "🔧 Corrigiendo configuración..."
echo ""
# 1. Corregir archivo de logs (quitar tilde si existe)
echo "1⃣ Corrigiendo archivo de logs..."
touch "$LOG_FILE"
chmod 666 "$LOG_FILE" 2>/dev/null || sudo chmod 666 "$LOG_FILE"
echo " ✅ Logs configurados: $LOG_FILE"
# 2. Verificar que el directorio de trabajo es un repositorio Git
echo ""
echo "2⃣ Verificando directorio de trabajo..."
if [ -d "$APP_DIR" ]; then
if [ ! -d "$APP_DIR/.git" ]; then
echo " ⚠️ Directorio existe pero no es un repositorio Git"
echo " 🔧 Inicializando repositorio..."
cd "$APP_DIR"
git init
git remote add origin "$GIT_DIR" 2>/dev/null || git remote set-url origin "$GIT_DIR"
git fetch origin
git checkout -b main origin/main 2>/dev/null || {
echo " ⚠️ No se pudo hacer checkout automático"
echo " 💡 Ejecutar manualmente: cd $APP_DIR && git pull origin main"
}
echo " ✅ Repositorio inicializado"
else
echo " ✅ Directorio ya es un repositorio Git"
cd "$APP_DIR"
echo " 📍 Rama actual: $(git branch --show-current 2>/dev/null || echo 'desconocida')"
# Asegurar que el remoto está configurado
if ! git remote get-url origin >/dev/null 2>&1; then
echo " 🔧 Configurando remoto..."
git remote add origin "$GIT_DIR"
fi
fi
else
echo " ❌ Directorio no existe"
exit 1
fi
# 3. Verificar hook
echo ""
echo "3⃣ Verificando hook..."
HOOK_FILE="$GIT_DIR/hooks/post-receive"
if [ -f "$HOOK_FILE" ]; then
if [ -x "$HOOK_FILE" ]; then
echo " ✅ Hook existe y es ejecutable"
else
echo " ⚠️ Hook no es ejecutable. Corrigiendo..."
chmod +x "$HOOK_FILE"
echo " ✅ Permisos corregidos"
fi
else
echo " ❌ Hook no existe. Crear primero."
fi
echo ""
echo "✅ Corrección completada"
echo ""
echo "📋 Estado actual:"
echo " - Directorio: $APP_DIR"
echo " - Logs: $LOG_FILE"
echo " - Hook: $HOOK_FILE"
echo ""
echo "🧪 Próximos pasos:"
echo " 1. Desde tu MÁQUINA LOCAL (no desde el servidor):"
echo " cd /home/planetazuzu/guia-tes"
echo " git push production main"
echo ""
echo " 2. En el SERVIDOR, ver logs:"
echo " tail -f $LOG_FILE"

View file

@ -0,0 +1,139 @@
#!/bin/bash
# Script de diagnóstico para el servidor
# Ejecutar en el servidor: bash diagnostico-servidor.sh
APP_DIR="/var/www/emerges-tes"
GIT_DIR="/var/repos/emerges-tes.git"
LOG_FILE="/var/log/emerges-tes-deploy.log"
echo "🔍 DIAGNÓSTICO DEL SERVIDOR"
echo "============================"
echo ""
# 1. Verificar Node.js y npm
echo "1⃣ Node.js y npm:"
if command -v node >/dev/null 2>&1; then
echo " ✅ Node.js: $(node --version)"
else
echo " ❌ Node.js NO está instalado"
echo " 💡 Instalar con: curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs"
fi
if command -v npm >/dev/null 2>&1; then
echo " ✅ npm: $(npm --version)"
else
echo " ❌ npm NO está instalado"
fi
echo ""
# 2. Verificar directorio de trabajo
echo "2⃣ Directorio de trabajo ($APP_DIR):"
if [ -d "$APP_DIR" ]; then
echo " ✅ Directorio existe"
cd "$APP_DIR"
if [ -d ".git" ]; then
echo " ✅ Es un repositorio Git"
echo " 📍 Rama: $(git branch --show-current 2>/dev/null || echo 'desconocida')"
echo " 🔗 Remoto: $(git remote get-url origin 2>/dev/null || echo 'no configurado')"
# Verificar si está actualizado
git fetch origin main 2>/dev/null || echo " ⚠️ No se pudo hacer fetch"
LOCAL=$(git rev-parse HEAD 2>/dev/null || echo "desconocido")
REMOTE=$(git rev-parse origin/main 2>/dev/null || echo "desconocido")
echo " 📦 Commit local: ${LOCAL:0:7}"
echo " 📦 Commit remoto: ${REMOTE:0:7}"
if [ "$LOCAL" != "$REMOTE" ] && [ "$REMOTE" != "desconocido" ]; then
echo " ⚠️ El directorio NO está actualizado con el repositorio"
else
echo " ✅ Directorio actualizado"
fi
else
echo " ❌ NO es un repositorio Git"
fi
# Verificar package.json
if [ -f "package.json" ]; then
echo " ✅ package.json existe"
else
echo " ❌ package.json NO existe"
fi
# Verificar node_modules
if [ -d "node_modules" ]; then
echo " ✅ node_modules existe"
else
echo " ⚠️ node_modules NO existe (necesita npm install)"
fi
# Verificar dist/
if [ -d "dist" ]; then
echo " ✅ dist/ existe"
echo " 📁 Archivos en dist/: $(ls -1 dist/ 2>/dev/null | wc -l)"
else
echo " ❌ dist/ NO existe (necesita npm run build)"
fi
else
echo " ❌ Directorio NO existe"
fi
echo ""
# 3. Verificar hook
echo "3⃣ Hook post-receive:"
HOOK_FILE="$GIT_DIR/hooks/post-receive"
if [ -f "$HOOK_FILE" ]; then
if [ -x "$HOOK_FILE" ]; then
echo " ✅ Hook existe y es ejecutable"
else
echo " ⚠️ Hook existe pero NO es ejecutable"
echo " 💡 Ejecutar: chmod +x $HOOK_FILE"
fi
else
echo " ❌ Hook NO existe"
fi
echo ""
# 4. Verificar logs
echo "4⃣ Logs:"
if [ -f "$LOG_FILE" ]; then
if [ -r "$LOG_FILE" ]; then
echo " ✅ Archivo de logs existe"
if [ -s "$LOG_FILE" ]; then
echo " 📋 Últimas 10 líneas del log:"
tail -n 10 "$LOG_FILE" | sed 's/^/ /'
else
echo " ⚠️ Archivo de logs está vacío (nunca se ha ejecutado el hook)"
fi
else
echo " ⚠️ Archivo de logs existe pero NO es legible"
fi
else
echo " ⚠️ Archivo de logs NO existe"
echo " 💡 Crear con: touch $LOG_FILE && chmod 666 $LOG_FILE"
fi
echo ""
# 5. Recomendaciones
echo "💡 RECOMENDACIONES:"
echo ""
if [ ! -d "$APP_DIR/dist" ]; then
echo " 🔨 Hacer despliegue manual para probar:"
echo " cd $APP_DIR"
echo " git pull origin main"
echo " npm install"
echo " npm run build"
echo ""
fi
if ! command -v node >/dev/null 2>&1; then
echo " 📦 Instalar Node.js primero"
echo ""
fi
echo " 🧪 Para probar el despliegue automático:"
echo " Desde tu máquina local: git push production main"
echo " Luego ver logs: tail -f $LOG_FILE"
echo ""

124
scripts/deploy/post-receive Executable file
View file

@ -0,0 +1,124 @@
#!/bin/bash
# Hook post-receive para despliegue automático
# Ubicación: /var/repos/emerges-tes.git/hooks/post-receive
set -e # Salir si hay error
# Configuración
APP_DIR="/var/www/emerges-tes"
GIT_DIR="/var/repos/emerges-tes.git"
BRANCH="main"
LOG_FILE="/var/log/emerges-tes-deploy.log"
# Función de logging
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "=========================================="
log "🚀 Iniciando despliegue automático"
log "=========================================="
# Leer la rama que se está actualizando
while read oldrev newrev refname; do
# Usar GIT_DIR para obtener el nombre de la rama desde el repositorio bare
branch=$(git --git-dir="$GIT_DIR" rev-parse --symbolic --abbrev-ref $refname 2>/dev/null || echo "$refname" | sed 's|refs/heads/||')
if [ "$branch" = "$BRANCH" ]; then
log "📦 Actualizando rama: $branch"
log " Commit anterior: $oldrev"
log " Commit nuevo: $newrev"
# Verificar que el directorio de trabajo existe
if [ ! -d "$APP_DIR" ]; then
log "❌ ERROR: Directorio $APP_DIR no existe"
exit 1
fi
# Ir al directorio de trabajo
cd "$APP_DIR" || {
log "❌ ERROR: No se puede acceder a $APP_DIR"
exit 1
}
# Usar git directamente con --work-tree y --git-dir para evitar problemas de work tree
# Esto funciona tanto si APP_DIR es un repositorio git como si no lo es
# Si no existe .git, inicializar o clonar
if [ ! -d "$APP_DIR/.git" ]; then
log "⚠️ $APP_DIR no es un repositorio git, clonando..."
# Si el directorio tiene contenido, hacer backup o limpiar
if [ "$(ls -A $APP_DIR 2>/dev/null)" ]; then
log "⚠️ Directorio no vacío, haciendo backup..."
mv "$APP_DIR" "${APP_DIR}.backup.$(date +%s)" 2>/dev/null || true
fi
# Clonar desde el repositorio bare
git clone "$GIT_DIR" "$APP_DIR" || {
log "❌ ERROR: No se pudo clonar repositorio"
exit 1
}
cd "$APP_DIR" || exit 1
git checkout "$BRANCH" || {
log "❌ ERROR: No se pudo hacer checkout de $BRANCH"
exit 1
}
else
# Si ya es un repositorio, usar git normal
cd "$APP_DIR" || exit 1
# Obtener los últimos cambios
log "📥 Obteniendo cambios del repositorio..."
git fetch "$GIT_DIR" "$BRANCH" || {
log "❌ ERROR: Fallo al hacer fetch"
exit 1
}
# Resetear a la versión más reciente (checkout limpio)
log "🔄 Haciendo checkout limpio..."
git reset --hard "FETCH_HEAD" || {
log "❌ ERROR: Fallo al hacer reset"
exit 1
}
fi
# Limpiar archivos no rastreados (opcional, pero recomendado)
log "🧹 Limpiando archivos no rastreados..."
git clean -fd || {
log "⚠️ ADVERTENCIA: Fallo al limpiar archivos"
}
# Instalar dependencias
log "📦 Instalando dependencias (npm install)..."
if ! npm install --production=false 2>&1 | tee -a "$LOG_FILE"; then
log "❌ ERROR: Fallo al instalar dependencias"
exit 1
fi
log "✅ Dependencias instaladas correctamente"
# Build de producción
log "🔨 Construyendo aplicación (npm run build)..."
if ! npm run build 2>&1 | tee -a "$LOG_FILE"; then
log "❌ ERROR: Fallo al construir la aplicación"
exit 1
fi
log "✅ Build completado correctamente"
# Verificar que el build se creó
if [ ! -d "$APP_DIR/dist" ]; then
log "❌ ERROR: El directorio dist/ no existe después del build"
exit 1
fi
log "✅ Despliegue completado exitosamente"
log " Aplicación disponible en: $APP_DIR/dist"
log "=========================================="
exit 0
else
log "⏭️ Ignorando push en rama: $branch (solo se despliega $BRANCH)"
fi
done
log "⚠️ No se procesó ningún cambio"
exit 0

159
scripts/deploy/setup-deploy.sh Executable file
View file

@ -0,0 +1,159 @@
#!/bin/bash
# Script para configurar el sistema de despliegue automático
# Ejecutar en el servidor: sudo ./setup-deploy.sh
set -e
APP_DIR="/var/www/emerges-tes"
GIT_DIR="/var/repos/emerges-tes.git"
HOOK_FILE="$GIT_DIR/hooks/post-receive"
LOG_FILE="/var/log/emerges-tes-deploy.log"
echo "🔧 Configurando sistema de despliegue automático..."
echo ""
# Verificar que el repositorio bare existe
if [ ! -d "$GIT_DIR" ]; then
echo "❌ ERROR: El repositorio bare no existe en $GIT_DIR"
echo " Créalo primero con: git init --bare $GIT_DIR"
exit 1
fi
# Verificar que el directorio de trabajo existe
if [ ! -d "$APP_DIR" ]; then
echo "📁 Creando directorio de trabajo: $APP_DIR"
sudo mkdir -p "$APP_DIR"
sudo chown -R $USER:$USER "$APP_DIR" || {
echo "⚠️ No se pudo cambiar propietario. Asegúrate de tener permisos."
}
fi
# Si el directorio está vacío, clonar el repositorio
if [ ! -d "$APP_DIR/.git" ]; then
echo "📥 Clonando repositorio en $APP_DIR..."
git clone "$GIT_DIR" "$APP_DIR" || {
echo "❌ ERROR: No se pudo clonar el repositorio"
exit 1
}
fi
# Crear el hook post-receive
echo "📝 Creando hook post-receive..."
# Copiar el hook desde el proyecto local (si existe)
if [ -f "scripts/deploy/post-receive" ]; then
sudo cp "scripts/deploy/post-receive" "$HOOK_FILE"
else
# Si no existe, crear directamente
sudo tee "$HOOK_FILE" > /dev/null << 'HOOK_EOF'
#!/bin/bash
# Hook post-receive para despliegue automático
# Ubicación: /var/repos/emerges-tes.git/hooks/post-receive
set -e
APP_DIR="/var/www/emerges-tes"
GIT_DIR="/var/repos/emerges-tes.git"
BRANCH="main"
LOG_FILE="/var/log/emerges-tes-deploy.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "=========================================="
log "🚀 Iniciando despliegue automático"
log "=========================================="
while read oldrev newrev refname; do
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
if [ "$branch" = "$BRANCH" ]; then
log "📦 Actualizando rama: $branch"
log " Commit anterior: $oldrev"
log " Commit nuevo: $newrev"
if [ ! -d "$APP_DIR" ]; then
log "❌ ERROR: Directorio $APP_DIR no existe"
exit 1
fi
cd "$APP_DIR" || {
log "❌ ERROR: No se puede acceder a $APP_DIR"
exit 1
}
log "📥 Obteniendo cambios del repositorio..."
git fetch origin "$BRANCH" || {
log "❌ ERROR: Fallo al hacer fetch"
exit 1
}
log "🔄 Haciendo checkout limpio..."
git reset --hard "origin/$BRANCH" || {
log "❌ ERROR: Fallo al hacer reset"
exit 1
}
log "🧹 Limpiando archivos no rastreados..."
git clean -fd || {
log "⚠️ ADVERTENCIA: Fallo al limpiar archivos"
}
log "📦 Instalando dependencias (npm install)..."
if ! npm install --production=false 2>&1 | tee -a "$LOG_FILE"; then
log "❌ ERROR: Fallo al instalar dependencias"
exit 1
fi
log "✅ Dependencias instaladas correctamente"
log "🔨 Construyendo aplicación (npm run build)..."
if ! npm run build 2>&1 | tee -a "$LOG_FILE"; then
log "❌ ERROR: Fallo al construir la aplicación"
exit 1
fi
log "✅ Build completado correctamente"
if [ ! -d "$APP_DIR/dist" ]; then
log "❌ ERROR: El directorio dist/ no existe después del build"
exit 1
fi
log "✅ Despliegue completado exitosamente"
log " Aplicación disponible en: $APP_DIR/dist"
log "=========================================="
exit 0
else
log "⏭️ Ignorando push en rama: $branch (solo se despliega $BRANCH)"
fi
done
log "⚠️ No se procesó ningún cambio"
exit 0
HOOK_EOF
fi
# Dar permisos de ejecución al hook
echo "🔐 Configurando permisos..."
sudo chmod +x "$HOOK_FILE"
sudo chown $USER:$USER "$HOOK_FILE" 2>/dev/null || true
# Crear directorio de logs si no existe
echo "📋 Configurando logs..."
sudo touch "$LOG_FILE"
sudo chmod 666 "$LOG_FILE" 2>/dev/null || sudo chmod 644 "$LOG_FILE"
echo ""
echo "✅ Configuración completada"
echo ""
echo "📋 Resumen:"
echo " - Hook: $HOOK_FILE"
echo " - Directorio app: $APP_DIR"
echo " - Logs: $LOG_FILE"
echo ""
echo "🧪 Para probar el despliegue:"
echo " 1. Desde tu máquina local: git push production main"
echo " 2. Ver logs: tail -f $LOG_FILE"
echo ""

61
scripts/deploy/test-deploy.sh Executable file
View file

@ -0,0 +1,61 @@
#!/bin/bash
# Script para probar el despliegue desde la máquina local
# Ejecutar desde: /home/planetazuzu/guia-tes
set -e
echo "🧪 Probando despliegue automático..."
echo ""
# Verificar que estamos en el directorio correcto
if [ ! -f "package.json" ]; then
echo "❌ ERROR: No estás en el directorio del proyecto"
echo " Ejecuta: cd /home/planetazuzu/guia-tes"
exit 1
fi
# Verificar que el remoto production existe
if ! git remote get-url production >/dev/null 2>&1; then
echo "❌ ERROR: Remoto 'production' no configurado"
echo " Configura con: git remote add production root@207.180.226.141:/var/repos/emerges-tes.git"
exit 1
fi
echo "✅ Directorio correcto"
echo "✅ Remoto 'production' configurado"
echo ""
# Hacer un cambio pequeño para probar
echo "📝 Creando cambio de prueba..."
echo "" >> README.md
echo "<!-- Test deploy $(date '+%Y-%m-%d %H:%M:%S') -->" >> README.md
# Commit
echo "💾 Haciendo commit..."
git add README.md
git commit -m "test: probar despliegue automático $(date '+%Y-%m-%d %H:%M:%S')" || {
echo "⚠️ No hay cambios nuevos para commitear"
echo " Haciendo push de commits existentes..."
}
# Push
echo ""
echo "🚀 Haciendo push a producción..."
echo " Esto activará el hook post-receive automáticamente"
echo ""
if git push production main; then
echo ""
echo "✅ Push completado"
echo ""
echo "📋 Próximos pasos:"
echo " 1. Conectarte al servidor: ssh root@207.180.226.141"
echo " 2. Ver logs en tiempo real: tail -f /var/log/emerges-tes-deploy.log"
echo " 3. Verificar build: ls -la /var/www/emerges-tes/dist/"
else
echo ""
echo "❌ Error en el push"
echo " Verifica la conexión SSH y los permisos"
exit 1
fi

View file

@ -0,0 +1,116 @@
#!/bin/bash
# Script para verificar y corregir la configuración en el servidor
# Ejecutar en el servidor: bash verificar-servidor.sh
set -e
GIT_DIR="/var/repos/emerges-tes.git"
APP_DIR="/var/www/emerges-tes"
HOOK_FILE="$GIT_DIR/hooks/post-receive"
LOG_FILE="/var/log/emerges-tes-deploy.log"
echo "🔍 Verificando configuración del despliegue..."
echo ""
# 1. Verificar hook
echo "1⃣ Verificando hook post-receive..."
if [ -f "$HOOK_FILE" ]; then
if [ -x "$HOOK_FILE" ]; then
echo " ✅ Hook existe y es ejecutable"
else
echo " ⚠️ Hook existe pero no es ejecutable. Corrigiendo..."
chmod +x "$HOOK_FILE"
echo " ✅ Permisos corregidos"
fi
else
echo " ❌ Hook no existe. Crear primero con los comandos de configuración."
exit 1
fi
# 2. Verificar directorio de trabajo
echo ""
echo "2⃣ Verificando directorio de trabajo..."
if [ -d "$APP_DIR" ]; then
if [ -d "$APP_DIR/.git" ]; then
echo " ✅ Directorio existe y es un repositorio Git"
echo " 📍 Rama actual: $(cd "$APP_DIR" && git branch --show-current 2>/dev/null || echo 'desconocida')"
else
echo " ⚠️ Directorio existe pero no es un repositorio Git"
echo " 🔧 Inicializando repositorio..."
cd "$APP_DIR"
git init
git remote add origin "$GIT_DIR" 2>/dev/null || git remote set-url origin "$GIT_DIR"
git fetch origin
git checkout -b main origin/main 2>/dev/null || git checkout main 2>/dev/null || echo " ⚠️ No se pudo hacer checkout automático"
echo " ✅ Repositorio inicializado"
fi
else
echo " ❌ Directorio no existe. Creando..."
mkdir -p "$APP_DIR"
git clone "$GIT_DIR" "$APP_DIR"
echo " ✅ Directorio creado y clonado"
fi
# 3. Verificar logs
echo ""
echo "3⃣ Verificando archivo de logs..."
if [ -f "$LOG_FILE" ]; then
if [ -w "$LOG_FILE" ]; then
echo " ✅ Archivo de logs existe y es escribible"
else
echo " ⚠️ Archivo de logs existe pero no es escribible. Corrigiendo..."
chmod 666 "$LOG_FILE" 2>/dev/null || sudo chmod 666 "$LOG_FILE"
echo " ✅ Permisos corregidos"
fi
else
echo " ⚠️ Archivo de logs no existe. Creando..."
touch "$LOG_FILE"
chmod 666 "$LOG_FILE" 2>/dev/null || sudo chmod 666 "$LOG_FILE"
echo " ✅ Archivo de logs creado"
fi
# 4. Verificar Node.js y npm
echo ""
echo "4⃣ Verificando Node.js y npm..."
if command -v node >/dev/null 2>&1; then
echo " ✅ Node.js: $(node --version)"
else
echo " ❌ Node.js no está instalado"
echo " 💡 Instalar con: curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs"
fi
if command -v npm >/dev/null 2>&1; then
echo " ✅ npm: $(npm --version)"
else
echo " ❌ npm no está instalado"
fi
# 5. Verificar que el directorio de trabajo está actualizado
echo ""
echo "5⃣ Verificando estado del repositorio..."
if [ -d "$APP_DIR/.git" ]; then
cd "$APP_DIR"
echo " 📍 Directorio: $APP_DIR"
echo " 📦 Rama: $(git branch --show-current 2>/dev/null || echo 'desconocida')"
echo " 🔗 Remoto: $(git remote get-url origin 2>/dev/null || echo 'no configurado')"
# Verificar si hay cambios pendientes
if [ -n "$(git status --porcelain 2>/dev/null)" ]; then
echo " ⚠️ Hay cambios no commiteados en el directorio de trabajo"
else
echo " ✅ Directorio de trabajo limpio"
fi
fi
echo ""
echo "✅ Verificación completada"
echo ""
echo "📋 Resumen:"
echo " - Hook: $HOOK_FILE"
echo " - Directorio app: $APP_DIR"
echo " - Logs: $LOG_FILE"
echo ""
echo "🧪 Para probar el despliegue:"
echo " 1. Desde tu máquina local: git push production main"
echo " 2. En el servidor, ver logs: tail -f $LOG_FILE"