# frozen_string_literal: true require_relative 'test_mode_transaction' require_relative 'database_migrator' require_relative 'data_importer' require_relative 'image_downloader' require_relative 'search_indexer' require_relative '../logging_helper' module PostDeployment class Manager include LoggingHelper def initialize(options = {}) @test_mode = options.fetch(:test_mode, false) @verbose = options.fetch(:verbose, false) @storage = options.fetch(:storage, :both) @force = options.fetch(:force, false) @new_records = Hash.new { |h, k| h[k] = [] } @updated_records = Hash.new { |h, k| h[k] = [] } @test_transaction = TestModeTransaction.new if @test_mode end def run migrate_database import_new_data display_import_summary download_images rebuild_search_indices display_completion_message rescue => e handle_error(e) end private def migrate_database DatabaseMigrator.new( test_mode: @test_mode, verbose: @verbose ).run end def import_new_data log_header 'Importing new data...' puts "\n" importer = DataImporter.new( test_mode: @test_mode, verbose: @verbose, test_transaction: @test_transaction, force: @force ) process_imports(importer) end def process_imports(importer) importer.process_all_files do |result| merge_import_results(result) end end def merge_import_results(result) result[:new].each do |type, records| @new_records[type].concat(records) end result[:updated].each do |type, records| @updated_records[type].concat(records) end end def download_images return if all_records_empty? ImageDownloader.new( test_mode: @test_mode, verbose: @verbose, storage: @storage, new_records: @new_records, updated_records: @updated_records ).run end def rebuild_search_indices SearchIndexer.new( test_mode: @test_mode, verbose: @verbose, new_records: @new_records ).rebuild_all end def display_import_summary if @new_records.size > 0 || @updated_records.size > 0 log_header 'Import Summary', '-' display_record_summary('New', @new_records) display_record_summary('Updated', @updated_records) else log_step "\nNo new records imported." end end def display_record_summary(label, records) records.each do |type, items| next if items.empty? count = items.size puts "\n#{type.capitalize}: #{count} #{label.downcase} #{count == 1 ? 'record' : 'records'}" items.each do |item| puts " - #{item[:name_en]} (ID: #{item[:granblue_id]})" end end end def display_completion_message if @test_mode log_header "✅ Test run completed successfully!", "-" puts "\n" log_step "#{@new_records.values.flatten.size} records would be created" log_step "#{@updated_records.values.flatten.size} records would be updated" puts "\n" else log_header "✅ Post-deployment tasks completed successfully!" end end def handle_error(error) error_message = format_error_message(error) log_formatted_error(error_message) @test_transaction&.rollback exit(1) end def format_error_message(error) sections = [] # Add header section sections << [ "═" * 60, "❌ Error during deployment", "═" * 60 ] # Add main error message sections << format_main_error(error) # Add stack trace if verbose if @verbose && error.respond_to?(:backtrace) sections << [ "Stack trace:", error.backtrace.take(5).map { |line| " #{line}" } ].flatten end sections.flatten.join("\n") end def format_main_error(error) case error when Granblue::Importers::ImportError [ "File: #{error.file_name}", "-" * 80, error.details ] else error.message.to_s end end def log_formatted_error(message) # Split message into lines and log each with error prefix message.split("\n").each do |line| log_error line end end def all_records_empty? @new_records.values.all?(&:empty?) && @updated_records.values.all?(&:empty?) end end end