Skip to content

Commit 5a14e20

Browse files
author
Kevin Paulisse
committed
Keep track of stdout, stderr, exit status within the object
1 parent 1e0d735 commit 5a14e20

2 files changed

Lines changed: 45 additions & 1 deletion

File tree

lib/octocatalog-diff/util/scriptrunner.rb

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ module OctocatalogDiff
1010
module Util
1111
# This is a utility class to execute a built-in script.
1212
class ScriptRunner
13-
attr_reader :script, :logger
13+
# For an exception running the script
14+
class ScriptException < RuntimeError; end
15+
16+
attr_reader :script, :logger, :stdout, :stderr, :exitcode
1417

1518
# Create the object - the object is a configured script, which can be executed multiple
1619
# times with different environment varibles.
@@ -22,17 +25,39 @@ class ScriptRunner
2225
def initialize(opts = {})
2326
@logger = opts.fetch(:logger)
2427
@script = find_script(opts.fetch(:default_script), opts[:override_script_path])
28+
@stdout = nil
29+
@stderr = nil
30+
@exitcode = nil
2531
end
2632

2733
# Execute the script from a given working directory, with additional environment variables
2834
# specified in the options hash.
2935
#
3036
# @param opts [Hash] Options hash
3137
# opts[:working_dir] (Required) Directory where script is to be executed
38+
# opts[:argv] (Optional Array) Command line arguments
3239
# opts[<STRING>] (Optional) Environment variable
3340
def run(opts = {})
3441
working_dir = opts.fetch(:working_dir)
3542
assert_directory_exists(working_dir)
43+
44+
argv = opts.fetch(:argv, [])
45+
46+
env = opts.select { |k, _v| k.is_a?(String) }
47+
env['HOME'] ||= ENV['HOME']
48+
env['PWD'] = working_dir
49+
env['PATH'] ||= ENV['PATH']
50+
51+
cmdline = [@script, argv].flatten.compact.map { |x| Shellwords.escape(x) }.join(' ')
52+
@logger.debug "Execute: #{cmdline}"
53+
54+
@stdout, @stderr, status = Open3.capture3(env, cmdline, unsetenv_others: true, chdir: working_dir)
55+
@exitcode = status.exitstatus
56+
57+
@stderr.split(/\n/).select { |line| line =~ /\S/ }.each { |line| @logger.debug "STDERR: #{line}" }
58+
@logger.debug "Exit status: #{@exitcode}"
59+
return @stdout if @exitcode.zero?
60+
raise ScriptException, [@stdout.split(/\n/), @stderr.split(/\n/)].compact.join("\n")
3661
end
3762

3863
private

spec/octocatalog-diff/tests/util/scriptrunner_spec.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

33
require_relative '../spec_helper'
4+
require 'ostruct'
45
require OctocatalogDiff::Spec.require_path('/util/scriptrunner')
56

67
describe OctocatalogDiff::Util::ScriptRunner do
@@ -71,5 +72,23 @@
7172
}
7273
expect { @described_obj.run(opts) }.to raise_error(Errno::ENOENT)
7374
end
75+
76+
it 'should raise ScriptException when script fails' do
77+
stdout = 'Something was printed'
78+
stderr = "The command failed to run\nSomething must be busted\n"
79+
exitstatus = OpenStruct.new(exitstatus: 42)
80+
expect(Open3).to receive(:capture3).and_return([stdout, stderr, exitstatus])
81+
82+
opts = {
83+
working_dir: File.dirname(__FILE__),
84+
argv: %w(foo bar)
85+
}
86+
87+
expect { @described_obj.run(opts) }.to raise_error(OctocatalogDiff::Util::ScriptRunner::ScriptException)
88+
89+
expect(@described_obj.stdout).to eq(stdout)
90+
expect(@described_obj.stderr).to eq(stderr)
91+
expect(@described_obj.exitcode).to eq(42)
92+
end
7493
end
7594
end

0 commit comments

Comments
 (0)