Class: Makit::Commands::Result

Inherits:
Object
  • Object
show all
Defined in:
lib/makit/commands/result.rb

Overview

Structured result objects with comprehensive metadata. Uses native Ruby objects instead of protobuf for better performance.

Examples:

Basic result creation

result = Result.new(
  command: "git --version",
  exit_code: 0,
  stdout: "git version 2.39.5\n",
  stderr: ""
)

Result with full metadata

result = Result.new(
  command: "bundle install",
  exit_code: 0,
  stdout: "Bundle complete!",
  stderr: "",
  started_at: Time.now - 10,
  finished_at: Time.now,
  metadata: { gems_installed: 42, cache_hit: true }
)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(command:, **attributes) ⇒ Result

Initialize a new command result.

Parameters:

  • command (String)

    the command that was executed

  • exit_code (Integer)

    process exit code (default: nil)

  • stdout (String)

    standard output (default: “”)

  • stderr (String)

    standard error output (default: “”)

  • started_at (Time)

    when execution started (default: Time.now)

  • finished_at (Time, nil)

    when execution finished

  • metadata (Hash)

    additional metadata (default: {})



59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/makit/commands/result.rb', line 59

def initialize(command:, **attributes)
  @command = command.to_s
  @exit_code = attributes[:exit_code]
  @stdout = attributes[:stdout] || ""
  @stderr = attributes[:stderr] || ""
  @started_at = attributes[:started_at] || Time.now
  @finished_at = attributes[:finished_at]
  @duration = calculate_duration
  @metadata = attributes[:metadata] || {}

  # Ensure output is always strings
  @stdout = @stdout.to_s
  @stderr = @stderr.to_s
end

Instance Attribute Details

#commandString (readonly)

Returns the command that was executed.

Returns:

  • (String)

    the command that was executed



48
49
50
# File 'lib/makit/commands/result.rb', line 48

def command
  @command
end

#durationFloat? (readonly)

Returns execution duration in seconds.

Returns:

  • (Float, nil)

    execution duration in seconds



48
# File 'lib/makit/commands/result.rb', line 48

attr_reader :command, :exit_code, :stdout, :stderr, :started_at, :finished_at, :duration, :metadata

#exit_codeInteger (readonly)

Returns process exit code.

Returns:

  • (Integer)

    process exit code



48
# File 'lib/makit/commands/result.rb', line 48

attr_reader :command, :exit_code, :stdout, :stderr, :started_at, :finished_at, :duration, :metadata

#finished_atTime? (readonly)

Returns when execution finished.

Returns:

  • (Time, nil)

    when execution finished



48
# File 'lib/makit/commands/result.rb', line 48

attr_reader :command, :exit_code, :stdout, :stderr, :started_at, :finished_at, :duration, :metadata

#metadataObject (readonly)

Command execution result with comprehensive metadata.



48
# File 'lib/makit/commands/result.rb', line 48

attr_reader :command, :exit_code, :stdout, :stderr, :started_at, :finished_at, :duration, :metadata

#started_atTime (readonly)

Returns when execution started.

Returns:

  • (Time)

    when execution started



48
# File 'lib/makit/commands/result.rb', line 48

attr_reader :command, :exit_code, :stdout, :stderr, :started_at, :finished_at, :duration, :metadata

#stderrString (readonly)

Returns standard error output.

Returns:

  • (String)

    standard error output



48
# File 'lib/makit/commands/result.rb', line 48

attr_reader :command, :exit_code, :stdout, :stderr, :started_at, :finished_at, :duration, :metadata

#stdoutString (readonly)

Returns standard output.

Returns:

  • (String)

    standard output



48
# File 'lib/makit/commands/result.rb', line 48

attr_reader :command, :exit_code, :stdout, :stderr, :started_at, :finished_at, :duration, :metadata

Class Method Details

.failure(command:, error:, started_at: Time.now) ⇒ Result

Create a failed result with error information.

Parameters:

  • command (String)

    the command that failed

  • error (Exception, String)

    error that occurred

  • started_at (Time) (defaults to: Time.now)

    when execution started

Returns:

  • (Result)

    failed result object



220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/makit/commands/result.rb', line 220

