| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 # Copyright (c) 2014 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 | 7 |
| 8 """Generate new bench expectations from results of trybots on a code review.""" | 8 """Generate new bench expectations from results of trybots on a code review.""" |
| 9 | 9 |
| 10 | 10 |
| 11 import collections | 11 import collections |
| 12 import compare_codereview | 12 import compare_codereview |
| 13 import os | 13 import os |
| 14 import re | 14 import re |
| 15 import shutil | 15 import shutil |
| 16 import subprocess | 16 import subprocess |
| 17 import sys | 17 import sys |
| 18 | 18 |
| 19 | 19 |
| 20 BENCH_DATA_URL = 'gs://chromium-skia-gm/perfdata/%s/%s/*' | 20 BENCH_DATA_URL = 'gs://chromium-skia-gm/perfdata/%s/%s/*' |
| 21 CHECKOUT_PATH = os.path.realpath(os.path.join( | 21 CHECKOUT_PATH = os.path.realpath(os.path.join( |
| 22 os.path.dirname(os.path.abspath(__file__)), os.pardir)) | 22 os.path.dirname(os.path.abspath(__file__)), os.pardir)) |
| 23 TMP_BENCH_DATA_DIR = os.path.join(CHECKOUT_PATH, '.bench_data') | 23 TMP_BENCH_DATA_DIR = os.path.join(CHECKOUT_PATH, '.bench_data') |
| 24 | 24 |
| 25 | 25 |
| 26 TryBuild = collections.namedtuple( |
| 27 'TryBuild', ['builder_name', 'build_number', 'is_finished']) |
| 28 |
| 29 |
| 26 def find_all_builds(codereview_url): | 30 def find_all_builds(codereview_url): |
| 27 """Finds and returns information about trybot runs for a code review. | 31 """Finds and returns information about trybot runs for a code review. |
| 28 | 32 |
| 29 Args: | 33 Args: |
| 30 codereview_url: URL of the codereview in question. | 34 codereview_url: URL of the codereview in question. |
| 31 | 35 |
| 32 Returns: | 36 Returns: |
| 33 List of NamedTuples: (builder_name, build_number, is_finished) | 37 List of NamedTuples: (builder_name, build_number, is_finished) |
| 34 """ | 38 """ |
| 35 results = compare_codereview.CodeReviewHTMLParser().parse(codereview_url) | 39 results = compare_codereview.CodeReviewHTMLParser().parse(codereview_url) |
| 36 TryBuild = collections.namedtuple( | |
| 37 'TryBuild', ['builder_name', 'build_number', 'is_finished']) | |
| 38 try_builds = [] | 40 try_builds = [] |
| 39 | |
| 40 for builder, data in results.iteritems(): | 41 for builder, data in results.iteritems(): |
| 41 if builder.startswith('Perf'): | 42 if builder.startswith('Perf'): |
| 42 try_builds.append(TryBuild(builder, data.url.split('/')[-1], | 43 build_num = data.url.split('/')[-1] if data.url else None |
| 44 try_builds.append(TryBuild(builder, build_num, |
| 43 data.status != 'pending')) | 45 data.status != 'pending')) |
| 44 return try_builds | 46 return try_builds |
| 45 | 47 |
| 46 | 48 |
| 49 def _all_trybots_finished(try_builds): |
| 50 """Return True iff all of the given try jobs have finished. |
| 51 |
| 52 Args: |
| 53 try_builds: list of TryBuild instances. |
| 54 |
| 55 Returns: |
| 56 True if all of the given try jobs have finished, otherwise False. |
| 57 """ |
| 58 for try_build in try_builds: |
| 59 if not try_build.is_finished: |
| 60 return False |
| 61 return True |
| 62 |
| 63 |
| 64 def all_trybots_finished(codereview_url): |
| 65 """Return True iff all of the try jobs on the given codereview have finished. |
| 66 |
| 67 Args: |
| 68 codereview_url: string; URL of the codereview. |
| 69 |
| 70 Returns: |
| 71 True if all of the try jobs have finished, otherwise False. |
| 72 """ |
| 73 return _all_trybots_finished(find_all_builds(codereview_url)) |
| 74 |
| 75 |
| 47 def get_bench_data(builder, build_num, dest_dir): | 76 def get_bench_data(builder, build_num, dest_dir): |
| 48 """Download the bench data for the given builder at the given build_num. | 77 """Download the bench data for the given builder at the given build_num. |
| 49 | 78 |
| 50 Args: | 79 Args: |
| 51 builder: string; name of the builder. | 80 builder: string; name of the builder. |
| 52 build_num: string; build number. | 81 build_num: string; build number. |
| 53 dest_dir: string; destination directory for the bench data. | 82 dest_dir: string; destination directory for the bench data. |
| 54 """ | 83 """ |
| 55 url = BENCH_DATA_URL % (builder, build_num) | 84 url = BENCH_DATA_URL % (builder, build_num) |
| 56 subprocess.check_call(['gsutil', 'cp', '-R', url, dest_dir], | 85 subprocess.check_call(['gsutil', 'cp', '-R', url, dest_dir], |
| (...skipping 30 matching lines...) Expand all Loading... |
| 87 finished trybots and uses them to generate new expectations for their | 116 finished trybots and uses them to generate new expectations for their |
| 88 waterfall counterparts. | 117 waterfall counterparts. |
| 89 | 118 |
| 90 Args: | 119 Args: |
| 91 url: string; URL of the code review. | 120 url: string; URL of the code review. |
| 92 error_on_unfinished: bool; throw an error if any trybot has not finished. | 121 error_on_unfinished: bool; throw an error if any trybot has not finished. |
| 93 """ | 122 """ |
| 94 try_builds = find_all_builds(codereview_url) | 123 try_builds = find_all_builds(codereview_url) |
| 95 | 124 |
| 96 # Verify that all trybots have finished running. | 125 # Verify that all trybots have finished running. |
| 97 if error_on_unfinished: | 126 if error_on_unfinished and not _all_trybots_finished(try_builds): |
| 98 for try_build in try_builds: | 127 raise TrybotNotFinishedError('Not all trybots have finished.') |
| 99 if not try_build.is_finished: | 128 |
| 100 raise TrybotNotFinishedError('%s: #%s is not finished.' % ( | |
| 101 try_build.builder_name, | |
| 102 try_build.build_number)) | |
| 103 failed_data_pull = [] | 129 failed_data_pull = [] |
| 104 failed_gen_expectations = [] | 130 failed_gen_expectations = [] |
| 105 | 131 |
| 106 if os.path.isdir(TMP_BENCH_DATA_DIR): | 132 if os.path.isdir(TMP_BENCH_DATA_DIR): |
| 107 shutil.rmtree(TMP_BENCH_DATA_DIR) | 133 shutil.rmtree(TMP_BENCH_DATA_DIR) |
| 108 | 134 |
| 109 for try_build in try_builds: | 135 for try_build in try_builds: |
| 110 try_builder = try_build.builder_name | 136 try_builder = try_build.builder_name |
| 111 builder = try_builder.replace('-Trybot', '') | 137 builder = try_builder.replace('-Trybot', '') |
| 112 | 138 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 if failed_gen_expectations: | 171 if failed_gen_expectations: |
| 146 failure += 'Failed to generate expectations for: %s\n\n' % ','.join( | 172 failure += 'Failed to generate expectations for: %s\n\n' % ','.join( |
| 147 failed_gen_expectations) | 173 failed_gen_expectations) |
| 148 if failure: | 174 if failure: |
| 149 raise Exception(failure) | 175 raise Exception(failure) |
| 150 | 176 |
| 151 | 177 |
| 152 if __name__ == '__main__': | 178 if __name__ == '__main__': |
| 153 gen_bench_expectations_from_codereview(sys.argv[1]) | 179 gen_bench_expectations_from_codereview(sys.argv[1]) |
| 154 | 180 |
| OLD | NEW |