| Index: tools/bisect-perf-regression.py
|
| diff --git a/tools/bisect-perf-regression.py b/tools/bisect-perf-regression.py
|
| index 5367345d6af2abcccf3277c8a312c6bdc15ba431..bb5ef19bfc6dfe6da079d177fceaffc6f6a968cc 100755
|
| --- a/tools/bisect-perf-regression.py
|
| +++ b/tools/bisect-perf-regression.py
|
| @@ -482,7 +482,7 @@ def FetchFromCloudStorage(bucket_name, source_path, destination_path):
|
| destination_path: Destination file path.
|
|
|
| Returns:
|
| - True if the fetching succeeds, otherwise False.
|
| + Downloaded file path if exisits, otherwise None.
|
| """
|
| target_file = os.path.join(destination_path, os.path.basename(source_path))
|
| try:
|
| @@ -490,7 +490,7 @@ def FetchFromCloudStorage(bucket_name, source_path, destination_path):
|
| print 'Fetching file from gs//%s/%s ...' % (bucket_name, source_path)
|
| cloud_storage.Get(bucket_name, source_path, destination_path)
|
| if os.path.exists(target_file):
|
| - return True
|
| + return target_file
|
| else:
|
| print ('File gs://%s/%s not found in cloud storage.' % (
|
| bucket_name, source_path))
|
| @@ -498,7 +498,7 @@ def FetchFromCloudStorage(bucket_name, source_path, destination_path):
|
| print 'Something went wrong while fetching file from cloud: %s' % e
|
| if os.path.exists(target_file):
|
| os.remove(target_file)
|
| - return False
|
| + return None
|
|
|
|
|
| # This is copied from Chromium's project build/scripts/common/chromium_utils.py.
|
| @@ -1553,12 +1553,42 @@ class BisectPerformanceMetrics(object):
|
| return destination_dir
|
| return None
|
|
|
| + def GetBuildArchiveForRevision(self, revision, gs_bucket, target_arch,
|
| + patch_sha, out_dir):
|
| + """Checks and downloads build archive for a given revision.
|
| +
|
| + Checks for build archive with Git hash or SVN revision. If either of the
|
| + file exists, then downloads the archive file.
|
| +
|
| + Args:
|
| + revision: A Git hash revision.
|
| + gs_bucket: Cloud storage bucket name
|
| + target_arch: 32 or 64 bit build target
|
| + patch: A DEPS patch (used while bisecting 3rd party repositories).
|
| + out_dir: Build output directory where downloaded file is stored.
|
| +
|
| + Returns:
|
| + Downloaded archive file path if exists, otherwise None.
|
| + """
|
| + # Source archive file path on cloud storage using Git revision.
|
| + source_file = GetRemoteBuildPath(revision, target_arch, patch_sha)
|
| + downloaded_archive = FetchFromCloudStorage(gs_bucket, source_file, out_dir)
|
| + if not downloaded_archive:
|
| + # Get SVN revision for the given SHA.
|
| + svn_revision = self.source_control.SVNFindRev(revision)
|
| + if svn_revision:
|
| + # Source archive file path on cloud storage using SVN revision.
|
| + source_file = GetRemoteBuildPath(svn_revision, target_arch, patch_sha)
|
| + return FetchFromCloudStorage(gs_bucket, source_file, out_dir)
|
| + return downloaded_archive
|
| +
|
| def DownloadCurrentBuild(self, revision, build_type='Release', patch=None):
|
| """Downloads the build archive for the given revision.
|
|
|
| Args:
|
| - revision: The SVN revision to build.
|
| + revision: The Git revision to download or build.
|
| build_type: Target build type ('Release', 'Debug', 'Release_x64' etc.)
|
| + patch: A DEPS patch (used while bisecting 3rd party repositories).
|
|
|
| Returns:
|
| True if download succeeds, otherwise False.
|
| @@ -1572,27 +1602,25 @@ class BisectPerformanceMetrics(object):
|
| # 'DEPS.sha' and add patch_sha evaluated above to it.
|
| patch = '%s\n%s' % (patch, DEPS_SHA_PATCH % {'deps_sha': patch_sha})
|
|
|
| - # Source archive file path on cloud storage.
|
| - source_file = GetRemoteBuildPath(revision, self.opts.target_arch, patch_sha)
|
| -
|
| # Get Build output directory
|
| abs_build_dir = os.path.abspath(
|
| self.builder.GetBuildOutputDirectory(self.opts, self.src_cwd))
|
| - # Downloaded archive file path.
|
| - downloaded_file = os.path.join(
|
| - abs_build_dir,
|
| - GetZipFileName(revision, self.opts.target_arch, patch_sha))
|
| -
|
| - fetch_build_func = lambda: FetchFromCloudStorage(self.opts.gs_bucket,
|
| - source_file,
|
| - abs_build_dir)
|
| -
|
| - if not fetch_build_func():
|
| - if not self.PostBuildRequestAndWait(revision,
|
| - fetch_build=fetch_build_func,
|
| - patch=patch):
|
| - raise RuntimeError('Somewthing went wrong while processing build'
|
| - 'request for: %s' % revision)
|
| +
|
| + fetch_build_func = lambda: self.GetBuildArchiveForRevision(
|
| + revision, self.opts.gs_bucket, self.opts.target_arch,
|
| + patch_sha, abs_build_dir)
|
| +
|
| + # Downloaded archive file path, downloads build archive for given revision.
|
| + downloaded_file = fetch_build_func()
|
| +
|
| + # When build archive doesn't exists, post a build request to tryserver
|
| + # and wait for the build to be produced.
|
| + if not downloaded_file:
|
| + downloaded_file = self.PostBuildRequestAndWait(
|
| + revision, fetch_build=fetch_build_func, patch=patch)
|
| + if not downloaded_file:
|
| + return False
|
| +
|
| # Generic name for the archive, created when archive file is extracted.
|
| output_dir = os.path.join(
|
| abs_build_dir, GetZipFileName(target_arch=self.opts.target_arch))
|
| @@ -1634,8 +1662,7 @@ class BisectPerformanceMetrics(object):
|
| max_timeout: Maximum time to wait for the build.
|
|
|
| Returns:
|
| - True if build exists and download is successful, otherwise throws
|
| - RuntimeError exception when time elapse.
|
| + Downloaded archive file path if exists, otherwise None.
|
| """
|
| # Build number on the tryserver.
|
| build_num = None
|
| @@ -1665,16 +1692,36 @@ class BisectPerformanceMetrics(object):
|
| build_status, status_link = bisect_builder.GetBuildStatus(
|
| build_num, bot_name, builder_host, builder_port)
|
| if build_status == bisect_builder.FAILED:
|
| - return (False, 'Failed to produce build, log: %s' % status_link)
|
| + return (None, 'Failed to produce build, log: %s' % status_link)
|
| elapsed_time = time.time() - start_time
|
| if elapsed_time > max_timeout:
|
| - return (False, 'Timed out: %ss without build' % max_timeout)
|
| + return (None, 'Timed out: %ss without build' % max_timeout)
|
|
|
| print 'Time elapsed: %ss without build.' % elapsed_time
|
| time.sleep(poll_interval)
|
|
|
| def PostBuildRequestAndWait(self, revision, fetch_build, patch=None):
|
| - """POSTs the build request job to the tryserver instance."""
|
| + """POSTs the build request job to the tryserver instance.
|
| +
|
| + A try job build request is posted to tryserver.chromium.perf master,
|
| + and waits for the binaries to be produced and archived on cloud storage.
|
| + Once the build is ready and stored onto cloud, build archive is downloaded
|
| + into the output folder.
|
| +
|
| + Args:
|
| + revision: A Git hash revision.
|
| + fetch_build: Function to check and download build from cloud storage.
|
| + patch: A DEPS patch (used while bisecting 3rd party repositories).
|
| +
|
| + Returns:
|
| + Downloaded archive file path when requested build exists and download is
|
| + successful, otherwise None.
|
| + """
|
| + # Get SVN revision for the given SHA.
|
| + svn_revision = self.source_control.SVNFindRev(revision)
|
| + if not svn_revision:
|
| + raise RuntimeError(
|
| + 'Failed to determine SVN revision for %s' % revision)
|
|
|
| def GetBuilderNameAndBuildTime(target_arch='ia32'):
|
| """Gets builder bot name and buildtime in seconds based on platform."""
|
| @@ -1698,12 +1745,12 @@ class BisectPerformanceMetrics(object):
|
| # Create a unique ID for each build request posted to tryserver builders.
|
| # This ID is added to "Reason" property in build's json.
|
| build_request_id = GetSHA1HexDigest(
|
| - '%s-%s-%s' % (revision, patch, time.time()))
|
| + '%s-%s-%s' % (svn_revision, patch, time.time()))
|
|
|
| # Creates a try job description.
|
| job_args = {'host': builder_host,
|
| 'port': builder_port,
|
| - 'revision': 'src@%s' % revision,
|
| + 'revision': 'src@%s' % svn_revision,
|
| 'bot': bot_name,
|
| 'name': build_request_id
|
| }
|
| @@ -1712,16 +1759,18 @@ class BisectPerformanceMetrics(object):
|
| job_args['patch'] = patch
|
| # Posts job to build the revision on the server.
|
| if bisect_builder.PostTryJob(job_args):
|
| - status, error_msg = self.WaitUntilBuildIsReady(fetch_build,
|
| - bot_name,
|
| - builder_host,
|
| - builder_port,
|
| - build_request_id,
|
| - build_timeout)
|
| - if not status:
|
| - raise RuntimeError('%s [revision: %s]' % (error_msg, revision))
|
| - return True
|
| - return False
|
| + target_file, error_msg = self.WaitUntilBuildIsReady(fetch_build,
|
| + bot_name,
|
| + builder_host,
|
| + builder_port,
|
| + build_request_id,
|
| + build_timeout)
|
| + if not target_file:
|
| + print '%s [revision: %s]' % (error_msg, svn_revision)
|
| + return None
|
| + return target_file
|
| + print 'Failed to post build request for revision: [%s]' % svn_revision
|
| + return None
|
|
|
| def IsDownloadable(self, depot):
|
| """Checks if build is downloadable based on target platform and depot."""
|
| @@ -1921,13 +1970,7 @@ class BisectPerformanceMetrics(object):
|
| if depot != 'chromium':
|
| # Create a DEPS patch with new revision for dependency repository.
|
| (revision, deps_patch) = self.CreateDEPSPatch(depot, revision)
|
| - # Get SVN revision for the given SHA, since builds are archived using SVN
|
| - # revision.
|
| - chromium_revision = self.source_control.SVNFindRev(revision)
|
| - if not chromium_revision:
|
| - raise RuntimeError(
|
| - 'Failed to determine SVN revision for %s' % revision)
|
| - if self.DownloadCurrentBuild(chromium_revision, patch=deps_patch):
|
| + if self.DownloadCurrentBuild(revision, patch=deps_patch):
|
| os.chdir(cwd)
|
| if deps_patch:
|
| # Reverts the changes to DEPS file.
|
| @@ -1935,12 +1978,9 @@ class BisectPerformanceMetrics(object):
|
| revision,
|
| cwd=self.src_cwd)
|
| return True
|
| - raise RuntimeError('Failed to download build archive for revision %s.\n'
|
| - 'Unfortunately, bisection couldn\'t continue any '
|
| - 'further. Please try running script without '
|
| - '--gs_bucket flag to produce local builds.' % revision)
|
| -
|
| + return False
|
|
|
| + # These codes are executed when bisect bots builds binaries locally.
|
| build_success = self.builder.Build(depot, self.opts)
|
| os.chdir(cwd)
|
| return build_success
|
|
|