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:
parent
1e50a72c8e
commit
f3f2ab3c55
629
docs/PLAN_CONVERSION_SCORM.md
Normal file
629
docs/PLAN_CONVERSION_SCORM.md
Normal 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
106
docs/SCORM_QUICK_START.md
Normal 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
|
||||
|
||||
272
scripts/deploy/COMANDOS_DEPLOY.md
Normal file
272
scripts/deploy/COMANDOS_DEPLOY.md
Normal 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.
|
||||
|
||||
298
scripts/deploy/README_DEPLOY.md
Normal file
298
scripts/deploy/README_DEPLOY.md
Normal 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.
|
||||
|
||||
129
scripts/deploy/RESUMEN_DEPLOY.md
Normal file
129
scripts/deploy/RESUMEN_DEPLOY.md
Normal 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** 🚀
|
||||
|
||||
|
||||
36
scripts/deploy/actualizar-hook.sh
Executable file
36
scripts/deploy/actualizar-hook.sh
Executable 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"
|
||||
|
||||
81
scripts/deploy/corregir-servidor.sh
Normal file
81
scripts/deploy/corregir-servidor.sh
Normal 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"
|
||||
|
||||
139
scripts/deploy/diagnostico-servidor.sh
Normal file
139
scripts/deploy/diagnostico-servidor.sh
Normal 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
124
scripts/deploy/post-receive
Executable 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
159
scripts/deploy/setup-deploy.sh
Executable 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
61
scripts/deploy/test-deploy.sh
Executable 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
|
||||
|
||||
116
scripts/deploy/verificar-servidor.sh
Normal file
116
scripts/deploy/verificar-servidor.sh
Normal 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"
|
||||
|
||||
Loading…
Reference in a new issue