lib/jive.rb in jive-0.1.0 vs lib/jive.rb in jive-0.2.0

- old
+ new

@@ -1,144 +1,17 @@ # frozen_string_literal: true require "fileutils" -require "jive/version" require "open3" +require "jive/batch_runner" +require "jive/popen" +require "jive/runner" +require "jive/version" + module Jive class Error < StandardError; end def self.run(tasks) Jive::BatchRunner.new.run(tasks) - end - - module Popen - Result = Struct.new(:command, :stdout, :stderr, :status, :duration) - - def self.popen(command, path = nil, env = {}, &block) - result = popen_with_detail(command, path, env, &block) - - ["#{result.stdout}#{result.stderr}", result.status&.exitstatus] - end - - def self.popen_with_detail(command, path = Dir.pwd, env = {}) - FileUtils.mkdir_p(path) unless File.directory?(path) - - captured_stdout = '' - captured_stderr = '' - exit_status = nil - start = Time.now - - Open3.popen3(env.merge('PWD' => path), *Array(command), { chdir: path }) do |stdin, stdout, stderr, wait_thr| - out_reader = Thread.new { stdout.read } - err_reader = Thread.new { stderr.read } - - yield(stdin) if block_given? - - stdin.close - captured_stdout = out_reader.value - captured_stderr = err_reader.value - exit_status = wait_thr.value - end - Result.new(command, captured_stdout, captured_stderr, exit_status, Time.now - start) - end - end - - class BatchRunner - attr_reader :runner, :stdout - - def initialize(runner: Runner.new, stdout: STDOUT) - @runner = runner - @stdout = stdout - end - - def run(tasks, verbose: true) - runner.run(tasks) do |command, &run| - stdout.puts - stdout.puts "$ #{command.join(' ')}" - result = run.call - stdout.print result.stdout if verbose - stdout.print result.stderr if verbose - stdout.puts "==> Finished in #{result.duration} seconds" - stdout.puts - end - stdout.puts '===================================================' - if runner.all_success_and_clean? - stdout.puts 'Passed successfully.' - return 0 - elsif runner.all_success? - stdout.puts 'Passed successfully, but we have warnings:' - stdout.puts - emit_warnings - return 2 - else - stdout.puts 'Something failed:' - emit_warnings - emit_errors - return 1 - end - end - - private - - def emit_warnings - runner.warned_results.each do |result| - stdout.puts - stdout.puts "**** #{result.command.join(' ')} had the following warning(s):" - stdout.puts - stdout.puts result.stderr - stdout.puts - end - end - - def emit_errors - runner.failed_results.each do |result| - stdout.puts - stdout.puts "**** #{result.command.join(' ')} failed with the following error(s):" - stdout.puts - stdout.puts result.stdout - stdout.puts result.stderr - stdout.puts - end - end - end - - class Runner - attr_reader :results - - def initialize - @results = [] - end - - def run(commands, &block) - commands.each do |command| - block.call(command) do - cmd_result = Popen.popen_with_detail(command) - results << cmd_result - cmd_result - end - end - end - - def all_success_and_clean? - all_success? && all_stderr_empty? - end - - def all_success? - results.all? { |result| result.status.success? } - end - - def all_stderr_empty? - results.all? { |result| result.stderr.empty? } - end - - def failed_results - results.reject { |result| result.status.success? } - end - - def warned_results - results.select do |result| - result.status.success? && !result.stderr.empty? - end - end end end