Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
B
brew
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to JiHu GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
KMSCAKKSCFKA AKFACAMADCAS
brew
Commits
b7c9025d
Commit
b7c9025d
authored
Sep 20, 2014
by
Mike McQuaid
Browse files
Options
Downloads
Patches
Plain Diff
brew-test-bot: make an internal command.
parent
bd8559c7
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
Library/Contributions/cmd/brew-test-bot.rb
+0
-663
0 additions, 663 deletions
Library/Contributions/cmd/brew-test-bot.rb
Library/Homebrew/cmd/test-bot.rb
+666
-0
666 additions, 0 deletions
Library/Homebrew/cmd/test-bot.rb
with
666 additions
and
663 deletions
Library/Contributions/cmd/brew-test-bot.rb
deleted
100755 → 0
+
0
−
663
View file @
bd8559c7
# Comprehensively test a formula or pull request.
#
# Usage: brew test-bot [options...] <pull-request|formula>
#
# Options:
# --keep-logs: Write and keep log files under ./brewbot/
# --cleanup: Clean the Homebrew directory. Very dangerous. Use with care.
# --clean-cache: Remove all cached downloads. Use with care.
# --skip-setup: Don't check the local system is setup correctly.
# --junit: Generate a JUnit XML test results file.
# --email: Generate an email subject file.
# --no-bottle: Run brew install without --build-bottle
# --HEAD: Run brew install with --HEAD
# --local: Ask Homebrew to write verbose logs under ./logs/
# --tap=<tap>: Use the git repository of the given tap
# --dry-run: Just print commands, don't run them.
#
# --ci-master: Shortcut for Homebrew master branch CI options.
# --ci-pr: Shortcut for Homebrew pull request CI options.
# --ci-testing: Shortcut for Homebrew testing CI options.
# --ci-pr-upload: Homebrew CI pull request bottle upload.
# --ci-testing-upload: Homebrew CI testing bottle upload.
require
'formula'
require
'utils'
require
'date'
require
'rexml/document'
require
'rexml/xmldecl'
require
'rexml/cdata'
EMAIL_SUBJECT_FILE
=
"brew-test-bot.
#{
MacOS
.
cat
}
.email.txt"
def
homebrew_git_repo
tap
=
nil
if
tap
HOMEBREW_LIBRARY
/
"Taps/
#{
tap
}
"
else
HOMEBREW_REPOSITORY
end
end
class
Step
attr_reader
:command
,
:name
,
:status
,
:output
,
:time
def
initialize
test
,
command
,
options
=
{}
@test
=
test
@category
=
test
.
category
@command
=
command
@puts_output_on_success
=
options
[
:puts_output_on_success
]
@name
=
command
[
1
].
delete
(
"-"
)
@status
=
:running
@repository
=
options
[
:repository
]
||
HOMEBREW_REPOSITORY
@time
=
0
end
def
log_file_path
file
=
"
#{
@category
}
.
#{
@name
}
.txt"
root
=
@test
.
log_root
root
?
root
+
file
:
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
def
command_short
(
@command
-
%w[brew --force --retry --verbose --build-bottle --rb]
).
join
(
" "
)
end
def
passed?
@status
==
:passed
end
def
failed?
@status
==
:failed
end
def
puts_command
cmd
=
@command
.
join
(
" "
)
print
"
#{
Tty
.
blue
}
==>
#{
Tty
.
white
}
#{
cmd
}#{
Tty
.
reset
}
"
tabs
=
(
80
-
"PASSED"
.
length
+
1
-
cmd
.
length
)
/
8
tabs
.
times
{
print
"
\t
"
}
$stdout
.
flush
end
def
puts_result
puts
"
#{
Tty
.
send
status_colour
}#{
status_upcase
}#{
Tty
.
reset
}
"
end
def
has_output?
@output
&&
!
@output
.
empty?
end
def
run
puts_command
if
ARGV
.
include?
"--dry-run"
puts
@status
=
:passed
return
end
start_time
=
Time
.
now
log
=
log_file_path
pid
=
fork
do
File
.
open
(
log
,
"wb"
)
do
|
f
|
STDOUT
.
reopen
(
f
)
STDERR
.
reopen
(
f
)
end
Dir
.
chdir
(
@repository
)
if
@command
.
first
==
"git"
exec
(
*
@command
)
end
Process
.
wait
(
pid
)
@time
=
Time
.
now
-
start_time
@status
=
$?
.
success?
?
:passed
:
:failed
puts_result
if
File
.
exist?
(
log
)
@output
=
File
.
read
(
log
)
if
has_output?
and
(
failed?
or
@puts_output_on_success
)
puts
@output
end
FileUtils
.
rm
(
log
)
unless
ARGV
.
include?
"--keep-logs"
end
end
end
class
Test
attr_reader
:log_root
,
:category
,
:name
,
:steps
def
initialize
argument
,
tap
=
nil
@hash
=
nil
@url
=
nil
@formulae
=
[]
@steps
=
[]
@tap
=
tap
@repository
=
homebrew_git_repo
@tap
@repository_requires_tapping
=
!
@repository
.
directory?
url_match
=
argument
.
match
HOMEBREW_PULL_OR_COMMIT_URL_REGEX
# Tap repository if required, this is done before everything else
# because Formula parsing and/or git commit hash lookup depends on it.
test
"brew"
,
"tap"
,
@tap
if
@tap
&&
@repository_requires_tapping
begin
formula
=
Formulary
.
factory
(
argument
)
rescue
FormulaUnavailableError
end
git
"rev-parse"
,
"--verify"
,
"-q"
,
argument
if
$?
.
success?
@hash
=
argument
elsif
url_match
@url
=
url_match
[
0
]
elsif
formula
@formulae
=
[
argument
]
else
odie
"
#{
argument
}
is not a pull request URL, commit URL or formula name."
end
@category
=
__method__
@brewbot_root
=
Pathname
.
pwd
+
"brewbot"
FileUtils
.
mkdir_p
@brewbot_root
end
def
no_args?
@hash
==
'HEAD'
end
def
git
(
*
args
)
rd
,
wr
=
IO
.
pipe
pid
=
fork
do
rd
.
close
STDERR
.
reopen
(
"/dev/null"
)
STDOUT
.
reopen
(
wr
)
wr
.
close
Dir
.
chdir
@repository
exec
(
"git"
,
*
args
)
end
wr
.
close
Process
.
wait
(
pid
)
rd
.
read
ensure
rd
.
close
end
def
download
def
shorten_revision
revision
git
(
"rev-parse"
,
"--short"
,
revision
).
strip
end
def
current_sha1
shorten_revision
'HEAD'
end
def
current_branch
git
(
"symbolic-ref"
,
"HEAD"
).
gsub
(
"refs/heads/"
,
""
).
strip
end
def
single_commit?
start_revision
,
end_revision
git
(
"rev-list"
,
"--count"
,
"
#{
start_revision
}
..
#{
end_revision
}
"
).
to_i
==
1
end
@category
=
__method__
@start_branch
=
current_branch
# Use Jenkins environment variables if present.
if
no_args?
and
ENV
[
'GIT_PREVIOUS_COMMIT'
]
and
ENV
[
'GIT_COMMIT'
]
\
and
not
ENV
[
'ghprbPullId'
]
diff_start_sha1
=
shorten_revision
ENV
[
'GIT_PREVIOUS_COMMIT'
]
diff_end_sha1
=
shorten_revision
ENV
[
'GIT_COMMIT'
]
test
"brew"
,
"update"
if
current_branch
==
"master"
elsif
@hash
or
@url
diff_start_sha1
=
current_sha1
test
"brew"
,
"update"
if
current_branch
==
"master"
diff_end_sha1
=
current_sha1
end
# 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
}
"
@hash
=
nil
else
puts
"Invalid 'ghprbPullId' environment variable value!"
end
end
if
no_args?
if
diff_start_sha1
==
diff_end_sha1
or
\
single_commit?
(
diff_start_sha1
,
diff_end_sha1
)
@name
=
diff_end_sha1
else
@name
=
"
#{
diff_start_sha1
}
-
#{
diff_end_sha1
}
"
end
elsif
@hash
test
"git"
,
"checkout"
,
@hash
diff_start_sha1
=
"
#{
@hash
}
^"
diff_end_sha1
=
@hash
@name
=
@hash
elsif
@url
test
"git"
,
"checkout"
,
current_sha1
test
"brew"
,
"pull"
,
"--clean"
,
@url
diff_end_sha1
=
current_sha1
@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
else
diff_start_sha1
=
diff_end_sha1
=
current_sha1
@name
=
"
#{
@formulae
.
first
}
-
#{
diff_end_sha1
}
"
end
@log_root
=
@brewbot_root
+
@name
FileUtils
.
mkdir_p
@log_root
return
unless
diff_start_sha1
!=
diff_end_sha1
return
if
@url
and
not
steps
.
last
.
passed?
if
@tap
formula_path
=
%w[Formula HomebrewFormula]
.
find
{
|
dir
|
(
@repository
/
dir
).
directory?
}
||
""
else
formula_path
=
"Library/Formula"
end
git
(
"diff-tree"
,
"-r"
,
"--name-only"
,
"--diff-filter=AM"
,
diff_start_sha1
,
diff_end_sha1
,
"--"
,
formula_path
).
each_line
do
|
line
|
@formulae
<<
File
.
basename
(
line
.
chomp
,
".rb"
)
end
end
def
skip
formula
puts
"
#{
Tty
.
blue
}
==>
#{
Tty
.
white
}
SKIPPING:
#{
formula
}#{
Tty
.
reset
}
"
end
def
satisfied_requirements?
formula_object
,
spec
requirements
=
formula_object
.
send
(
spec
).
requirements
unsatisfied_requirements
=
requirements
.
reject
do
|
requirement
|
requirement
.
satisfied?
||
requirement
.
default_formula?
end
if
unsatisfied_requirements
.
empty?
true
else
formula
=
formula_object
.
name
formula
+=
" (
#{
spec
}
)"
unless
spec
==
:stable
skip
formula
unsatisfied_requirements
.
each
{
|
r
|
puts
r
.
message
}
false
end
end
def
setup
@category
=
__method__
return
if
ARGV
.
include?
"--skip-setup"
test
"brew"
,
"doctor"
test
"brew"
,
"--env"
test
"brew"
,
"config"
end
def
formula
formula
@category
=
__method__
.
to_s
+
".
#{
formula
}
"
test
"brew"
,
"uses"
,
formula
dependencies
=
`brew deps
#{
formula
}
`
.
split
(
"
\n
"
)
dependencies
-=
`brew list`
.
split
(
"
\n
"
)
unchanged_dependencies
=
dependencies
-
@formulae
changed_dependences
=
dependencies
-
unchanged_dependencies
formula_object
=
Formulary
.
factory
(
formula
)
return
unless
satisfied_requirements?
(
formula_object
,
:stable
)
installed_gcc
=
false
deps
=
formula_object
.
stable
.
deps
.
to_a
reqs
=
formula_object
.
stable
.
requirements
.
to_a
if
formula_object
.
devel
&&
!
ARGV
.
include?
(
'--HEAD'
)
deps
|=
formula_object
.
devel
.
deps
.
to_a
reqs
|=
formula_object
.
devel
.
requirements
.
to_a
end
begin
deps
.
each
{
|
d
|
CompilerSelector
.
select_for
(
d
.
to_formula
)
}
CompilerSelector
.
select_for
(
formula_object
)
rescue
CompilerSelectionError
=>
e
unless
installed_gcc
test
"brew"
,
"install"
,
"gcc"
installed_gcc
=
true
OS
::
Mac
.
clear_version_cache
retry
end
skip
formula
puts
e
.
message
return
end
if
(
deps
|
reqs
).
any?
{
|
d
|
d
.
name
==
"mercurial"
&&
d
.
build?
}
test
"brew"
,
"install"
,
"mercurial"
end
test
"brew"
,
"fetch"
,
"--retry"
,
*
unchanged_dependencies
unless
unchanged_dependencies
.
empty?
test
"brew"
,
"fetch"
,
"--retry"
,
"--build-bottle"
,
*
changed_dependences
unless
changed_dependences
.
empty?
formula_fetch_options
=
[]
formula_fetch_options
<<
"--build-bottle"
unless
ARGV
.
include?
"--no-bottle"
formula_fetch_options
<<
"--force"
if
ARGV
.
include?
"--cleanup"
formula_fetch_options
<<
formula
test
"brew"
,
"fetch"
,
"--retry"
,
*
formula_fetch_options
test
"brew"
,
"uninstall"
,
"--force"
,
formula
if
formula_object
.
installed?
install_args
=
%w[--verbose]
install_args
<<
"--build-bottle"
unless
ARGV
.
include?
"--no-bottle"
install_args
<<
"--HEAD"
if
ARGV
.
include?
"--HEAD"
install_args
<<
formula
# Don't care about e.g. bottle failures for dependencies.
ENV
[
"HOMEBREW_DEVELOPER"
]
=
nil
test
"brew"
,
"install"
,
"--only-dependencies"
,
*
install_args
unless
dependencies
.
empty?
ENV
[
"HOMEBREW_DEVELOPER"
]
=
"1"
test
"brew"
,
"install"
,
*
install_args
install_passed
=
steps
.
last
.
passed?
test
"brew"
,
"audit"
,
formula
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
&&
!
ARGV
.
include?
(
'--HEAD'
)
\
&&
satisfied_requirements?
(
formula_object
,
:devel
)
test
"brew"
,
"fetch"
,
"--retry"
,
"--devel"
,
*
formula_fetch_options
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
end
end
test
"brew"
,
"uninstall"
,
"--force"
,
*
unchanged_dependencies
unless
unchanged_dependencies
.
empty?
end
def
homebrew
@category
=
__method__
test
"brew"
,
"tests"
test
"brew"
,
"readall"
end
def
cleanup_before
@category
=
__method__
return
unless
ARGV
.
include?
'--cleanup'
git
"stash"
git
"am"
,
"--abort"
git
"rebase"
,
"--abort"
git
"reset"
,
"--hard"
git
"checkout"
,
"-f"
,
"master"
git
"clean"
,
"--force"
,
"-dx"
end
def
cleanup_after
@category
=
__method__
checkout_args
=
[]
if
ARGV
.
include?
'--cleanup'
test
"git"
,
"clean"
,
"--force"
,
"-dx"
checkout_args
<<
"-f"
end
checkout_args
<<
@start_branch
if
ARGV
.
include?
'--cleanup'
or
@url
or
@hash
test
"git"
,
"checkout"
,
*
checkout_args
end
if
ARGV
.
include?
'--cleanup'
test
"git"
,
"reset"
,
"--hard"
git
"stash"
,
"pop"
test
"brew"
,
"cleanup"
end
test
"brew"
,
"untap"
,
@tap
if
@tap
&&
@repository_requires_tapping
FileUtils
.
rm_rf
@brewbot_root
unless
ARGV
.
include?
"--keep-logs"
end
def
test
(
*
args
)
options
=
Hash
===
args
.
last
?
args
.
pop
:
{}
options
[
:repository
]
=
@repository
step
=
Step
.
new
self
,
args
,
options
step
.
run
steps
<<
step
step
end
def
check_results
status
=
:passed
steps
.
each
do
|
step
|
case
step
.
status
when
:passed
then
next
when
:running
then
raise
when
:failed
then
status
=
:failed
end
end
status
==
:passed
end
def
formulae
changed_formulae_dependents
=
{}
dependencies
=
[]
non_dependencies
=
[]
@formulae
.
each
do
|
formula
|
formula_dependencies
=
`brew deps
#{
formula
}
`
.
split
(
"
\n
"
)
unchanged_dependencies
=
formula_dependencies
-
@formulae
changed_dependences
=
formula_dependencies
-
unchanged_dependencies
changed_dependences
.
each
do
|
changed_formula
|
changed_formulae_dependents
[
changed_formula
]
||=
0
changed_formulae_dependents
[
changed_formula
]
+=
1
end
end
changed_formulae
=
changed_formulae_dependents
.
sort
do
|
a1
,
a2
|
a2
[
1
].
to_i
<=>
a1
[
1
].
to_i
end
changed_formulae
.
map!
(
&
:first
)
unchanged_formulae
=
@formulae
-
changed_formulae
changed_formulae
+
unchanged_formulae
end
def
run
cleanup_before
download
setup
homebrew
formulae
.
each
do
|
f
|
formula
(
f
)
end
cleanup_after
check_results
end
end
tap
=
ARGV
.
value
(
'tap'
)
if
Pathname
.
pwd
==
HOMEBREW_PREFIX
and
ARGV
.
include?
"--cleanup"
odie
'cannot use --cleanup from HOMEBREW_PREFIX as it will delete all output.'
end
if
ARGV
.
include?
"--email"
File
.
open
EMAIL_SUBJECT_FILE
,
'w'
do
|
file
|
# The file should be written at the end but in case we don't get to that
# point ensure that we have something valid.
file
.
write
"
#{
MacOS
.
version
}
: internal error."
end
end
ENV
[
'HOMEBREW_DEVELOPER'
]
=
'1'
ENV
[
'HOMEBREW_NO_EMOJI'
]
=
'1'
if
ARGV
.
include?
'--ci-master'
or
ARGV
.
include?
'--ci-pr'
\
or
ARGV
.
include?
'--ci-testing'
ARGV
<<
'--cleanup'
<<
'--junit'
<<
'--local'
end
if
ARGV
.
include?
'--ci-master'
ARGV
<<
'--no-bottle'
<<
'--email'
end
if
ARGV
.
include?
'--local'
ENV
[
'HOMEBREW_LOGS'
]
=
"
#{
Dir
.
pwd
}
/logs"
end
if
ARGV
.
include?
'--ci-pr-upload'
or
ARGV
.
include?
'--ci-testing-upload'
jenkins
=
ENV
[
'JENKINS_HOME'
]
job
=
ENV
[
'UPSTREAM_JOB_NAME'
]
id
=
ENV
[
'UPSTREAM_BUILD_ID'
]
raise
"Missing Jenkins variables!"
unless
jenkins
and
job
and
id
ARGV
<<
'--verbose'
cp_args
=
Dir
[
"
#{
jenkins
}
/jobs/
#{
job
}
/configurations/axis-version/*/builds/
#{
id
}
/archive/*.bottle*.*"
]
+
[
"."
]
exit
unless
system
"cp"
,
*
cp_args
ENV
[
"GIT_COMMITTER_NAME"
]
=
"BrewTestBot"
ENV
[
"GIT_COMMITTER_EMAIL"
]
=
"brew-test-bot@googlegroups.com"
ENV
[
"GIT_WORK_TREE"
]
=
homebrew_git_repo
tap
ENV
[
"GIT_DIR"
]
=
"
#{
ENV
[
"GIT_WORK_TREE"
]
}
/.git"
pr
=
ENV
[
'UPSTREAM_PULL_REQUEST'
]
number
=
ENV
[
'UPSTREAM_BUILD_NUMBER'
]
system
"git am --abort 2>/dev/null"
system
"git rebase --abort 2>/dev/null"
safe_system
"git"
,
"checkout"
,
"-f"
,
"master"
safe_system
"git"
,
"reset"
,
"--hard"
,
"origin/master"
safe_system
"brew"
,
"update"
if
ARGV
.
include?
'--ci-pr-upload'
safe_system
"brew"
,
"pull"
,
"--clean"
,
pr
end
ENV
[
"GIT_AUTHOR_NAME"
]
=
ENV
[
"GIT_COMMITTER_NAME"
]
ENV
[
"GIT_AUTHOR_EMAIL"
]
=
ENV
[
"GIT_COMMITTER_EMAIL"
]
safe_system
"brew"
,
"bottle"
,
"--merge"
,
"--write"
,
*
Dir
[
"*.bottle.rb"
]
remote
=
"git@github.com:BrewTestBot/homebrew.git"
tag
=
pr
?
"pr-
#{
pr
}
"
:
"testing-
#{
number
}
"
safe_system
"git"
,
"push"
,
"--force"
,
remote
,
"master:master"
,
":refs/tags/
#{
tag
}
"
path
=
"/home/frs/project/m/ma/machomebrew/Bottles/"
url
=
"BrewTestBot,machomebrew@frs.sourceforge.net:
#{
path
}
"
rsync_args
=
%w[--partial --progress --human-readable --compress]
rsync_args
+=
Dir
[
"*.bottle*.tar.gz"
]
+
[
url
]
safe_system
"rsync"
,
*
rsync_args
safe_system
"git"
,
"tag"
,
"--force"
,
tag
safe_system
"git"
,
"push"
,
"--force"
,
remote
,
"refs/tags/
#{
tag
}
"
exit
end
tests
=
[]
any_errors
=
false
if
ARGV
.
named
.
empty?
# With no arguments just build the most recent commit.
test
=
Test
.
new
(
'HEAD'
,
tap
)
any_errors
=
test
.
run
tests
<<
test
else
ARGV
.
named
.
each
do
|
argument
|
test
=
Test
.
new
(
argument
,
tap
)
any_errors
=
test
.
run
or
any_errors
tests
<<
test
end
end
if
ARGV
.
include?
"--junit"
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?
# Remove invalid XML CData characters from step output.
output
=
step
.
output
if
output
.
respond_to?
(
:force_encoding
)
&&
!
output
.
valid_encoding?
output
.
force_encoding
(
Encoding
::
UTF_8
)
end
output
=
REXML
::
CData
.
new
output
.
delete
(
"
\000\a\b\e\f
"
)
if
step
.
passed?
system_out
=
testcase
.
add_element
'system-out'
system_out
.
text
=
output
else
failure
.
attributes
[
"message"
]
=
"
#{
step
.
status
}
:
#{
step
.
command
.
join
(
" "
)
}
"
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
)
end
end
if
ARGV
.
include?
"--email"
failed_steps
=
[]
tests
.
each
do
|
test
|
test
.
steps
.
each
do
|
step
|
next
unless
step
.
failed?
failed_steps
<<
step
.
command_short
end
end
if
failed_steps
.
empty?
email_subject
=
''
else
email_subject
=
"
#{
MacOS
.
version
}
:
#{
failed_steps
.
join
', '
}
."
end
File
.
open
EMAIL_SUBJECT_FILE
,
'w'
do
|
file
|
file
.
write
email_subject
end
end
safe_system
"rm -rf
#{
HOMEBREW_CACHE
}
/*"
if
ARGV
.
include?
"--clean-cache"
exit
any_errors
?
0
:
1
This diff is collapsed.
Click to expand it.
Library/Homebrew/cmd/test-bot.rb
0 → 100755
+
666
−
0
View file @
b7c9025d
# Comprehensively test a formula or pull request.
#
# Usage: brew test-bot [options...] <pull-request|formula>
#
# Options:
# --keep-logs: Write and keep log files under ./brewbot/
# --cleanup: Clean the Homebrew directory. Very dangerous. Use with care.
# --clean-cache: Remove all cached downloads. Use with care.
# --skip-setup: Don't check the local system is setup correctly.
# --junit: Generate a JUnit XML test results file.
# --email: Generate an email subject file.
# --no-bottle: Run brew install without --build-bottle
# --HEAD: Run brew install with --HEAD
# --local: Ask Homebrew to write verbose logs under ./logs/
# --tap=<tap>: Use the git repository of the given tap
# --dry-run: Just print commands, don't run them.
#
# --ci-master: Shortcut for Homebrew master branch CI options.
# --ci-pr: Shortcut for Homebrew pull request CI options.
# --ci-testing: Shortcut for Homebrew testing CI options.
# --ci-pr-upload: Homebrew CI pull request bottle upload.
# --ci-testing-upload: Homebrew CI testing bottle upload.
require
'formula'
require
'utils'
require
'date'
require
'rexml/document'
require
'rexml/xmldecl'
require
'rexml/cdata'
module
Homebrew
EMAIL_SUBJECT_FILE
=
"brew-test-bot.
#{
MacOS
.
cat
}
.email.txt"
def
homebrew_git_repo
tap
=
nil
if
tap
HOMEBREW_LIBRARY
/
"Taps/
#{
tap
}
"
else
HOMEBREW_REPOSITORY
end
end
class
Step
attr_reader
:command
,
:name
,
:status
,
:output
,
:time
def
initialize
test
,
command
,
options
=
{}
@test
=
test
@category
=
test
.
category
@command
=
command
@puts_output_on_success
=
options
[
:puts_output_on_success
]
@name
=
command
[
1
].
delete
(
"-"
)
@status
=
:running
@repository
=
options
[
:repository
]
||
HOMEBREW_REPOSITORY
@time
=
0
end
def
log_file_path
file
=
"
#{
@category
}
.
#{
@name
}
.txt"
root
=
@test
.
log_root
root
?
root
+
file
:
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
def
command_short
(
@command
-
%w[brew --force --retry --verbose --build-bottle --rb]
).
join
(
" "
)
end
def
passed?
@status
==
:passed
end
def
failed?
@status
==
:failed
end
def
puts_command
cmd
=
@command
.
join
(
" "
)
print
"
#{
Tty
.
blue
}
==>
#{
Tty
.
white
}
#{
cmd
}#{
Tty
.
reset
}
"
tabs
=
(
80
-
"PASSED"
.
length
+
1
-
cmd
.
length
)
/
8
tabs
.
times
{
print
"
\t
"
}
$stdout
.
flush
end
def
puts_result
puts
"
#{
Tty
.
send
status_colour
}#{
status_upcase
}#{
Tty
.
reset
}
"
end
def
has_output?
@output
&&
!
@output
.
empty?
end
def
run
puts_command
if
ARGV
.
include?
"--dry-run"
puts
@status
=
:passed
return
end
start_time
=
Time
.
now
log
=
log_file_path
pid
=
fork
do
File
.
open
(
log
,
"wb"
)
do
|
f
|
STDOUT
.
reopen
(
f
)
STDERR
.
reopen
(
f
)
end
Dir
.
chdir
(
@repository
)
if
@command
.
first
==
"git"
exec
(
*
@command
)
end
Process
.
wait
(
pid
)
@time
=
Time
.
now
-
start_time
@status
=
$?
.
success?
?
:passed
:
:failed
puts_result
if
File
.
exist?
(
log
)
@output
=
File
.
read
(
log
)
if
has_output?
and
(
failed?
or
@puts_output_on_success
)
puts
@output
end
FileUtils
.
rm
(
log
)
unless
ARGV
.
include?
"--keep-logs"
end
end
end
class
Test
attr_reader
:log_root
,
:category
,
:name
,
:steps
def
initialize
argument
,
tap
=
nil
@hash
=
nil
@url
=
nil
@formulae
=
[]
@steps
=
[]
@tap
=
tap
@repository
=
Homebrew
.
homebrew_git_repo
@tap
@repository_requires_tapping
=
!
@repository
.
directory?
url_match
=
argument
.
match
HOMEBREW_PULL_OR_COMMIT_URL_REGEX
# Tap repository if required, this is done before everything else
# because Formula parsing and/or git commit hash lookup depends on it.
test
"brew"
,
"tap"
,
@tap
if
@tap
&&
@repository_requires_tapping
begin
formula
=
Formulary
.
factory
(
argument
)
rescue
FormulaUnavailableError
end
git
"rev-parse"
,
"--verify"
,
"-q"
,
argument
if
$?
.
success?
@hash
=
argument
elsif
url_match
@url
=
url_match
[
0
]
elsif
formula
@formulae
=
[
argument
]
else
odie
"
#{
argument
}
is not a pull request URL, commit URL or formula name."
end
@category
=
__method__
@brewbot_root
=
Pathname
.
pwd
+
"brewbot"
FileUtils
.
mkdir_p
@brewbot_root
end
def
no_args?
@hash
==
'HEAD'
end
def
git
(
*
args
)
rd
,
wr
=
IO
.
pipe
pid
=
fork
do
rd
.
close
STDERR
.
reopen
(
"/dev/null"
)
STDOUT
.
reopen
(
wr
)
wr
.
close
Dir
.
chdir
@repository
exec
(
"git"
,
*
args
)
end
wr
.
close
Process
.
wait
(
pid
)
rd
.
read
ensure
rd
.
close
end
def
download
def
shorten_revision
revision
git
(
"rev-parse"
,
"--short"
,
revision
).
strip
end
def
current_sha1
shorten_revision
'HEAD'
end
def
current_branch
git
(
"symbolic-ref"
,
"HEAD"
).
gsub
(
"refs/heads/"
,
""
).
strip
end
def
single_commit?
start_revision
,
end_revision
git
(
"rev-list"
,
"--count"
,
"
#{
start_revision
}
..
#{
end_revision
}
"
).
to_i
==
1
end
@category
=
__method__
@start_branch
=
current_branch
# Use Jenkins environment variables if present.
if
no_args?
and
ENV
[
'GIT_PREVIOUS_COMMIT'
]
and
ENV
[
'GIT_COMMIT'
]
\
and
not
ENV
[
'ghprbPullId'
]
diff_start_sha1
=
shorten_revision
ENV
[
'GIT_PREVIOUS_COMMIT'
]
diff_end_sha1
=
shorten_revision
ENV
[
'GIT_COMMIT'
]
test
"brew"
,
"update"
if
current_branch
==
"master"
elsif
@hash
or
@url
diff_start_sha1
=
current_sha1
test
"brew"
,
"update"
if
current_branch
==
"master"
diff_end_sha1
=
current_sha1
end
# 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
}
"
@hash
=
nil
else
puts
"Invalid 'ghprbPullId' environment variable value!"
end
end
if
no_args?
if
diff_start_sha1
==
diff_end_sha1
or
\
single_commit?
(
diff_start_sha1
,
diff_end_sha1
)
@name
=
diff_end_sha1
else
@name
=
"
#{
diff_start_sha1
}
-
#{
diff_end_sha1
}
"
end
elsif
@hash
test
"git"
,
"checkout"
,
@hash
diff_start_sha1
=
"
#{
@hash
}
^"
diff_end_sha1
=
@hash
@name
=
@hash
elsif
@url
test
"git"
,
"checkout"
,
current_sha1
test
"brew"
,
"pull"
,
"--clean"
,
@url
diff_end_sha1
=
current_sha1
@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
else
diff_start_sha1
=
diff_end_sha1
=
current_sha1
@name
=
"
#{
@formulae
.
first
}
-
#{
diff_end_sha1
}
"
end
@log_root
=
@brewbot_root
+
@name
FileUtils
.
mkdir_p
@log_root
return
unless
diff_start_sha1
!=
diff_end_sha1
return
if
@url
and
not
steps
.
last
.
passed?
if
@tap
formula_path
=
%w[Formula HomebrewFormula]
.
find
{
|
dir
|
(
@repository
/
dir
).
directory?
}
||
""
else
formula_path
=
"Library/Formula"
end
git
(
"diff-tree"
,
"-r"
,
"--name-only"
,
"--diff-filter=AM"
,
diff_start_sha1
,
diff_end_sha1
,
"--"
,
formula_path
).
each_line
do
|
line
|
@formulae
<<
File
.
basename
(
line
.
chomp
,
".rb"
)
end
end
def
skip
formula
puts
"
#{
Tty
.
blue
}
==>
#{
Tty
.
white
}
SKIPPING:
#{
formula
}#{
Tty
.
reset
}
"
end
def
satisfied_requirements?
formula_object
,
spec
requirements
=
formula_object
.
send
(
spec
).
requirements
unsatisfied_requirements
=
requirements
.
reject
do
|
requirement
|
requirement
.
satisfied?
||
requirement
.
default_formula?
end
if
unsatisfied_requirements
.
empty?
true
else
formula
=
formula_object
.
name
formula
+=
" (
#{
spec
}
)"
unless
spec
==
:stable
skip
formula
unsatisfied_requirements
.
each
{
|
r
|
puts
r
.
message
}
false
end
end
def
setup
@category
=
__method__
return
if
ARGV
.
include?
"--skip-setup"
test
"brew"
,
"doctor"
test
"brew"
,
"--env"
test
"brew"
,
"config"
end
def
formula
formula
@category
=
__method__
.
to_s
+
".
#{
formula
}
"
test
"brew"
,
"uses"
,
formula
dependencies
=
`brew deps
#{
formula
}
`
.
split
(
"
\n
"
)
dependencies
-=
`brew list`
.
split
(
"
\n
"
)
unchanged_dependencies
=
dependencies
-
@formulae
changed_dependences
=
dependencies
-
unchanged_dependencies
formula_object
=
Formulary
.
factory
(
formula
)
return
unless
satisfied_requirements?
(
formula_object
,
:stable
)
installed_gcc
=
false
deps
=
formula_object
.
stable
.
deps
.
to_a
reqs
=
formula_object
.
stable
.
requirements
.
to_a
if
formula_object
.
devel
&&
!
ARGV
.
include?
(
'--HEAD'
)
deps
|=
formula_object
.
devel
.
deps
.
to_a
reqs
|=
formula_object
.
devel
.
requirements
.
to_a
end
begin
deps
.
each
{
|
d
|
CompilerSelector
.
select_for
(
d
.
to_formula
)
}
CompilerSelector
.
select_for
(
formula_object
)
rescue
CompilerSelectionError
=>
e
unless
installed_gcc
test
"brew"
,
"install"
,
"gcc"
installed_gcc
=
true
OS
::
Mac
.
clear_version_cache
retry
end
skip
formula
puts
e
.
message
return
end
if
(
deps
|
reqs
).
any?
{
|
d
|
d
.
name
==
"mercurial"
&&
d
.
build?
}
test
"brew"
,
"install"
,
"mercurial"
end
test
"brew"
,
"fetch"
,
"--retry"
,
*
unchanged_dependencies
unless
unchanged_dependencies
.
empty?
test
"brew"
,
"fetch"
,
"--retry"
,
"--build-bottle"
,
*
changed_dependences
unless
changed_dependences
.
empty?
formula_fetch_options
=
[]
formula_fetch_options
<<
"--build-bottle"
unless
ARGV
.
include?
"--no-bottle"
formula_fetch_options
<<
"--force"
if
ARGV
.
include?
"--cleanup"
formula_fetch_options
<<
formula
test
"brew"
,
"fetch"
,
"--retry"
,
*
formula_fetch_options
test
"brew"
,
"uninstall"
,
"--force"
,
formula
if
formula_object
.
installed?
install_args
=
%w[--verbose]
install_args
<<
"--build-bottle"
unless
ARGV
.
include?
"--no-bottle"
install_args
<<
"--HEAD"
if
ARGV
.
include?
"--HEAD"
install_args
<<
formula
# Don't care about e.g. bottle failures for dependencies.
ENV
[
"HOMEBREW_DEVELOPER"
]
=
nil
test
"brew"
,
"install"
,
"--only-dependencies"
,
*
install_args
unless
dependencies
.
empty?
ENV
[
"HOMEBREW_DEVELOPER"
]
=
"1"
test
"brew"
,
"install"
,
*
install_args
install_passed
=
steps
.
last
.
passed?
test
"brew"
,
"audit"
,
formula
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
&&
!
ARGV
.
include?
(
'--HEAD'
)
\
&&
satisfied_requirements?
(
formula_object
,
:devel
)
test
"brew"
,
"fetch"
,
"--retry"
,
"--devel"
,
*
formula_fetch_options
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
end
end
test
"brew"
,
"uninstall"
,
"--force"
,
*
unchanged_dependencies
unless
unchanged_dependencies
.
empty?
end
def
homebrew
@category
=
__method__
test
"brew"
,
"tests"
test
"brew"
,
"readall"
end
def
cleanup_before
@category
=
__method__
return
unless
ARGV
.
include?
'--cleanup'
git
"stash"
git
"am"
,
"--abort"
git
"rebase"
,
"--abort"
git
"reset"
,
"--hard"
git
"checkout"
,
"-f"
,
"master"
git
"clean"
,
"--force"
,
"-dx"
end
def
cleanup_after
@category
=
__method__
checkout_args
=
[]
if
ARGV
.
include?
'--cleanup'
test
"git"
,
"clean"
,
"--force"
,
"-dx"
checkout_args
<<
"-f"
end
checkout_args
<<
@start_branch
if
ARGV
.
include?
'--cleanup'
or
@url
or
@hash
test
"git"
,
"checkout"
,
*
checkout_args
end
if
ARGV
.
include?
'--cleanup'
test
"git"
,
"reset"
,
"--hard"
git
"stash"
,
"pop"
test
"brew"
,
"cleanup"
end
test
"brew"
,
"untap"
,
@tap
if
@tap
&&
@repository_requires_tapping
FileUtils
.
rm_rf
@brewbot_root
unless
ARGV
.
include?
"--keep-logs"
end
def
test
(
*
args
)
options
=
Hash
===
args
.
last
?
args
.
pop
:
{}
options
[
:repository
]
=
@repository
step
=
Step
.
new
self
,
args
,
options
step
.
run
steps
<<
step
step
end
def
check_results
status
=
:passed
steps
.
each
do
|
step
|
case
step
.
status
when
:passed
then
next
when
:running
then
raise
when
:failed
then
status
=
:failed
end
end
status
==
:passed
end
def
formulae
changed_formulae_dependents
=
{}
dependencies
=
[]
non_dependencies
=
[]
@formulae
.
each
do
|
formula
|
formula_dependencies
=
`brew deps
#{
formula
}
`
.
split
(
"
\n
"
)
unchanged_dependencies
=
formula_dependencies
-
@formulae
changed_dependences
=
formula_dependencies
-
unchanged_dependencies
changed_dependences
.
each
do
|
changed_formula
|
changed_formulae_dependents
[
changed_formula
]
||=
0
changed_formulae_dependents
[
changed_formula
]
+=
1
end
end
changed_formulae
=
changed_formulae_dependents
.
sort
do
|
a1
,
a2
|
a2
[
1
].
to_i
<=>
a1
[
1
].
to_i
end
changed_formulae
.
map!
(
&
:first
)
unchanged_formulae
=
@formulae
-
changed_formulae
changed_formulae
+
unchanged_formulae
end
def
run
cleanup_before
download
setup
homebrew
formulae
.
each
do
|
f
|
formula
(
f
)
end
cleanup_after
check_results
end
end
def
test_bot
tap
=
ARGV
.
value
(
'tap'
)
if
Pathname
.
pwd
==
HOMEBREW_PREFIX
and
ARGV
.
include?
"--cleanup"
odie
'cannot use --cleanup from HOMEBREW_PREFIX as it will delete all output.'
end
if
ARGV
.
include?
"--email"
File
.
open
EMAIL_SUBJECT_FILE
,
'w'
do
|
file
|
# The file should be written at the end but in case we don't get to that
# point ensure that we have something valid.
file
.
write
"
#{
MacOS
.
version
}
: internal error."
end
end
ENV
[
'HOMEBREW_DEVELOPER'
]
=
'1'
ENV
[
'HOMEBREW_NO_EMOJI'
]
=
'1'
if
ARGV
.
include?
'--ci-master'
or
ARGV
.
include?
'--ci-pr'
\
or
ARGV
.
include?
'--ci-testing'
ARGV
<<
'--cleanup'
<<
'--junit'
<<
'--local'
end
if
ARGV
.
include?
'--ci-master'
ARGV
<<
'--no-bottle'
<<
'--email'
end
if
ARGV
.
include?
'--local'
ENV
[
'HOMEBREW_LOGS'
]
=
"
#{
Dir
.
pwd
}
/logs"
end
if
ARGV
.
include?
'--ci-pr-upload'
or
ARGV
.
include?
'--ci-testing-upload'
jenkins
=
ENV
[
'JENKINS_HOME'
]
job
=
ENV
[
'UPSTREAM_JOB_NAME'
]
id
=
ENV
[
'UPSTREAM_BUILD_ID'
]
raise
"Missing Jenkins variables!"
unless
jenkins
and
job
and
id
ARGV
<<
'--verbose'
cp_args
=
Dir
[
"
#{
jenkins
}
/jobs/
#{
job
}
/configurations/axis-version/*/builds/
#{
id
}
/archive/*.bottle*.*"
]
+
[
"."
]
return
unless
system
"cp"
,
*
cp_args
ENV
[
"GIT_COMMITTER_NAME"
]
=
"BrewTestBot"
ENV
[
"GIT_COMMITTER_EMAIL"
]
=
"brew-test-bot@googlegroups.com"
ENV
[
"GIT_WORK_TREE"
]
=
Homebrew
.
homebrew_git_repo
tap
ENV
[
"GIT_DIR"
]
=
"
#{
ENV
[
"GIT_WORK_TREE"
]
}
/.git"
pr
=
ENV
[
'UPSTREAM_PULL_REQUEST'
]
number
=
ENV
[
'UPSTREAM_BUILD_NUMBER'
]
system
"git am --abort 2>/dev/null"
system
"git rebase --abort 2>/dev/null"
safe_system
"git"
,
"checkout"
,
"-f"
,
"master"
safe_system
"git"
,
"reset"
,
"--hard"
,
"origin/master"
safe_system
"brew"
,
"update"
if
ARGV
.
include?
'--ci-pr-upload'
safe_system
"brew"
,
"pull"
,
"--clean"
,
pr
end
ENV
[
"GIT_AUTHOR_NAME"
]
=
ENV
[
"GIT_COMMITTER_NAME"
]
ENV
[
"GIT_AUTHOR_EMAIL"
]
=
ENV
[
"GIT_COMMITTER_EMAIL"
]
safe_system
"brew"
,
"bottle"
,
"--merge"
,
"--write"
,
*
Dir
[
"*.bottle.rb"
]
remote
=
"git@github.com:BrewTestBot/homebrew.git"
tag
=
pr
?
"pr-
#{
pr
}
"
:
"testing-
#{
number
}
"
safe_system
"git"
,
"push"
,
"--force"
,
remote
,
"master:master"
,
":refs/tags/
#{
tag
}
"
path
=
"/home/frs/project/m/ma/machomebrew/Bottles/"
url
=
"BrewTestBot,machomebrew@frs.sourceforge.net:
#{
path
}
"
rsync_args
=
%w[--partial --progress --human-readable --compress]
rsync_args
+=
Dir
[
"*.bottle*.tar.gz"
]
+
[
url
]
safe_system
"rsync"
,
*
rsync_args
safe_system
"git"
,
"tag"
,
"--force"
,
tag
safe_system
"git"
,
"push"
,
"--force"
,
remote
,
"refs/tags/
#{
tag
}
"
return
end
tests
=
[]
any_errors
=
false
if
ARGV
.
named
.
empty?
# With no arguments just build the most recent commit.
test
=
Test
.
new
(
'HEAD'
,
tap
)
any_errors
=
test
.
run
tests
<<
test
else
ARGV
.
named
.
each
do
|
argument
|
test
=
Test
.
new
(
argument
,
tap
)
any_errors
=
test
.
run
or
any_errors
tests
<<
test
end
end
if
ARGV
.
include?
"--junit"
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?
# Remove invalid XML CData characters from step output.
output
=
step
.
output
if
output
.
respond_to?
(
:force_encoding
)
&&
!
output
.
valid_encoding?
output
.
force_encoding
(
Encoding
::
UTF_8
)
end
output
=
REXML
::
CData
.
new
output
.
delete
(
"
\000\a\b\e\f
"
)
if
step
.
passed?
system_out
=
testcase
.
add_element
'system-out'
system_out
.
text
=
output
else
failure
.
attributes
[
"message"
]
=
"
#{
step
.
status
}
:
#{
step
.
command
.
join
(
" "
)
}
"
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
)
end
end
if
ARGV
.
include?
"--email"
failed_steps
=
[]
tests
.
each
do
|
test
|
test
.
steps
.
each
do
|
step
|
next
unless
step
.
failed?
failed_steps
<<
step
.
command_short
end
end
if
failed_steps
.
empty?
email_subject
=
''
else
email_subject
=
"
#{
MacOS
.
version
}
:
#{
failed_steps
.
join
', '
}
."
end
File
.
open
EMAIL_SUBJECT_FILE
,
'w'
do
|
file
|
file
.
write
email_subject
end
end
safe_system
"rm -rf
#{
HOMEBREW_CACHE
}
/*"
if
ARGV
.
include?
"--clean-cache"
Homebrew
.
failed
=
any_errors
end
end
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment