2012-04-17 13:17:24 -05:00
|
|
|
# Comprehensively test a formula or pull request.
|
|
|
|
#
|
|
|
|
# Usage: brew test-bot [options...] <pull-request|formula>
|
|
|
|
#
|
|
|
|
# Options:
|
2012-12-22 21:21:34 +00:00
|
|
|
# --keep-logs: Write and keep log files under ./brewbot/
|
2012-11-10 09:17:21 +00:00
|
|
|
# --cleanup: Clean the Homebrew directory. Very dangerous. Use with care.
|
|
|
|
# --skip-setup: Don't check the local system is setup correctly.
|
2013-05-25 21:32:43 +01:00
|
|
|
# --junit: Generate a JUnit XML test results file.
|
2013-06-22 10:54:14 +01:00
|
|
|
# --email: Generate an email subject file.
|
2013-09-10 22:10:58 +01:00
|
|
|
# --no-bottle: Run brew install without --build-bottle
|
2013-07-17 18:12:14 -07:00
|
|
|
# --HEAD: Run brew install with --HEAD
|
2012-04-17 13:17:24 -05:00
|
|
|
|
2012-08-25 13:46:16 -07:00
|
|
|
require 'formula'
|
2012-04-17 13:17:24 -05:00
|
|
|
require 'utils'
|
|
|
|
require 'date'
|
2013-10-08 16:32:59 +01:00
|
|
|
require 'rexml/document'
|
|
|
|
require 'rexml/xmldecl'
|
|
|
|
require 'rexml/cdata'
|
2012-04-17 13:17:24 -05:00
|
|
|
|
2013-09-14 13:41:40 +01:00
|
|
|
EMAIL_SUBJECT_FILE = "brew-test-bot.#{MacOS.cat}.email.txt"
|
2012-04-17 13:17:24 -05:00
|
|
|
|
|
|
|
class Step
|
2013-05-25 22:58:02 +01:00
|
|
|
attr_reader :command, :name, :status, :output, :time
|
2012-04-17 13:17:24 -05:00
|
|
|
|
2013-06-04 20:37:30 +01:00
|
|
|
def initialize test, command, options={}
|
2012-04-17 13:17:24 -05:00
|
|
|
@test = test
|
|
|
|
@category = test.category
|
|
|
|
@command = command
|
2013-06-04 20:37:30 +01:00
|
|
|
@puts_output_on_success = options[:puts_output_on_success]
|
2012-04-17 13:17:24 -05:00
|
|
|
@name = command.split[1].delete '-'
|
|
|
|
@status = :running
|
2012-11-10 09:17:21 +00:00
|
|
|
@repository = HOMEBREW_REPOSITORY
|
2013-05-25 22:58:02 +01:00
|
|
|
@time = 0
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def log_file_path full_path=true
|
|
|
|
file = "#{@category}.#{@name}.txt"
|
|
|
|
return file unless @test.log_root and full_path
|
|
|
|
@test.log_root + file
|
|
|
|
end
|
|
|
|
|
|
|
|
def status_colour
|
|
|
|
case @status
|
|
|
|
when :passed then "green"
|
|
|
|
when :running then "orange"
|
|
|
|
when :failed then "red"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def status_upcase
|
|
|
|
@status.to_s.upcase
|
|
|
|
end
|
|
|
|
|
2013-06-29 01:31:19 +01:00
|
|
|
def command_short
|
2013-09-21 21:24:50 +01:00
|
|
|
@command.gsub(/(brew|--force|--verbose|--build-bottle|--rb) /, '').strip.squeeze ' '
|
2013-06-29 01:31:19 +01:00
|
|
|
end
|
|
|
|
|
2013-05-26 01:11:12 +01:00
|
|
|
def passed?
|
|
|
|
@status == :passed
|
|
|
|
end
|
|
|
|
|
2013-05-25 22:58:02 +01:00
|
|
|
def failed?
|
|
|
|
@status == :failed
|
2013-05-25 22:07:28 +01:00
|
|
|
end
|
|
|
|
|
2012-04-17 13:17:24 -05:00
|
|
|
def puts_command
|
|
|
|
print "#{Tty.blue}==>#{Tty.white} #{@command}#{Tty.reset}"
|
|
|
|
tabs = (80 - "PASSED".length + 1 - @command.length) / 8
|
|
|
|
tabs.times{ print "\t" }
|
|
|
|
$stdout.flush
|
|
|
|
end
|
|
|
|
|
|
|
|
def puts_result
|
2013-06-02 13:01:20 +01:00
|
|
|
puts " #{Tty.send status_colour}#{status_upcase}#{Tty.reset}"
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
|
2013-05-25 22:58:02 +01:00
|
|
|
def has_output?
|
|
|
|
@output and @output.any?
|
|
|
|
end
|
|
|
|
|
2013-05-25 22:07:28 +01:00
|
|
|
def run
|
|
|
|
puts_command
|
2012-11-10 09:05:31 +00:00
|
|
|
|
2013-05-25 22:58:02 +01:00
|
|
|
start_time = Time.now
|
2013-06-29 01:31:01 +01:00
|
|
|
run_command = "#{@command} &>'#{log_file_path}'"
|
2013-05-25 22:07:28 +01:00
|
|
|
if run_command.start_with? 'git '
|
|
|
|
Dir.chdir @repository do
|
|
|
|
`#{run_command}`
|
2012-11-10 09:36:58 +00:00
|
|
|
end
|
2012-11-10 09:05:31 +00:00
|
|
|
else
|
2013-05-25 22:07:28 +01:00
|
|
|
`#{run_command}`
|
2012-11-10 09:05:31 +00:00
|
|
|
end
|
2013-05-25 22:58:02 +01:00
|
|
|
end_time = Time.now
|
|
|
|
@time = end_time - start_time
|
2012-11-10 09:05:31 +00:00
|
|
|
|
2012-12-22 21:21:34 +00:00
|
|
|
success = $?.success?
|
2013-05-25 22:07:28 +01:00
|
|
|
@status = success ? :passed : :failed
|
|
|
|
puts_result
|
|
|
|
|
|
|
|
return unless File.exists?(log_file_path)
|
|
|
|
@output = IO.read(log_file_path)
|
2013-05-25 22:58:02 +01:00
|
|
|
if has_output? and (not success or @puts_output_on_success)
|
2013-05-25 22:07:28 +01:00
|
|
|
puts @output
|
2012-12-22 21:21:34 +00:00
|
|
|
end
|
2013-05-25 22:07:28 +01:00
|
|
|
FileUtils.rm log_file_path unless ARGV.include? "--keep-logs"
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class Test
|
2013-06-15 10:42:39 +01:00
|
|
|
attr_reader :log_root, :category, :name, :formulae, :steps
|
2012-04-17 13:17:24 -05:00
|
|
|
|
2012-11-25 12:52:35 +00:00
|
|
|
def initialize argument
|
2012-12-01 11:46:12 +00:00
|
|
|
@hash = nil
|
2012-11-25 12:47:36 +00:00
|
|
|
@url = nil
|
|
|
|
@formulae = []
|
|
|
|
|
2013-06-02 12:48:57 +01:00
|
|
|
url_match = argument.match HOMEBREW_PULL_OR_COMMIT_URL_REGEX
|
2012-11-25 12:52:35 +00:00
|
|
|
formula = Formula.factory argument rescue FormulaUnavailableError
|
2012-12-01 11:46:12 +00:00
|
|
|
git "rev-parse --verify #{argument} &>/dev/null"
|
2012-11-25 12:47:36 +00:00
|
|
|
if $?.success?
|
2012-12-01 11:46:12 +00:00
|
|
|
@hash = argument
|
2012-11-25 12:47:36 +00:00
|
|
|
elsif url_match
|
|
|
|
@url = url_match[0]
|
|
|
|
elsif formula
|
2012-11-25 12:52:35 +00:00
|
|
|
@formulae = [argument]
|
2012-11-25 12:47:36 +00:00
|
|
|
else
|
2012-11-25 12:52:35 +00:00
|
|
|
odie "#{argument} is not a pull request URL, commit URL or formula name."
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
@category = __method__
|
|
|
|
@steps = []
|
|
|
|
@brewbot_root = Pathname.pwd + "brewbot"
|
2012-12-22 21:21:34 +00:00
|
|
|
FileUtils.mkdir_p @brewbot_root
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
|
2013-09-14 12:33:53 +01:00
|
|
|
def no_args?
|
|
|
|
@hash == 'HEAD'
|
|
|
|
end
|
|
|
|
|
2012-11-10 09:05:31 +00:00
|
|
|
def git arguments
|
|
|
|
Dir.chdir HOMEBREW_REPOSITORY do
|
|
|
|
`git #{arguments}`
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-04-17 13:17:24 -05:00
|
|
|
def download
|
2013-05-26 01:34:16 +01:00
|
|
|
def shorten_revision revision
|
|
|
|
git("rev-parse --short #{revision}").strip
|
|
|
|
end
|
|
|
|
|
2012-04-17 13:17:24 -05:00
|
|
|
def current_sha1
|
2013-05-26 01:34:16 +01:00
|
|
|
shorten_revision 'HEAD'
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def current_branch
|
2012-12-25 19:19:52 +00:00
|
|
|
git('symbolic-ref HEAD').gsub('refs/heads/', '').strip
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
|
2013-06-02 13:01:02 +01:00
|
|
|
def single_commit? start_revision, end_revision
|
|
|
|
git("rev-list --count #{start_revision}..#{end_revision}").to_i == 1
|
|
|
|
end
|
|
|
|
|
2012-04-17 13:17:24 -05:00
|
|
|
@category = __method__
|
2012-12-01 11:46:12 +00:00
|
|
|
@start_branch = current_branch
|
|
|
|
|
2013-05-26 01:11:12 +01:00
|
|
|
# Use Jenkins environment variables if present.
|
2013-09-14 12:34:56 +01:00
|
|
|
if no_args? and ENV['GIT_PREVIOUS_COMMIT'] and ENV['GIT_COMMIT'] \
|
2013-06-15 11:15:31 +01:00
|
|
|
and not ENV['ghprbPullId']
|
2013-05-26 01:34:16 +01:00
|
|
|
diff_start_sha1 = shorten_revision ENV['GIT_PREVIOUS_COMMIT']
|
|
|
|
diff_end_sha1 = shorten_revision ENV['GIT_COMMIT']
|
2013-05-26 01:11:12 +01:00
|
|
|
test "brew update" if current_branch == "master"
|
|
|
|
elsif @hash or @url
|
2012-12-01 11:46:12 +00:00
|
|
|
diff_start_sha1 = current_sha1
|
2012-04-17 13:17:24 -05:00
|
|
|
test "brew update" if current_branch == "master"
|
2012-12-01 11:46:12 +00:00
|
|
|
diff_end_sha1 = current_sha1
|
|
|
|
end
|
|
|
|
|
2013-06-15 10:44:08 +01:00
|
|
|
# Handle Jenkins pull request builder plugin.
|
|
|
|
if ENV['ghprbPullId'] and ENV['GIT_URL']
|
|
|
|
git_url = ENV['GIT_URL']
|
|
|
|
git_match = git_url.match %r{.*github.com[:/](\w+/\w+).*}
|
|
|
|
if git_match
|
|
|
|
github_repo = git_match[1]
|
|
|
|
pull_id = ENV['ghprbPullId']
|
|
|
|
@url = "https://github.com/#{github_repo}/pull/#{pull_id}"
|
2013-06-15 11:00:32 +01:00
|
|
|
@hash = nil
|
2013-06-15 11:15:31 +01:00
|
|
|
else
|
|
|
|
puts "Invalid 'ghprbPullId' environment variable value!"
|
2013-06-15 10:44:08 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-09-14 12:33:53 +01:00
|
|
|
if no_args?
|
2013-06-02 13:01:02 +01:00
|
|
|
if diff_start_sha1 == diff_end_sha1 or \
|
|
|
|
single_commit?(diff_start_sha1, diff_end_sha1)
|
2013-05-26 01:39:59 +01:00
|
|
|
@name = diff_end_sha1
|
|
|
|
else
|
|
|
|
@name = "#{diff_start_sha1}-#{diff_end_sha1}"
|
|
|
|
end
|
2012-12-01 11:46:12 +00:00
|
|
|
elsif @hash
|
|
|
|
test "git checkout #{@hash}"
|
|
|
|
diff_start_sha1 = "#{@hash}^"
|
|
|
|
diff_end_sha1 = @hash
|
|
|
|
@name = @hash
|
|
|
|
elsif @url
|
|
|
|
test "git checkout #{current_sha1}"
|
2012-04-17 13:17:24 -05:00
|
|
|
test "brew pull --clean #{@url}"
|
2012-12-01 11:46:12 +00:00
|
|
|
diff_end_sha1 = current_sha1
|
2013-06-02 13:01:02 +01:00
|
|
|
@short_url = @url.gsub('https://github.com/', '')
|
|
|
|
if @short_url.include? '/commit/'
|
|
|
|
# 7 characters should be enough for a commit (not 40).
|
|
|
|
@short_url.gsub!(/(commit\/\w{7}).*/, '\1')
|
|
|
|
@name = @short_url
|
|
|
|
else
|
|
|
|
@name = "#{@short_url}-#{diff_end_sha1}"
|
|
|
|
end
|
2012-04-17 13:17:24 -05:00
|
|
|
else
|
2012-12-01 11:46:12 +00:00
|
|
|
diff_start_sha1 = diff_end_sha1 = current_sha1
|
|
|
|
@name = "#{@formulae.first}-#{diff_end_sha1}"
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
@log_root = @brewbot_root + @name
|
2012-12-22 21:21:34 +00:00
|
|
|
FileUtils.mkdir_p @log_root
|
2012-12-01 11:46:12 +00:00
|
|
|
|
|
|
|
return unless diff_start_sha1 != diff_end_sha1
|
2013-05-26 01:11:12 +01:00
|
|
|
return if @url and not steps.last.passed?
|
2012-04-17 13:17:24 -05:00
|
|
|
|
2012-12-01 11:46:12 +00:00
|
|
|
diff_stat = git "diff #{diff_start_sha1}..#{diff_end_sha1} --name-status"
|
|
|
|
diff_stat.each_line do |line|
|
2012-04-17 13:17:24 -05:00
|
|
|
status, filename = line.split
|
|
|
|
# Don't try and do anything to removed files.
|
|
|
|
if (status == 'A' or status == 'M')
|
2013-11-15 00:06:50 +00:00
|
|
|
if filename.match /Formula\/.+\.rb$/
|
2012-04-17 13:17:24 -05:00
|
|
|
@formulae << File.basename(filename, '.rb')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def setup
|
|
|
|
@category = __method__
|
|
|
|
|
|
|
|
test "brew doctor"
|
|
|
|
test "brew --env"
|
|
|
|
test "brew --config"
|
|
|
|
end
|
|
|
|
|
|
|
|
def formula formula
|
|
|
|
@category = __method__.to_s + ".#{formula}"
|
|
|
|
|
2013-09-07 12:04:54 +01:00
|
|
|
test "brew uses #{formula}"
|
2012-12-16 19:39:54 +00:00
|
|
|
dependencies = `brew deps #{formula}`.split("\n")
|
|
|
|
dependencies -= `brew list`.split("\n")
|
|
|
|
dependencies = dependencies.join(' ')
|
2012-12-22 21:21:34 +00:00
|
|
|
formula_object = Formula.factory(formula)
|
2013-06-03 20:28:16 +01:00
|
|
|
requirements = formula_object.recursive_requirements
|
|
|
|
unsatisfied_requirements = requirements.reject {|r| r.satisfied?}
|
|
|
|
unless unsatisfied_requirements.empty?
|
|
|
|
puts "#{Tty.blue}==>#{Tty.white} SKIPPING: #{formula}#{Tty.reset}"
|
|
|
|
unsatisfied_requirements.each {|r| puts r.message}
|
|
|
|
return
|
|
|
|
end
|
2012-12-16 19:39:54 +00:00
|
|
|
|
|
|
|
test "brew fetch #{dependencies}" unless dependencies.empty?
|
2013-10-12 18:12:18 +01:00
|
|
|
formula_fetch_options = " "
|
2013-09-10 22:10:58 +01:00
|
|
|
formula_fetch_options << " --build-bottle" unless ARGV.include? '--no-bottle'
|
2013-07-17 22:08:21 -07:00
|
|
|
formula_fetch_options << " --force" if ARGV.include? '--cleanup'
|
2013-10-12 18:12:18 +01:00
|
|
|
test "brew fetch#{formula_fetch_options} #{formula}"
|
2013-07-04 10:52:55 +01:00
|
|
|
test "brew uninstall --force #{formula}" if formula_object.installed?
|
2013-09-10 22:10:58 +01:00
|
|
|
install_args = '--verbose'
|
|
|
|
install_args << ' --build-bottle' unless ARGV.include? '--no-bottle'
|
2013-07-17 18:12:14 -07:00
|
|
|
install_args << ' --HEAD' if ARGV.include? '--HEAD'
|
|
|
|
test "brew install #{install_args} #{formula}"
|
2013-07-15 19:33:03 -07:00
|
|
|
install_passed = steps.last.passed?
|
|
|
|
test "brew audit #{formula}"
|
2013-10-12 18:16:02 +01:00
|
|
|
if install_passed
|
|
|
|
unless ARGV.include? '--no-bottle'
|
|
|
|
test "brew bottle --rb #{formula}", :puts_output_on_success => true
|
|
|
|
bottle_step = steps.last
|
|
|
|
if bottle_step.passed? and bottle_step.has_output?
|
|
|
|
bottle_filename =
|
|
|
|
bottle_step.output.gsub(/.*(\.\/\S+#{bottle_native_regex}).*/m, '\1')
|
|
|
|
test "brew uninstall --force #{formula}"
|
|
|
|
test "brew install #{bottle_filename}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
test "brew test --verbose #{formula}" if formula_object.test_defined?
|
|
|
|
test "brew uninstall --force #{formula}"
|
|
|
|
end
|
|
|
|
if formula_object.devel and not ARGV.include? '--HEAD'
|
|
|
|
test "brew fetch --devel#{formula_fetch_options} #{formula}"
|
|
|
|
test "brew install --devel --verbose #{formula}"
|
|
|
|
devel_install_passed = steps.last.passed?
|
|
|
|
test "brew audit --devel #{formula}"
|
|
|
|
if devel_install_passed
|
|
|
|
test "brew test --devel --verbose #{formula}" if formula_object.test_defined?
|
|
|
|
test "brew uninstall --devel --force #{formula}"
|
2013-06-04 20:37:30 +01:00
|
|
|
end
|
|
|
|
end
|
2013-07-04 10:52:55 +01:00
|
|
|
test "brew uninstall --force #{dependencies}" unless dependencies.empty?
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def homebrew
|
|
|
|
@category = __method__
|
|
|
|
test "brew tests"
|
2012-11-25 12:47:36 +00:00
|
|
|
test "brew readall"
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
|
2012-12-01 11:46:12 +00:00
|
|
|
def cleanup_before
|
2012-04-17 13:17:24 -05:00
|
|
|
@category = __method__
|
2012-12-01 11:46:12 +00:00
|
|
|
return unless ARGV.include? '--cleanup'
|
2013-01-26 12:43:41 +00:00
|
|
|
git 'stash'
|
2012-12-01 11:46:12 +00:00
|
|
|
git 'am --abort 2>/dev/null'
|
|
|
|
git 'rebase --abort 2>/dev/null'
|
2012-12-22 21:21:34 +00:00
|
|
|
git 'reset --hard'
|
2013-07-15 21:18:32 -07:00
|
|
|
git 'checkout -f master'
|
2012-12-22 21:21:34 +00:00
|
|
|
git 'clean --force -dx'
|
2012-12-01 11:46:12 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def cleanup_after
|
|
|
|
@category = __method__
|
|
|
|
force_flag = ''
|
|
|
|
if ARGV.include? '--cleanup'
|
|
|
|
test 'brew cleanup'
|
|
|
|
test 'git clean --force -dx'
|
|
|
|
force_flag = '-f'
|
|
|
|
end
|
|
|
|
|
|
|
|
if ARGV.include? '--cleanup' or @url or @hash
|
|
|
|
test "git checkout #{force_flag} #{@start_branch}"
|
|
|
|
end
|
|
|
|
|
|
|
|
if ARGV.include? '--cleanup'
|
|
|
|
test 'git reset --hard'
|
2012-12-22 21:21:34 +00:00
|
|
|
git 'stash pop 2>/dev/null'
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
2012-12-22 21:21:34 +00:00
|
|
|
|
|
|
|
FileUtils.rm_rf @brewbot_root unless ARGV.include? "--keep-logs"
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
|
2013-06-04 20:37:30 +01:00
|
|
|
def test cmd, options={}
|
|
|
|
step = Step.new self, cmd, options
|
2013-05-25 22:07:28 +01:00
|
|
|
step.run
|
|
|
|
steps << step
|
2013-06-04 20:37:30 +01:00
|
|
|
step
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def check_results
|
|
|
|
message = "All tests passed and raring to brew."
|
|
|
|
|
|
|
|
status = :passed
|
|
|
|
steps.each do |step|
|
|
|
|
case step.status
|
|
|
|
when :passed then next
|
|
|
|
when :running then raise
|
|
|
|
when :failed then
|
|
|
|
if status == :passed
|
|
|
|
status = :failed
|
|
|
|
message = ""
|
|
|
|
end
|
|
|
|
message += "#{step.command}: #{step.status.to_s.upcase}\n"
|
|
|
|
end
|
|
|
|
end
|
2012-12-22 21:21:34 +00:00
|
|
|
status == :passed
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
|
2013-05-25 21:32:43 +01:00
|
|
|
def run
|
|
|
|
cleanup_before
|
|
|
|
download
|
|
|
|
setup unless ARGV.include? "--skip-setup"
|
2013-06-15 10:42:39 +01:00
|
|
|
homebrew
|
2013-05-25 21:32:43 +01:00
|
|
|
formulae.each do |f|
|
|
|
|
formula(f)
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
2013-05-25 21:32:43 +01:00
|
|
|
cleanup_after
|
|
|
|
check_results
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-11-25 13:03:13 +00:00
|
|
|
if Pathname.pwd == HOMEBREW_PREFIX and ARGV.include? "--cleanup"
|
|
|
|
odie 'cannot use --cleanup from HOMEBREW_PREFIX as it will delete all output.'
|
|
|
|
end
|
|
|
|
|
2013-06-27 00:24:16 +01:00
|
|
|
if ARGV.include? "--email"
|
|
|
|
File.open EMAIL_SUBJECT_FILE, 'w' do |file|
|
2013-06-29 13:18:40 +01:00
|
|
|
# The file should be written at the end but in case we don't get to that
|
|
|
|
# point ensure that we have something valid.
|
2013-09-14 13:41:40 +01:00
|
|
|
file.write "#{MacOS.version}: internal error."
|
2013-06-27 00:24:16 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-05-25 21:32:43 +01:00
|
|
|
tests = []
|
2012-12-22 21:21:34 +00:00
|
|
|
any_errors = false
|
2012-11-25 12:47:36 +00:00
|
|
|
if ARGV.named.empty?
|
|
|
|
# With no arguments just build the most recent commit.
|
2013-05-25 21:32:43 +01:00
|
|
|
test = Test.new('HEAD')
|
|
|
|
any_errors = test.run
|
|
|
|
tests << test
|
2012-11-25 12:47:36 +00:00
|
|
|
else
|
2013-05-25 21:32:43 +01:00
|
|
|
ARGV.named.each do |argument|
|
|
|
|
test = Test.new(argument)
|
|
|
|
any_errors = test.run or any_errors
|
|
|
|
tests << test
|
|
|
|
end
|
2012-04-17 13:17:24 -05:00
|
|
|
end
|
2013-05-25 21:32:43 +01:00
|
|
|
|
|
|
|
if ARGV.include? "--junit"
|
2013-10-08 16:32:59 +01:00
|
|
|
xml_document = REXML::Document.new
|
|
|
|
xml_document << REXML::XMLDecl.new
|
|
|
|
testsuites = xml_document.add_element 'testsuites'
|
|
|
|
tests.each do |test|
|
|
|
|
testsuite = testsuites.add_element 'testsuite'
|
|
|
|
testsuite.attributes['name'] = "brew-test-bot.#{MacOS.cat}"
|
|
|
|
testsuite.attributes['tests'] = test.steps.count
|
|
|
|
test.steps.each do |step|
|
|
|
|
testcase = testsuite.add_element 'testcase'
|
|
|
|
testcase.attributes['name'] = step.command_short
|
|
|
|
testcase.attributes['status'] = step.status
|
|
|
|
testcase.attributes['time'] = step.time
|
|
|
|
failure = testcase.add_element 'failure' if step.failed?
|
|
|
|
if step.has_output?
|
2013-10-09 09:04:31 +01:00
|
|
|
# Remove invalid XML CData characters from step output.
|
|
|
|
output = REXML::CData.new step.output.delete("\000\e")
|
2013-10-08 16:32:59 +01:00
|
|
|
if step.passed?
|
|
|
|
system_out = testcase.add_element 'system-out'
|
|
|
|
system_out.text = output
|
|
|
|
else
|
|
|
|
failure.attributes['message'] = "#{step.status}: #{step.command}"
|
|
|
|
failure.text = output
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
open("brew-test-bot.xml", "w") do |xml_file|
|
|
|
|
pretty_print_indent = 2
|
|
|
|
xml_document.write(xml_file, pretty_print_indent)
|
2013-05-25 21:32:43 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-06-22 10:54:14 +01:00
|
|
|
if ARGV.include? "--email"
|
|
|
|
failed_steps = []
|
|
|
|
tests.each do |test|
|
|
|
|
test.steps.each do |step|
|
|
|
|
next unless step.failed?
|
2013-06-29 01:31:19 +01:00
|
|
|
failed_steps << step.command_short
|
2013-06-22 10:54:14 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if failed_steps.empty?
|
2013-09-14 13:41:40 +01:00
|
|
|
email_subject = ''
|
2013-06-22 10:54:14 +01:00
|
|
|
else
|
2013-09-14 13:41:40 +01:00
|
|
|
email_subject = "#{MacOS.version}: #{failed_steps.join ', '}."
|
2013-06-22 10:54:14 +01:00
|
|
|
end
|
|
|
|
|
2013-06-27 00:24:16 +01:00
|
|
|
File.open EMAIL_SUBJECT_FILE, 'w' do |file|
|
2013-06-22 10:54:14 +01:00
|
|
|
file.write email_subject
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-12-22 21:21:34 +00:00
|
|
|
exit any_errors ? 0 : 1
|