420 lines
13 KiB
Ruby
Executable File
420 lines
13 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
|
# frozen_string_literal: true
|
|
|
|
# tools/orquestador/dashboard/orquestador.rb
|
|
# ==========================================
|
|
# Script maestro para orquestar todas las herramientas del dashboard P2601
|
|
# Filosofía: "Menos es más" - orquestación de herramientas pequeñas y específicas
|
|
|
|
require 'fileutils'
|
|
|
|
class DashboardOrchestrator
|
|
VERSION = '1.0.0'
|
|
|
|
# Mapeo de comandos a herramientas
|
|
HERRAMIENTAS = {
|
|
'limpiar' => {
|
|
archivo: 'limpiar.rb',
|
|
descripcion: 'Limpiar hitos duplicados del dashboard',
|
|
uso: './orquestador.rb limpiar [--dashboard RUTA]'
|
|
},
|
|
'agregar-hitos' => {
|
|
archivo: 'agregar_hitos.rb',
|
|
descripcion: 'Agregar hitos al dashboard',
|
|
uso: './orquestador.rb agregar-hitos [fase] [modo] [--dashboard RUTA]'
|
|
},
|
|
'actualizar-estados' => {
|
|
archivo: 'actualizar_estados.rb',
|
|
descripcion: 'Actualizar estados de hitos',
|
|
uso: './orquestador.rb actualizar-estados [comando] [argumentos...]'
|
|
},
|
|
'verificar' => {
|
|
archivo: 'verificar.rb',
|
|
descripcion: 'Verificar estructura del dashboard',
|
|
uso: './orquestador.rb verificar [comando] [--dashboard RUTA]'
|
|
},
|
|
'vista-previa' => {
|
|
archivo: 'vista_previa.rb',
|
|
descripcion: 'Vista previa del dashboard',
|
|
uso: './orquestador.rb vista-previa [modo] [--dashboard RUTA]'
|
|
},
|
|
'sincronizar' => {
|
|
archivo: 'sincronizar.rb',
|
|
descripcion: 'Sincronizar dashboard local con producción',
|
|
uso: './orquestador.rb sincronizar [--dry-run] [--no-backup]'
|
|
},
|
|
'agregar-hitos-db' => {
|
|
archivo: 'agregar_hitos_db.rb',
|
|
descripcion: 'Agregar hitos a la base de datos PostgreSQL',
|
|
uso: './orquestador.rb agregar-hitos-db [comando]'
|
|
}
|
|
}.freeze
|
|
|
|
# Flujos de trabajo predefinidos
|
|
FLUJOS_TRABAJO = {
|
|
'inicializar' => {
|
|
descripcion: 'Inicializar dashboard limpio con hitos de fase 5',
|
|
pasos: [
|
|
{ herramienta: 'limpiar', args: [] },
|
|
{ herramienta: 'agregar-hitos', args: ['fase5', 'append'] },
|
|
{ herramienta: 'verificar', args: ['verificar'] }
|
|
]
|
|
},
|
|
'seguimiento-diario' => {
|
|
descripcion: 'Flujo para seguimiento diario del proyecto',
|
|
pasos: [
|
|
{ herramienta: 'vista-previa', args: ['rapido'] },
|
|
{ herramienta: 'actualizar-estados', args: ['listar'] }
|
|
]
|
|
},
|
|
'revision-semanal' => {
|
|
descripcion: 'Flujo para revisión semanal completa',
|
|
pasos: [
|
|
{ herramienta: 'limpiar', args: [] },
|
|
{ herramienta: 'verificar', args: ['verificar'] },
|
|
{ herramienta: 'vista-previa', args: ['resumen'] },
|
|
{ herramienta: 'actualizar-estados', args: ['listar'] }
|
|
]
|
|
},
|
|
'agregar-fase5' => {
|
|
descripcion: 'Agregar hitos de fase 5 y verificar',
|
|
pasos: [
|
|
{ herramienta: 'agregar-hitos', args: ['fase5', 'append'] },
|
|
{ herramienta: 'verificar', args: ['analizar'] }
|
|
]
|
|
},
|
|
'desplegar-produccion' => {
|
|
descripcion: 'Sincronizar cambios a producción y verificar',
|
|
pasos: [
|
|
{ herramienta: 'sincronizar', args: [] },
|
|
{ herramienta: 'verificar', args: ['verificar'] },
|
|
{ herramienta: 'vista-previa', args: ['rapido'] }
|
|
]
|
|
},
|
|
'ciclo-completo' => {
|
|
descripcion: 'Ciclo completo: limpiar, agregar hitos, sincronizar',
|
|
pasos: [
|
|
{ herramienta: 'limpiar', args: [] },
|
|
{ herramienta: 'agregar-hitos', args: ['fase5', 'append'] },
|
|
{ herramienta: 'sincronizar', args: [] },
|
|
{ herramienta: 'verificar', args: ['verificar'] }
|
|
]
|
|
},
|
|
'agregar-hitos-produccion' => {
|
|
descripcion: 'Agregar hitos a la base de datos de producción',
|
|
pasos: [
|
|
{ herramienta: 'agregar-hitos-db', args: ['agregar'] },
|
|
{ herramienta: 'agregar-hitos-db', args: ['estado'] }
|
|
]
|
|
},
|
|
'dashboard-completo' => {
|
|
descripcion: 'Flujo completo para dashboard en producción',
|
|
pasos: [
|
|
{ herramienta: 'agregar-hitos-db', args: ['agregar'] },
|
|
{ herramienta: 'vista-previa', args: ['rapido'] },
|
|
{ herramienta: 'verificar', args: ['verificar'] }
|
|
]
|
|
}
|
|
}.freeze
|
|
|
|
def initialize
|
|
@directorio_herramientas = File.dirname(__FILE__)
|
|
end
|
|
|
|
def ejecutar_herramienta(nombre_herramienta, args = [])
|
|
puts "🛠️ EJECUTANDO: #{nombre_herramienta}"
|
|
puts "=" * 60
|
|
|
|
herramienta = HERRAMIENTAS[nombre_herramienta]
|
|
|
|
unless herramienta
|
|
puts "❌ Error: Herramienta '#{nombre_herramienta}' no encontrada"
|
|
puts " Herramientas disponibles: #{HERRAMIENTAS.keys.join(', ')}"
|
|
return false
|
|
end
|
|
|
|
ruta_herramienta = File.join(@directorio_herramientas, herramienta[:archivo])
|
|
|
|
unless File.exist?(ruta_herramienta)
|
|
puts "❌ Error: Archivo de herramienta no encontrado: #{ruta_herramienta}"
|
|
return false
|
|
end
|
|
|
|
# Construir comando
|
|
comando = "ruby #{ruta_herramienta} #{args.join(' ')}"
|
|
|
|
puts "📝 Comando: #{comando}"
|
|
puts "-" * 60
|
|
|
|
# Ejecutar herramienta
|
|
system(comando)
|
|
|
|
exit_status = $?.exitstatus
|
|
puts "-" * 60
|
|
|
|
if exit_status == 0
|
|
puts "✅ Herramienta ejecutada exitosamente"
|
|
true
|
|
else
|
|
puts "❌ Herramienta falló con código #{exit_status}"
|
|
false
|
|
end
|
|
end
|
|
|
|
def ejecutar_flujo_trabajo(nombre_flujo)
|
|
puts "🔄 EJECUTANDO FLUJO DE TRABAJO: #{nombre_flujo}"
|
|
puts "=" * 60
|
|
|
|
flujo = FLUJOS_TRABAJO[nombre_flujo]
|
|
|
|
unless flujo
|
|
puts "❌ Error: Flujo de trabajo '#{nombre_flujo}' no encontrado"
|
|
puts " Flujos disponibles: #{FLUJOS_TRABAJO.keys.join(', ')}"
|
|
return false
|
|
end
|
|
|
|
puts "📋 Descripción: #{flujo[:descripcion]}"
|
|
puts "📊 Pasos: #{flujo[:pasos].size}"
|
|
puts
|
|
|
|
resultados = []
|
|
flujo[:pasos].each_with_index do |paso, index|
|
|
puts "📝 PASO #{index + 1}/#{flujo[:pasos].size}: #{paso[:herramienta]}"
|
|
puts " Argumentos: #{paso[:args].join(' ')}" if paso[:args].any?
|
|
puts
|
|
|
|
exito = ejecutar_herramienta(paso[:herramienta], paso[:args])
|
|
resultados << { paso: paso[:herramienta], exito: exito }
|
|
|
|
unless exito
|
|
puts "⚠️ Flujo interrumpido por fallo en paso #{index + 1}"
|
|
break
|
|
end
|
|
|
|
puts "\n" unless index == flujo[:pasos].size - 1
|
|
end
|
|
|
|
# Mostrar resumen
|
|
mostrar_resumen_flujo(resultados, nombre_flujo)
|
|
|
|
resultados.all? { |r| r[:exito] }
|
|
end
|
|
|
|
def listar_herramientas
|
|
puts "🛠️ HERRAMIENTAS DISPONIBLES"
|
|
puts "=" * 60
|
|
|
|
HERRAMIENTAS.each do |nombre, info|
|
|
puts "• #{nombre}"
|
|
puts " 📝 #{info[:descripcion]}"
|
|
puts " 📋 Uso: #{info[:uso]}"
|
|
puts
|
|
end
|
|
|
|
true
|
|
end
|
|
|
|
def listar_flujos
|
|
puts "🔄 FLUJOS DE TRABAJO PREDEFINIDOS"
|
|
puts "=" * 60
|
|
|
|
FLUJOS_TRABAJO.each do |nombre, flujo|
|
|
puts "• #{nombre}"
|
|
puts " 📝 #{flujo[:descripcion]}"
|
|
puts " 📊 Pasos: #{flujo[:pasos].size}"
|
|
flujo[:pasos].each_with_index do |paso, i|
|
|
puts " #{i + 1}. #{paso[:herramienta]} #{paso[:args].join(' ')}"
|
|
end
|
|
puts
|
|
end
|
|
|
|
true
|
|
end
|
|
|
|
def mostrar_estado_sistema
|
|
puts "📊 ESTADO DEL SISTEMA DE ORQUESTACIÓN"
|
|
puts "=" * 60
|
|
|
|
puts "🏗️ INFORMACIÓN GENERAL:"
|
|
puts " • Versión: #{VERSION}"
|
|
puts " • Directorio herramientas: #{@directorio_herramientas}"
|
|
puts " • Herramientas disponibles: #{HERRAMIENTAS.size}"
|
|
puts "📊 Flujos predefinidos: #{FLUJOS_TRABAJO.size}"
|
|
|
|
puts "\n🎯 DASHBOARDS DISPONIBLES:"
|
|
puts " • Producción: https://ns8.frlr.utn.edu.ar/bitacoras/p2601"
|
|
puts " • Estático: https://ns8.frlr.utn.edu.ar/P2601/"
|
|
|
|
puts "\n🔍 VERIFICACIÓN DE HERRAMIENTAS:"
|
|
herramientas_ok = 0
|
|
HERRAMIENTAS.each do |nombre, info|
|
|
ruta = File.join(@directorio_herramientas, info[:archivo])
|
|
existe = File.exist?(ruta)
|
|
ejecutable = File.executable?(ruta)
|
|
emoji = existe && ejecutable ? '✅' : '❌'
|
|
|
|
puts " #{emoji} #{nombre}: #{info[:archivo]}"
|
|
puts " - Existe: #{existe ? 'Sí' : 'No'}"
|
|
puts " - Ejecutable: #{ejecutable ? 'Sí' : 'No'}"
|
|
puts " - Tipo: #{nombre.include?('db') ? 'Base de datos' : 'Archivo'}"
|
|
|
|
herramientas_ok += 1 if existe && ejecutable
|
|
end
|
|
|
|
puts "\n📈 RESUMEN:"
|
|
puts " • Herramientas listas: #{herramientas_ok}/#{HERRAMIENTAS.size}"
|
|
|
|
if herramientas_ok == HERRAMIENTAS.size
|
|
puts " ✅ Todas las herramientas están listas para usar"
|
|
else
|
|
puts " ⚠️ Algunas herramientas requieren atención"
|
|
end
|
|
|
|
true
|
|
end
|
|
|
|
private
|
|
|
|
def mostrar_resumen_flujo(resultados, nombre_flujo)
|
|
puts "📊 RESUMEN DEL FLUJO: #{nombre_flujo}"
|
|
puts "=" * 60
|
|
|
|
exitosos = resultados.count { |r| r[:exito] }
|
|
total = resultados.size
|
|
|
|
resultados.each_with_index do |resultado, index|
|
|
emoji = resultado[:exito] ? '✅' : '❌'
|
|
puts " #{emoji} Paso #{index + 1}: #{resultado[:paso]}"
|
|
end
|
|
|
|
puts "\n📈 ESTADÍSTICAS:"
|
|
puts " • Pasos ejecutados: #{total}"
|
|
puts " • Pasos exitosos: #{exitosos}"
|
|
puts " • Porcentaje de éxito: #{(exitosos * 100.0 / total).round(1)}%"
|
|
|
|
if exitosos == total
|
|
puts "\n🎉 ¡Flujo de trabajo completado exitosamente!"
|
|
else
|
|
puts "\n⚠️ Flujo de trabajo completado con errores"
|
|
end
|
|
end
|
|
end
|
|
|
|
# Interfaz de línea de comandos
|
|
if __FILE__ == $0
|
|
begin
|
|
orquestador = DashboardOrchestrator.new
|
|
|
|
# Parsear argumentos
|
|
comando = ARGV[0] || 'help'
|
|
|
|
case comando
|
|
when 'herramienta', 'tool'
|
|
if ARGV.length < 2
|
|
puts "❌ Error: Se requiere nombre de herramienta"
|
|
puts " Uso: #{$0} herramienta NOMBRE_HERRAMIENTA [argumentos...]"
|
|
exit 1
|
|
end
|
|
|
|
nombre_herramienta = ARGV[1]
|
|
args = ARGV[2..-1] || []
|
|
success = orquestador.ejecutar_herramienta(nombre_herramienta, args)
|
|
|
|
when 'flujo', 'workflow'
|
|
if ARGV.length < 2
|
|
puts "❌ Error: Se requiere nombre de flujo"
|
|
puts " Uso: #{$0} flujo NOMBRE_FLUJO"
|
|
exit 1
|
|
end
|
|
|
|
nombre_flujo = ARGV[1]
|
|
success = orquestador.ejecutar_flujo_trabajo(nombre_flujo)
|
|
|
|
when 'listar-herramientas', 'list-tools'
|
|
success = orquestador.listar_herramientas
|
|
|
|
when 'listar-flujos', 'list-workflows'
|
|
success = orquestador.listar_flujos
|
|
|
|
when 'estado', 'status'
|
|
success = orquestador.mostrar_estado_sistema
|
|
|
|
when 'version', '--version', '-v'
|
|
puts "Dashboard Orchestrator v#{DashboardOrchestrator::VERSION}"
|
|
success = true
|
|
|
|
when 'help', '--help', '-h'
|
|
puts "📖 ORQUESTADOR DE HERRAMIENTAS - DASHBOARD P2601"
|
|
puts "=" * 60
|
|
puts
|
|
puts "DESCRIPCIÓN:"
|
|
puts " Script maestro para orquestar herramientas pequeñas y específicas"
|
|
puts " del dashboard P2601, siguiendo la filosofía 'Menos es más'."
|
|
puts
|
|
puts "USO:"
|
|
puts " #{$0} [comando] [argumentos...]"
|
|
puts
|
|
puts "COMANDOS PRINCIPALES:"
|
|
puts " herramienta, tool NOMBRE [args...] Ejecutar una herramienta específica"
|
|
puts " flujo, workflow NOMBRE Ejecutar flujo de trabajo predefinido"
|
|
puts " listar-herramientas, list-tools Listar todas las herramientas"
|
|
puts " listar-flujos, list-workflows Listar flujos de trabajo"
|
|
puts " estado, status Mostrar estado del sistema"
|
|
puts " version, -v Mostrar versión"
|
|
puts " help, -h Mostrar esta ayuda"
|
|
puts
|
|
puts "HERRAMIENTAS DISPONIBLES:"
|
|
DashboardOrchestrator::HERRAMIENTAS.each do |nombre, info|
|
|
puts " • #{nombre}: #{info[:descripcion]}"
|
|
end
|
|
puts
|
|
puts "FLUJOS PREDEFINIDOS:"
|
|
DashboardOrchestrator::FLUJOS_TRABAJO.each do |nombre, flujo|
|
|
puts " • #{nombre}: #{flujo[:descripcion]}"
|
|
end
|
|
puts
|
|
puts "EJEMPLOS:"
|
|
puts " #{$0} herramienta limpiar"
|
|
puts " #{$0} herramienta agregar-hitos fase5 append"
|
|
puts " #{$0} flujo inicializar"
|
|
puts " #{$0} flujo seguimiento-diario"
|
|
puts " #{$0} estado"
|
|
puts
|
|
puts "📅 #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
|
|
puts "=" * 60
|
|
success = true
|
|
|
|
else
|
|
puts "❌ Comando '#{comando}' no reconocido"
|
|
puts " Use '#{$0} help' para ver la ayuda"
|
|
success = false
|
|
end
|
|
|
|
# Verificar si es un comando de base de datos
|
|
if comando == 'herramienta' && nombre_herramienta == 'agregar-hitos-db'
|
|
puts "\n⚠️ NOTA: Esta herramienta modifica la base de datos PostgreSQL"
|
|
puts " • Asegúrese de que el contenedor esté ejecutándose"
|
|
puts " • Los cambios se reflejan en: https://ns8.frlr.utn.edu.ar/bitacoras/p2601"
|
|
end
|
|
|
|
if success
|
|
puts "\n🚀 RECOMENDACIONES:"
|
|
puts " 1. Usar 'flujo inicializar' para dashboard limpio"
|
|
puts " 1. Usar 'flujo agregar-hitos-produccion' para hitos en base de datos"
|
|
puts " 2. Usar 'flujo seguimiento-diario' para monitoreo regular"
|
|
puts " 3. Verificar dashboard en: https://ns8.frlr.utn.edu.ar/bitacoras/p2601"
|
|
puts " 4. Dashboard estático en: https://ns8.frlr.utn.edu.ar/P2601/"
|
|
puts
|
|
puts "📅 #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
|
|
puts "=" * 60
|
|
else
|
|
exit 1
|
|
end
|
|
|
|
rescue => e
|
|
puts "❌ Error: #{e.message}"
|
|
puts e.backtrace if ENV['DEBUG']
|
|
exit 1
|
|
end
|
|
end
|