Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 """ | 3 """ |
| 4 Copyright 2014 Google Inc. | 4 Copyright 2014 Google Inc. |
| 5 | 5 |
| 6 Use of this source code is governed by a BSD-style license that can be | 6 Use of this source code is governed by a BSD-style license that can be |
| 7 found in the LICENSE file. | 7 found in the LICENSE file. |
| 8 | 8 |
| 9 Download actual GM results for a particular builder. | 9 Download actual GM results for a particular builder. |
| 10 """ | 10 """ |
| 11 | 11 |
| 12 # System-level imports | 12 # System-level imports |
| 13 import httplib | |
| 14 import logging | |
| 13 import optparse | 15 import optparse |
| 14 import os | 16 import os |
| 15 import posixpath | 17 import posixpath |
| 16 import re | 18 import re |
| 19 import traceback | |
| 17 import urllib2 | 20 import urllib2 |
| 18 | 21 |
| 19 # Must fix up PYTHONPATH before importing from within Skia | 22 # Must fix up PYTHONPATH before importing from within Skia |
| 20 import rs_fixpypath # pylint: disable=W0611 | 23 import rs_fixpypath # pylint: disable=W0611 |
| 21 | 24 |
| 22 # Imports from within Skia | 25 # Imports from within Skia |
| 23 from py.utils import gs_utils | 26 from py.utils import gs_utils |
| 24 from py.utils import url_utils | 27 from py.utils import url_utils |
| 25 import buildbot_globals | 28 import buildbot_globals |
| 26 import gm_json | 29 import gm_json |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 def get_builders_list(summaries_bucket=GM_SUMMARIES_BUCKET): | 92 def get_builders_list(summaries_bucket=GM_SUMMARIES_BUCKET): |
| 90 """ Returns the list of builders we have actual results for. | 93 """ Returns the list of builders we have actual results for. |
| 91 | 94 |
| 92 Args: | 95 Args: |
| 93 summaries_bucket: Google Cloud Storage bucket containing the summary | 96 summaries_bucket: Google Cloud Storage bucket containing the summary |
| 94 JSON files | 97 JSON files |
| 95 """ | 98 """ |
| 96 dirs, _ = gs_utils.GSUtils().list_bucket_contents(bucket=GM_SUMMARIES_BUCKET) | 99 dirs, _ = gs_utils.GSUtils().list_bucket_contents(bucket=GM_SUMMARIES_BUCKET) |
| 97 return dirs | 100 return dirs |
| 98 | 101 |
| 102 def get_rietveld_actuals(issue, json_filename): | |
| 103 """ Returns the actuals for the given rietveld issue's tryjobs. | |
| 104 {non_try_builder:string -> [ bucket:string, path:string, generation:string ]} | |
| 105 | |
| 106 e.g. | |
| 107 {'Test-Android-Xoom-Tegra2-Arm7-Release': ( | |
| 108 'chromium-skia-gm-summaries', | |
| 109 'Test-Android-Xoom-Tegra2-Arm7-Release-Trybot/actual-results.json', | |
| 110 '1415041165535000')} | |
| 111 """ | |
| 112 result = dict() | |
| 113 json_filename_re = re.compile('^Created: gs://([^/]+)/((?:[^/]+/)+%s)#(\d+)$' | |
| 114 % re.escape(json_filename), re.MULTILINE) | |
| 115 codereview_api_url = 'https://codereview.chromium.org/api' | |
| 116 upload_gm_results_step_url = '/steps/Upload GM Results/logs/stdio' | |
| 117 | |
| 118 logging.info('Fetching issue %s ...' % (issue,)) | |
| 119 json_issue_url = '%s/%s' % (codereview_api_url, issue) | |
| 120 json_issue_data = urllib2.urlopen(json_issue_url).read() | |
| 121 issue_dict = gm_json.LoadFromString(json_issue_data) | |
| 122 | |
| 123 patchsets = issue_dict.get("patchsets", []) | |
| 124 patchset = patchsets[-1] | |
| 125 if not patchset: | |
| 126 logging.warning('No patchsets for rietveld issue %s.' % (issue,)) | |
| 127 return result | |
| 128 | |
| 129 logging.info('Fetching issue %s patch %s...' % (issue, patchset)) | |
| 130 json_patchset_url = '%s/%s/%s' % (codereview_api_url, issue, patchset) | |
| 131 json_patchset_data = urllib2.urlopen(json_patchset_url).read() | |
| 132 patchset_dict = gm_json.LoadFromString(json_patchset_data) | |
| 133 | |
| 134 # try_job_results is ordered reverse chronologically | |
| 135 try_job_results = patchset_dict.get('try_job_results', []) | |
| 136 for try_job_result in try_job_results: | |
| 137 builder = try_job_result.get('builder', '<bad builder>') | |
| 138 non_try_builder = builder | |
|
rmistry
2014/11/05 13:39:16
Seems confusing to switch non_try_builder's value
bungeman-skia
2014/11/07 22:56:52
Done.
| |
| 139 if non_try_builder.endswith('-Trybot'): | |
| 140 non_try_builder = non_try_builder[:-len('-Trybot')] | |
| 141 if non_try_builder in result: | |
| 142 continue | |
| 143 | |
| 144 logging.info('Fetching issue %s patch %s try %s...' % | |
| 145 (issue, patchset, builder)) | |
| 146 build_url = try_job_result.get('url', '<bad url>') | |
| 147 gm_upload_output_url = build_url + urllib2.quote(upload_gm_results_step_url) | |
| 148 logging.info('Fetching %s ...' % (gm_upload_output_url,)) | |
| 149 | |
| 150 # Tryjobs might not produce the step, but don't let that fail everything. | |
| 151 gm_upload_output = None | |
| 152 try: | |
| 153 gm_upload_output = urllib2.urlopen(gm_upload_output_url).read() | |
| 154 except urllib2.HTTPError, e: | |
| 155 logging.warning('HTTPError: ' + str(e.code)) | |
| 156 except urllib2.URLError, e: | |
| 157 logging.warning('URLError: ' + str(e.reason)) | |
| 158 except httplib.HTTPException, e: | |
| 159 logging.warning('HTTPException') | |
| 160 except Exception: | |
| 161 logging.warning('generic exception: ' + traceback.format_exc()) | |
|
rmistry
2014/11/05 13:39:16
traceback.format_exc() returns None so this will p
bungeman-skia
2014/11/07 22:56:53
Done.
| |
| 162 if not gm_upload_output: | |
| 163 logging.warning('Could not fetch %s .' % (gm_upload_output_url,)) | |
| 164 continue | |
| 165 | |
| 166 json_filename_match = json_filename_re.search(gm_upload_output) | |
| 167 if json_filename_match: | |
| 168 logging.info('Found issue %s patch %s try %s result gs://%s/%s#%s .' % | |
| 169 (issue, patchset, non_try_builder, | |
| 170 json_filename_match.group(1), | |
| 171 json_filename_match.group(2), | |
| 172 json_filename_match.group(3))) | |
| 173 result[non_try_builder] = [json_filename_match.group(1), | |
| 174 json_filename_match.group(2), | |
| 175 json_filename_match.group(3)] | |
| 176 else: | |
| 177 logging.warning('Did not find %s for issue %s patch %s try %s.' % | |
| 178 (json_filename, issue, patchset, builder)) | |
| 179 | |
| 180 return result | |
| 99 | 181 |
| 100 def main(): | 182 def main(): |
| 101 parser = optparse.OptionParser() | 183 parser = optparse.OptionParser() |
| 102 required_params = [] | 184 required_params = [] |
| 103 parser.add_option('--actuals-base-url', | 185 parser.add_option('--actuals-base-url', |
| 104 action='store', type='string', | 186 action='store', type='string', |
| 105 default=DEFAULT_ACTUALS_BASE_URL, | 187 default=DEFAULT_ACTUALS_BASE_URL, |
| 106 help=('Base URL from which to read files containing JSON ' | 188 help=('Base URL from which to read files containing JSON ' |
| 107 'summaries of actual GM results; defaults to ' | 189 'summaries of actual GM results; defaults to ' |
| 108 '"%default".')) | 190 '"%default".')) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 145 remaining_args) | 227 remaining_args) |
| 146 | 228 |
| 147 downloader = Download(actuals_base_url=params.actuals_base_url) | 229 downloader = Download(actuals_base_url=params.actuals_base_url) |
| 148 downloader.fetch(builder_name=params.builder, | 230 downloader.fetch(builder_name=params.builder, |
| 149 dest_dir=params.dest_dir) | 231 dest_dir=params.dest_dir) |
| 150 | 232 |
| 151 | 233 |
| 152 | 234 |
| 153 if __name__ == '__main__': | 235 if __name__ == '__main__': |
| 154 main() | 236 main() |
| OLD | NEW |