#!/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