Class: Kdeploy::OutputFormatter

Inherits:
Object
  • Object
show all
Defined in:
lib/kdeploy/output/output_formatter.rb

Overview

Formats and displays execution results

Instance Method Summary collapse

Constructor Details

#initialize(debug: false) ⇒ OutputFormatter

Returns a new instance of OutputFormatter.



9
10
11
12
# File 'lib/kdeploy/output/output_formatter.rb', line 9

def initialize(debug: false)
  @pastel = Pastel.new
  @debug = debug
end

Instance Method Details

#build_summary_line(host, counts, max_host_len) ⇒ Object



110
111
112
113
114
115
116
117
118
119
# File 'lib/kdeploy/output/output_formatter.rb', line 110

def build_summary_line(host, counts, max_host_len)
  ok_w = 7
  changed_w = 11
  failed_w = 10

  ok_str = @pastel.green("ok=#{counts[:ok].to_s.ljust(ok_w - 3)}")
  changed_str = @pastel.yellow("changed=#{counts[:changed].to_s.ljust(changed_w - 8)}")
  failed_str = @pastel.red("failed=#{counts[:failed].to_s.ljust(failed_w - 7)}")
  "#{host.ljust(max_host_len)} : #{ok_str}  #{changed_str}  #{failed_str}"
end

#calculate_host_duration(result) ⇒ Object



36
37
38
39
40
# File 'lib/kdeploy/output/output_formatter.rb', line 36

def calculate_host_duration(result)
  return 0.0 unless result.is_a?(Hash)

  Array(result[:output]).sum { |step| step[:duration].to_f }
end

#calculate_summary_counts(result) ⇒ Object



103
104
105
106
107
108
# File 'lib/kdeploy/output/output_formatter.rb', line 103

def calculate_summary_counts(result)
  ok = %i[success changed].include?(result[:status]) ? result[:output].size : 0
  failed = result[:status] == :failed ? 1 : 0
  changed = result[:status] == :changed ? result[:output].size : 0
  { ok: ok, failed: failed, changed: changed }
end

#colorize_summary_line(line, counts) ⇒ Object



121
122
123
124
125
126
127
128
129
# File 'lib/kdeploy/output/output_formatter.rb', line 121

def colorize_summary_line(line, counts)
  if counts[:failed].positive?
    @pastel.red(line)
  elsif counts[:ok].positive? && counts[:failed].zero?
    @pastel.green(line)
  else
    line
  end
end

#format_command_for_dry_run(command) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/kdeploy/output/output_formatter.rb', line 155

def format_command_for_dry_run(command)
  case command[:type]
  when :run
    "#{@pastel.green('>')} #{command[:command]}"
  when :upload
    "#{@pastel.blue('>')} Upload: #{command[:source]} -> #{command[:destination]}"
  when :upload_template
    "#{@pastel.blue('>')} Template: #{command[:source]} -> #{command[:destination]}"
  when :sync
    ignore_str = command[:ignore]&.any? ? " (ignore: #{command[:ignore].join(', ')})" : ''
    delete_str = command[:delete] ? ' (delete: true)' : ''
    "#{@pastel.blue('>')} Sync: #{command[:source]} -> #{command[:destination]}#{ignore_str}#{delete_str}"
  else
    "#{@pastel.blue('>')} #{command[:type]}: #{command}"
  end
end

#format_dry_run_box(title, content) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
# File 'lib/kdeploy/output/output_formatter.rb', line 131

def format_dry_run_box(title, content)
  TTY::Box.frame(
    content,
    title: { top_left: " #{title} " },
    style: {
      border: {
        fg: :yellow
      }
    }
  )
end

#format_dry_run_headerObject



143
144
145
146
147
148
149
150
151
152
153
# File 'lib/kdeploy/output/output_formatter.rb', line 143

def format_dry_run_header
  TTY::Box.frame(
    'Showing what would be done without executing any commands',
    title: { top_left: ' Dry Run Mode ', bottom_right: ' Kdeploy ' },
    style: {
      border: {
        fg: :blue
      }
    }
  )
end

#format_error(error_message) ⇒ Object



89
90
91
# File 'lib/kdeploy/output/output_formatter.rb', line 89

def format_error(error_message)
  @pastel.red("    āœ— ERROR: #{error_message}")
end

#format_file_step(step, type, prefix) ⇒ Object



58
59
60
61
62
63
64
65
66
# File 'lib/kdeploy/output/output_formatter.rb', line 58

