Index: tools/bisect-perf-regression.py |
diff --git a/tools/bisect-perf-regression.py b/tools/bisect-perf-regression.py |
index 0b5866926d924aa06ec63ef3ccfd96f6a9f4f025..4b1685d1168be9dcb73e9eb34dec2eb6eb3a6a3e 100755 |
--- a/tools/bisect-perf-regression.py |
+++ b/tools/bisect-perf-regression.py |
@@ -52,6 +52,8 @@ import time |
import zipfile |
import bisect_utils |
+import post_perf_builder_job |
+ |
try: |
from telemetry.page import cloud_storage |
@@ -1313,23 +1315,16 @@ class BisectPerformanceMetrics(object): |
return destination_dir |
return None |
- def DownloadCurrentBuild(self, sha_revision, build_type='Release'): |
+ def DownloadCurrentBuild(self, revision, build_type='Release'): |
"""Download the build archive for the given revision. |
Args: |
- sha_revision: The git SHA1 for the revision. |
+ revision: The SVN revision to build. |
build_type: Target build type ('Release', 'Debug', 'Release_x64' etc.) |
Returns: |
True if download succeeds, otherwise False. |
""" |
- # Get SVN revision for the given SHA, since builds are archived using SVN |
- # revision. |
- revision = self.source_control.SVNFindRev(sha_revision) |
- if not revision: |
- raise RuntimeError( |
- 'Failed to determine SVN revision for %s' % sha_revision) |
- |
abs_build_dir = os.path.abspath( |
self.builder.GetBuildOutputDirectory(self.opts, self.src_cwd)) |
target_build_output_dir = os.path.join(abs_build_dir, build_type) |
@@ -1338,33 +1333,86 @@ class BisectPerformanceMetrics(object): |
# File path of the downloaded archive file. |
archive_file_dest = os.path.join(abs_build_dir, |
GetZipFileName(revision, build_arch)) |
- if FetchFromCloudStorage(self.opts.gs_bucket, |
- GetRemoteBuildPath(revision, build_arch), |
- abs_build_dir): |
- # Generic name for the archive, created when archive file is extracted. |
- output_dir = os.path.join(abs_build_dir, |
- GetZipFileName(target_arch=build_arch)) |
- # Unzip build archive directory. |
- try: |
+ remote_build = GetRemoteBuildPath(revision, build_arch) |
+ fetch_build_func = lambda: FetchFromCloudStorage(self.opts.gs_bucket, |
+ remote_build, |
+ abs_build_dir) |
+ if not fetch_build_func(): |
+ if not self.PostBuildRequestAndWait(revision, condition=fetch_build_func): |
+ raise RuntimeError('Somewthing went wrong while processing build' |
+ 'request for: %s' % revision) |
+ |
+ # Generic name for the archive, created when archive file is extracted. |
+ output_dir = os.path.join(abs_build_dir, |
+ GetZipFileName(target_arch=build_arch)) |
+ # Unzip build archive directory. |
+ try: |
+ RmTreeAndMkDir(output_dir, skip_makedir=True) |
+ ExtractZip(archive_file_dest, abs_build_dir) |
+ if os.path.exists(output_dir): |
+ self.BackupOrRestoreOutputdirectory(restore=False) |
+ print 'Moving build from %s to %s' % ( |
+ output_dir, target_build_output_dir) |
+ shutil.move(output_dir, target_build_output_dir) |
+ return True |
+ raise IOError('Missing extracted folder %s ' % output_dir) |
+ except e: |
+ print 'Somewthing went wrong while extracting archive file: %s' % e |
+ self.BackupOrRestoreOutputdirectory(restore=True) |
+ # Cleanup any leftovers from unzipping. |
+ if os.path.exists(output_dir): |
RmTreeAndMkDir(output_dir, skip_makedir=True) |
- ExtractZip(archive_file_dest, abs_build_dir) |
- if os.path.exists(output_dir): |
- self.BackupOrRestoreOutputdirectory(restore=False) |
- print 'Moving build from %s to %s' % ( |
- output_dir, target_build_output_dir) |
- shutil.move(output_dir, target_build_output_dir) |
- return True |
- raise IOError('Missing extracted folder %s ' % output_dir) |
- except e: |
- print 'Somewthing went wrong while extracting archive file: %s' % e |
- self.BackupOrRestoreOutputdirectory(restore=True) |
- # Cleanup any leftovers from unzipping. |
- if os.path.exists(output_dir): |
- RmTreeAndMkDir(output_dir, skip_makedir=True) |
- finally: |
- # Delete downloaded archive |
- if os.path.exists(archive_file_dest): |
- os.remove(archive_file_dest) |
+ finally: |
+ # Delete downloaded archive |
+ if os.path.exists(archive_file_dest): |
+ os.remove(archive_file_dest) |
+ return False |
+ |
+ |
qyearsley
2014/03/06 23:40:45
Style: Both DownloadCurrentBuild and PostBuildRequ
prasadv
2014/03/07 01:07:44
Done.
|
+ def PostBuildRequestAndWait(self, revision, condition, patch=None): |
+ """POSTs the build request job to the tryserver instance.""" |
+ |
+ def GetBuilderNameAndBuildTime(target_arch='ia32'): |
+ """Gets builder name and buildtime in seconds based on platform.""" |
+ if IsWindows(): |
+ if Is64BitWindows() and target_arch == 'x64': |
+ return ('Win x64 Bisect Builder', 3600) # 60 mins |
qyearsley
2014/03/06 23:40:45
Style nit: The style guide suggests spacing inline
prasadv
2014/03/07 01:07:44
Done.
|
+ return ('Win Bisect Builder', 3600) |
+ if IsLinux(): |
+ return ('Linux Bisect Builder', 1800) # 30 mins |
+ if IsMac(): |
+ return ('Mac Bisect Builder', 2700) # 45 mins |
+ raise NotImplementedError('Unsupported Platform "%s".' % sys.platform) |
+ if not condition: |
+ return False |
+ |
+ bot_name, build_timeout = GetBuilderNameAndBuildTime(self.opts.target_arch) |
+ |
+ # Creates a try job description. |
+ job_args = {'host': self.opts.host, |
+ 'port': self.opts.port, |
+ 'revision': revision, |
+ 'bot': bot_name, |
+ 'name': 'Bisect Job-%s' % revision |
+ } |
+ # Update patch information if supplied. |
+ if patch: |
+ job_args['patch'] = patch |
+ #Posts job to build the revision on the server. |
qyearsley
2014/03/06 23:40:45
Style: Should add space after #.
prasadv
2014/03/07 01:07:44
Done.
|
+ if post_perf_builder_job.PostTryJob(job_args): |
+ poll_interval = 60 |
qyearsley
2014/03/06 23:40:45
Style: Unnecessary spaces.
prasadv
2014/03/07 01:07:44
Done.
|
+ start_time = time.time() |
+ while True: |
+ res = condition() |
+ if res: |
+ return res |
+ elapsed_time = time.time() - start_time |
+ if elapsed_time > build_timeout: |
+ raise RuntimeError('Timed out while waiting %ds for %s build.' % |
+ (build_timeout, revision)) |
+ print ('Time elapsed: %ss, still waiting for %s build' % |
+ (elapsed_time, revision)) |
+ time.sleep(poll_interval) |
return False |
def BuildCurrentRevision(self, depot, revision=None): |
@@ -1380,6 +1428,12 @@ class BisectPerformanceMetrics(object): |
# Fetch build archive for the given revision from the cloud storage when |
# the storage bucket is passed. |
if depot == 'chromium' and self.opts.gs_bucket and revision: |
+ # Get SVN revision for the given SHA, since builds are archived using SVN |
+ # revision. |
+ revision = self.source_control.SVNFindRev(revision) |
+ if not revision: |
+ raise RuntimeError( |
+ 'Failed to determine SVN revision for %s' % sha_revision) |
if self.DownloadCurrentBuild(revision): |
os.chdir(cwd) |
return True |
@@ -1388,6 +1442,7 @@ class BisectPerformanceMetrics(object): |
'further. Please try running script without ' |
'--gs_bucket flag to produce local builds.' % revision) |
+ |
build_success = self.builder.Build(depot, self.opts) |
os.chdir(cwd) |
return build_success |
@@ -3022,6 +3077,8 @@ class BisectOptions(object): |
self.debug_ignore_perf_test = None |
self.gs_bucket = None |
self.target_arch = 'ia32' |
+ self.host = None |
+ self.port = None |
def _CreateCommandLineParser(self): |
"""Creates a parser with bisect options. |
@@ -3135,7 +3192,16 @@ class BisectOptions(object): |
dest='target_arch', |
help=('The target build architecture. Choices are "ia32" ' |
'(default), "x64" or "arm".')) |
- |
+ group.add_option('--host', |
+ dest='host', |
+ type='str', |
+ help=('Host address of server to produce build by posting' |
+ ' try job request.')) |
+ group.add_option('--port', |
+ dest='port', |
+ type='int', |
+ help=('HTTP port of the server to produce build by posting' |
+ ' try job request.')) |
parser.add_option_group(group) |
group = optparse.OptionGroup(parser, 'Debug options') |
@@ -3149,8 +3215,6 @@ class BisectOptions(object): |
action="store_true", |
help='DEBUG: Don\'t perform performance tests.') |
parser.add_option_group(group) |
- |
- |
return parser |
def ParseCommandLine(self): |
@@ -3173,8 +3237,13 @@ class BisectOptions(object): |
if opts.gs_bucket: |
if not cloud_storage.List(opts.gs_bucket): |
- raise RuntimeError('Invalid Google Storage URL: [%s]', e) |
- |
+ raise RuntimeError('Invalid Google Storage: gs://%s' % opts.gs_bucket) |
+ if not opts.host: |
+ raise RuntimeError('Must specify try server hostname, when ' |
+ 'gs_bucket is used: --host') |
+ if not opts.port: |
+ raise RuntimeError('Must specify try server port number, when ' |
+ 'gs_bucket is used: --port') |
if opts.target_platform == 'cros': |
# Run sudo up front to make sure credentials are cached for later. |
print 'Sudo is required to build cros:' |
@@ -3279,7 +3348,6 @@ def main(): |
not opts.debug_ignore_sync and |
not opts.working_directory): |
raise RuntimeError("You must switch to master branch to run bisection.") |
- |
bisect_test = BisectPerformanceMetrics(source_control, opts) |
try: |
bisect_results = bisect_test.Run(opts.command, |