def self.failure(command:, error:, started_at: Time.now)
  error_message = error.is_a?(Exception) ? error.message : error.to_s
  error_class = error.is_a?(Exception) ? error.class.name : "Error"

  new(
    command: command,
    exit_code: 1,
    stdout: "",
    stderr: error_message,
    started_at: started_at,
    finished_at: Time.now,
    metadata: { error_class: error_class, failed: true },
  )
end

.from_hash(hash) ⇒ Result

Create result from hash representation.

Parameters:

  • hash (Hash)

    hash containing result information

Returns:

  • (Result)

    new result object



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/makit/commands/result.rb', line 185

def self.from_hash(hash)
  # Parse time strings back to Time objects
  started_at = hash[:started_at] || hash["started_at"]
  finished_at = hash[:finished_at] || hash["finished_at"]

  started_at = Time.iso8601(started_at) if started_at.is_a?(String)
  finished_at = Time.iso8601(finished_at) if finished_at.is_a?(String)

  new(
    command: hash[:command] || hash["command"],
    exit_code: hash[:exit_code] || hash["exit_code"],
    stdout: hash[:stdout] || hash["stdout"] || "",
    stderr: hash[:stderr] || hash["stderr"] || "",
    started_at: started_at,
    finished_at: finished_at,
    metadata: hash[:metadata] || hash["metadata"] || {},
  )
end

.from_json(json_string) ⇒ Result

Create result from JSON string.

Parameters:

  • json_string (String)

    JSON string representation

Returns:

  • (Result)

    new result object

Raises:

  • (JSON::ParserError)

    if JSON is invalid



209
210
211
212
# File 'lib/makit/commands/result.rb', line 209

def self.from_json(json_string)
  hash = JSON.parse(json_string)
  from_hash(hash)
end

.success(command:, stdout: "", started_at: Time.now, duration: nil) ⇒ Result

Create a successful result.

Parameters:

  • command (String)

    the command that succeeded

  • stdout (String) (defaults to: "")

    standard output

  • started_at (Time) (defaults to: Time.now)

    when execution started

  • duration (Float) (defaults to: nil)

    execution duration

Returns:

  • (Result)

    successful result object



242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/makit/commands/result.rb', line 242

def self.success(command:, stdout: "", started_at: Time.now, duration: nil)
  finished_at = duration ? started_at + duration : Time.now

  new(
    command: command,
    exit_code: 0,
    stdout: stdout,
    stderr: "",
    started_at: started_at,
    finished_at: finished_at,
  )
end

Instance Method Details

#add_metadata(key, value) ⇒ self

Add metadata to the result.

Parameters:

  • key (String, Symbol)

    metadata key

  • value (Object)

    metadata value

Returns:

  • (self)

    for method chaining



260
261
262
263
# File 'lib/makit/commands/result.rb', line 260

def (key, value)
  @metadata[key] = value
  self
end

#contains?(text, case_sensitive: true) ⇒ Boolean

Check if output contains specific text.

Parameters:

  • text (String)

    text to search for

  • case_sensitive (Boolean) (defaults to: true)

    whether to perform case-sensitive search

Returns:

  • (Boolean)

    true if text is found in stdout or stderr



148
149
150
151
152
153
154
# File 'lib/makit/commands/result.rb', line 148

def contains?(text, case_sensitive: true)
  search_text = case_sensitive ? text : text.downcase
  search_stdout = case_sensitive ? stdout : stdout.downcase
  search_stderr = case_sensitive ? stderr : stderr.downcase

  search_stdout.include?(search_text) || search_stderr.include?(search_text)
end

#detailsString

Get detailed execution information.

Returns:

  • (String)

    detailed execution information



287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'lib/makit/commands/result.rb', line 287

def details
  lines = []
  lines << "Command: #{command}"
  lines << "Exit Code: #{exit_code}"
  lines << "Started: #{started_at}"
  lines << "Finished: #{finished_at}" if finished_at
  lines << "Duration: #{format("%.2f", duration)}s" if duration
  lines << "Status: #{success? ? "Success" : "Failed"}"

  unless stdout.empty?
    lines << "STDOUT:"
    lines << stdout.split("\n").map { |line| "  #{line}" }
  end

  unless stderr.empty?
    lines << "STDERR:"
    lines << stderr.split("\n").map { |line| "  #{line}" }
  end

  lines << "Metadata: #{}" unless .empty?

  lines.flatten.join("\n")
