Class: Maze::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/maze/runner.rb

Overview

Runs scripts and commands, applying relevant environment variables as necessary

Class Method Summary collapse

Class Method Details

.environmentHash

Allows access to a hash of environment variables applied to command and script runs.

Returns:

  • (Hash)

    The hash of currently set environment variables and their values



137
138
139
# File 'lib/maze/runner.rb', line 137

def environment
  @environment ||= {}
end

.interactive_sessionObject



100
101
102
103
104
# File 'lib/maze/runner.rb', line 100

def interactive_session
  raise 'No interactive session is running!' unless interactive_session?

  @interactive_session
end

.interactive_session?Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/maze/runner.rb', line 96

def interactive_session?
  !@interactive_session.nil?
end

.kill_running_scriptsObject

Stops all script processes previously started by this class.



123
124
125
126
127
128
129
130
131
132
# File 'lib/maze/runner.rb', line 123

def kill_running_scripts
  stop_interactive_session if interactive_session?

  pids.each do |p|
    Process.kill('KILL', p)
  rescue Errno::ESRCH
    # ignored
  end
  pids.clear
end

.pidsArray

Allows access to the process ids created by the runner.

Returns:

  • (Array)

    pids created by the runner



144
145
146
# File 'lib/maze/runner.rb', line 144

def pids
  @pids ||= []
end

.run_command(cmd, blocking: true, success_codes: [0]) ⇒ Array, Thread

Runs a command, applying previously set environment variables. The output from the command is always printed in debug mode - just so the caller can verify something about the output.

Parameters:

  • cmd (String)

    The command to run

  • blocking (Boolean) (defaults to: true)

    Optional. Whether to wait for a return code before proceeding

  • success_codes (Array) (defaults to: [0])

    Optional. An array of integer codes which indicate the run was successful

Returns:

  • (Array, Thread)

    If blocking, the output and exit_status are returned



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/maze/runner.rb', line 22

def run_command(cmd, blocking: true, success_codes: [0])
  executor = lambda do
    $logger.debug "Executing: #{cmd}"

    Open3.popen2e(environment, cmd) do |_stdin, stdout_and_stderr, wait_thr|
      # Add the pid to the list of pids to kill at the end
      pids << wait_thr.pid unless blocking

      output = []
      stdout_and_stderr.each do |line|
        output << line
        $logger.debug line.chomp
      end

      exit_status = wait_thr.value.to_i
      $logger.debug "Exit status: #{exit_status}"

      # if the command fails we log the output at warn level too
      if !success_codes.nil? && !success_codes.include?(exit_status) && $logger.level != Logger::DEBUG
        output.each { |line| $logger.warn(cmd) { line.chomp } }
      end

      return [output, exit_status]
    end
  end

  if blocking
    executor.call
  else
    Thread.new(&executor)
  end
end

.run_script(script_name, blocking: false, success_codes: [0], command: nil) ⇒ Array

Runs a script in the script directory indicated by the SCRIPT_PATH environment variable.

Parameters:

  • script_name (String)

    The name of the script to run

  • blocking (Boolean) (defaults to: false)

    Optional. Whether to wait for a return code before proceeding

  • success_codes (Array) (defaults to: [0])

    Optional. An array of integer codes which indicate the run was successful

  • command (String) (defaults to: nil)

    Optional. Command to run the script with, e.g. ‘ruby’.

Returns:

  • (Array)

    If blocking, the output and exit_status are returned



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/maze/runner.rb', line 63

def run_script(script_name, blocking: false, success_codes: [0], command: nil)
  script_path = File.join(SCRIPT_PATH, script_name)
  script_path = File.join(Dir.pwd, script_name) unless File.exist? script_path
  if command
    script_path = "#{command} #{script_path}"
  elsif Gem.win_platform?
    # Windows does not support the shebang that we use in the scripts so it
    # needs to know how to execute the script. Passing `cmd /c` tells windows
    # to use its known file associations to execute this path. If Ruby is
    # installed on Windows then it will know that `rb` files should be executed
    # using Ruby etc.
    script_path = "cmd /c #{script_path}"
  end
  run_command(script_path, blocking: blocking, success_codes: success_codes)
end

.start_interactive_session(*args) ⇒ InteractiveCLI

Creates a new interactive session. Can only be called if no session already exists. Check with interactive_session? if necessary.

Returns:



83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/maze/runner.rb', line 83

def start_interactive_session(*args)
  raise 'An interactive session is already running!' if interactive_session?

  wait = Maze::Wait.new(interval: 0.3, timeout: 3)

  interactive_session = InteractiveCLI.new(*args)

  success = wait.until { interactive_session.running? }
  raise 'Shell session did not start in time!' unless success

  @interactive_session = interactive_session
end

.stop_interactive_sessionBoolean

Stops the interactive session, allowing a new one to be started

Returns:

  • (Boolean)

    True if the interactive session exited successfully



109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/maze/runner.rb', line 109

def stop_interactive_session
  raise 'No interactive session is running!' unless interactive_session?

  success = @interactive_session.stop

  # Make sure the process is killed if it did not stop
  pids << @interactive_session.pid if @interactive_session.running?

  @interactive_session = nil

  success
end