def format_file_step(step, type, prefix)
  duration_str = format_duration(step[:duration])
  status_str = format_step_status(step)
  file_path = step[:command].sub(prefix, '')
  # Truncate long paths for cleaner output
  display_path = file_path.length > 50 ? "...#{file_path[-47..]}" : file_path
  color_method = type == :upload ? :green : :yellow
  @pastel.dim('    ') + @pastel.send(color_method, display_path) + duration_str + " #{status_str}"
end

#format_file_steps(steps, type, prefix) ⇒ Object



54
55
56
# File 'lib/kdeploy/output/output_formatter.rb', line 54

def format_file_steps(steps, type, prefix)
  steps.map { |step| format_file_step(step, type, prefix) }
end

#format_host_completed(duration) ⇒ Object



32
33
34
# File 'lib/kdeploy/output/output_formatter.rb', line 32

def format_host_completed(duration)
  @pastel.dim("    [completed in #{format('%.2f', duration)}s]")
end

#format_host_status(host, status) ⇒ Object



18
19
20
21
22
23
24
25
# File 'lib/kdeploy/output/output_formatter.rb', line 18

def format_host_status(host, status)
  status_str = case status
               when :success then @pastel.green('āœ“ ok')
               when :changed then @pastel.yellow('~ changed')
               else @pastel.red('āœ— failed')
               end
  @pastel.bright_white("  #{host.ljust(20)} #{status_str}")
end

#format_run_steps(steps, _shown = nil) ⇒ Object



68
69
70
# File 'lib/kdeploy/output/output_formatter.rb', line 68

def format_run_steps(steps, _shown = nil)
  steps.flat_map { |step| format_single_run_step(step) }
end

#format_single_run_step(step) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/kdeploy/output/output_formatter.rb', line 72

def format_single_run_step(step)
  output = []
  duration_str = format_duration(step[:duration])
  status_str = format_step_status(step)
  command_line = first_meaningful_command_line(step[:command].to_s)
  # Truncate long commands for cleaner output
  display_cmd = command_line.length > 60 ? "#{command_line[0..57]}..." : command_line
  output << (@pastel.dim('    ') + @pastel.cyan(display_cmd) + duration_str + " #{status_str}")
  # Only show multiline details in debug mode
  if @debug
    output.concat(format_multiline_command(step[:command]))
    cmd_output = format_command_output(step[:output])
    output.concat(cmd_output) if cmd_output.any?
  end
  output
end

#format_summary_headerObject



93
94
95
# File 'lib/kdeploy/output/output_formatter.rb', line 93

def format_summary_header
  "#{@pastel.bright_cyan("\nšŸ“Š Execution Summary")}\n#{@pastel.dim('─' * 60)}"
end

#format_summary_line(host, result, max_host_len) ⇒ Object



97
98
99
100
101
# File 'lib/kdeploy/output/output_formatter.rb', line 97

def format_summary_line(host, result, max_host_len)
  counts = calculate_summary_counts(result)
  line = build_summary_line(host, counts, max_host_len)
  colorize_summary_line(line, counts)
end

#format_sync_steps(steps, _shown = nil) ⇒ Object



50
51
52
# File 'lib/kdeploy/output/output_formatter.rb', line 50

def format_sync_steps(steps, _shown = nil)
  steps.map { |step| format_sync_step(step) }
end

#format_task_header(task_name) ⇒ Object



14
15
16
# File 'lib/kdeploy/output/output_formatter.rb', line 14

def format_task_header(task_name)
  "#{@pastel.bright_cyan("\nšŸš€ Task: #{task_name}")}\n#{@pastel.dim('─' * 60)}"
end

#format_template_steps(steps, _shown = nil) ⇒ Object



46
47
48
# File 'lib/kdeploy/output/output_formatter.rb', line 46

def format_template_steps(steps, _shown = nil)
  format_file_steps(steps, :upload_template, 'upload_template: ')
end

#format_upload_steps(steps, _shown = nil) ⇒ Object



42
43
44
# File 'lib/kdeploy/output/output_formatter.rb', line 42

def format_upload_steps(steps, _shown = nil)
  format_file_steps(steps, :upload, 'upload: ')
end

#host_prefix(host) ⇒ Object

Prefix for per-step lines to make multi-host logs easier to scan.



28
29
30
# File 'lib/kdeploy/output/output_formatter.rb', line 28

def host_prefix(host)
  @pastel.dim("  #{host.ljust(20)} ")
end