end

#failure?Boolean

Check if the command execution failed.

Returns:

  • (Boolean)

    true if exit code is not 0



100
101
102
# File 'lib/makit/commands/result.rb', line 100

def failure?
  !success?
end

#finish!(finished_at: Time.now, exit_code: nil, stdout: nil, stderr: nil) ⇒ self

Mark the result as finished.

Parameters:

  • finished_at (Time) (defaults to: Time.now)

    when execution finished (default: Time.now)

  • exit_code (Integer) (defaults to: nil)

    process exit code

  • stdout (String) (defaults to: nil)

    standard output

  • stderr (String) (defaults to: nil)

    standard error output

Returns:

  • (self)

    for method chaining



81
82
83
84
85
86
87
88
# File 'lib/makit/commands/result.rb', line 81

def finish!(finished_at: Time.now, exit_code: nil, stdout: nil, stderr: nil)
  @finished_at = finished_at
  @duration = calculate_duration
  @exit_code = exit_code if exit_code
  @stdout = stdout.to_s if stdout
  @stderr = stderr.to_s if stderr
  self
end

#finished?Boolean

Check if the command execution is complete.

Returns:

  • (Boolean)

    true if finished_at is set



107
108
109
# File 'lib/makit/commands/result.rb', line 107

def finished?
  !finished_at.nil?
end

#first_lineString?

Get the first line of stdout (useful for simple commands).

Returns:

  • (String, nil)

    first line of stdout



128
129
130
131
132
# File 'lib/makit/commands/result.rb', line 128

def first_line
  return nil if stdout.empty?

  stdout.lines.first&.chomp
end

#last_lineString?

Get the last line of stdout (useful for progress indicators).

Returns:

  • (String, nil)

    last line of stdout



137
138
139
140
141
# File 'lib/makit/commands/result.rb', line 137

def last_line
  return nil if stdout.empty?

  stdout.lines.last&.chomp
end

#merge_metadata(additional_metadata) ⇒ self

Merge additional metadata.

Parameters:

  • additional_metadata (Hash)

    metadata to merge

Returns:

  • (self)

    for method chaining



269
270
271
272
# File 'lib/makit/commands/result.rb', line 269

def ()
  @metadata.merge!()
  self
end

#outputString

Get combined output (stdout + stderr).

Returns:

  • (String)

    combined output



121
122
123
# File 'lib/makit/commands/result.rb', line 121

def output
  [stdout, stderr].reject(&:empty?).join("\n")
end

#running?Boolean

Check if the command is still running.

Returns:

  • (Boolean)

    true if execution started but not finished



114
115
116
# File 'lib/makit/commands/result.rb', line 114

def running?
  !started_at.nil? && finished_at.nil?
end

#success?Boolean

Check if the command executed successfully.

Returns:

  • (Boolean)

    true if exit code is 0



93
94
95
# File 'lib/makit/commands/result.rb', line 93

def success?
  exit_code.zero?
end

#summaryString

Get execution summary for logging/display.

Returns:

  • (String)

    human-readable execution summary



277
278
279
280
281
282
# File 'lib/makit/commands/result.rb', line 277

def summary
  status = success? ? "" : ""
  duration_text = duration ? " (#{format("%.2f", duration)}s)" : ""

  "#{status} #{command}#{duration_text}"
end

#to_hHash

Convert result to hash representation.

Returns:

  • (Hash)

    hash representation of the result



159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/makit/commands/result.rb', line 159

def to_h
  {
    command: command,
    exit_code: exit_code,
    stdout: stdout,
    stderr: stderr,
    started_at: started_at&.iso8601,
    finished_at: finished_at&.iso8601,
    duration: duration,
    success: success?,
    metadata: ,
  }
end

#to_json(*args) ⇒ String

Convert result to JSON representation.

Parameters:

  • args (Array)

    arguments passed to JSON.generate

Returns:

  • (String)

    JSON representation



177
178
179
# File 'lib/makit/commands/result.rb', line 177

def to_json(*args)
  JSON.generate(to_h, *args)
end