OLD | NEW |
---|---|
1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """A command to fetch new baselines from try jobs for the current CL.""" | 5 """A command to fetch new baselines from try jobs for the current CL.""" |
6 | 6 |
7 import json | 7 import json |
8 import logging | 8 import logging |
9 import optparse | 9 import optparse |
10 | 10 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
56 _log.error(' %s', path) | 56 _log.error(' %s', path) |
57 return 1 | 57 return 1 |
58 | 58 |
59 issue_number = self._get_issue_number() | 59 issue_number = self._get_issue_number() |
60 if issue_number is None: | 60 if issue_number is None: |
61 _log.error('No issue number for current branch.') | 61 _log.error('No issue number for current branch.') |
62 return 1 | 62 return 1 |
63 _log.debug('Issue number for current branch: %s', issue_number) | 63 _log.debug('Issue number for current branch: %s', issue_number) |
64 | 64 |
65 builds = self.git_cl().latest_try_jobs(self._try_bots()) | 65 builds = self.git_cl().latest_try_jobs(self._try_bots()) |
66 | 66 self._log_pending_builds(builds) |
67 builders_with_pending_builds = self.builders_with_pending_builds(builds) | |
68 if builders_with_pending_builds: | |
69 _log.info('There are existing pending builds for:') | |
70 for builder in sorted(builders_with_pending_builds): | |
71 _log.info(' %s', builder) | |
72 builders_with_no_results = self.builders_with_no_results(builds) | 67 builders_with_no_results = self.builders_with_no_results(builds) |
73 | 68 |
74 if options.trigger_jobs and builders_with_no_results: | 69 if options.trigger_jobs: |
75 self.trigger_builds(builders_with_no_results) | 70 triggered = self.trigger_builds(builders_with_no_results) |
76 _log.info('Please re-run webkit-patch rebaseline-cl once all pending try jobs have finished.') | 71 if triggered: |
jeffcarp
2017/05/19 20:21:45
Could these two lines be collapsed?
qyearsley
2017/05/19 20:39:03
Yep, and that would be a bit nicer I think; done.
| |
77 return 1 | 72 return 1 |
78 | 73 |
79 if builders_with_no_results and not options.fill_missing: | 74 if builders_with_no_results and not options.fill_missing: |
80 _log.error('The following builders have no results:') | 75 _log.error('The following builders have no results:') |
81 for builder in builders_with_no_results: | 76 for builder in builders_with_no_results: |
82 _log.error(' %s', builder) | 77 _log.error(' %s', builder) |
83 return 1 | 78 return 1 |
84 | 79 |
85 _log.debug('Getting results for issue %d.', issue_number) | 80 _log.debug('Getting results for issue %d.', issue_number) |
86 builds_to_results = self._fetch_results(builds) | 81 builds_to_results = self._fetch_results(builds) |
87 if not options.fill_missing and len(builds_to_results) < len(builds): | 82 if not options.fill_missing and len(builds_to_results) < len(builds): |
88 return 1 | 83 return 1 |
89 | 84 |
90 test_baseline_set = TestBaselineSet(tool) | |
91 if args: | 85 if args: |
92 for test in args: | 86 test_baseline_set = self._make_test_baseline_set_for_tests( |
93 for build in builds: | 87 args, builds_to_results) |
94 if not builds_to_results.get(build): | |
95 continue | |
96 test_baseline_set.add(test, build) | |
97 else: | 88 else: |
98 test_baseline_set = self._make_test_baseline_set( | 89 test_baseline_set = self._make_test_baseline_set( |
99 builds_to_results, | 90 builds_to_results, options.only_changed_tests) |
100 only_changed_tests=options.only_changed_tests) | |
101 | 91 |
102 if options.fill_missing: | 92 if options.fill_missing: |
103 self.fill_in_missing_results(test_baseline_set) | 93 self.fill_in_missing_results(test_baseline_set) |
104 | 94 |
105 _log.debug('Rebaselining: %s', test_baseline_set) | 95 _log.debug('Rebaselining: %s', test_baseline_set) |
106 | 96 |
107 if not options.dry_run: | 97 if not options.dry_run: |
108 self.rebaseline(options, test_baseline_set) | 98 self.rebaseline(options, test_baseline_set) |
109 return 0 | 99 return 0 |
110 | 100 |
111 def _get_issue_number(self): | 101 def _get_issue_number(self): |
112 """Returns the current CL issue number, or None.""" | 102 """Returns the current CL issue number, or None.""" |
113 issue = self.git_cl().get_issue_number() | 103 issue = self.git_cl().get_issue_number() |
114 if not issue.isdigit(): | 104 if not issue.isdigit(): |
115 return None | 105 return None |
116 return int(issue) | 106 return int(issue) |
117 | 107 |
118 def git_cl(self): | 108 def git_cl(self): |
119 """Returns a GitCL instance. Can be overridden for tests.""" | 109 """Returns a GitCL instance. Can be overridden for tests.""" |
120 return GitCL(self._tool) | 110 return GitCL(self._tool) |
121 | 111 |
122 def trigger_builds(self, builders): | 112 def trigger_builds(self, builders): |
113 """Triggers try jobs if necessary; returns whether builds were triggered .""" | |
114 if builders is None: | |
115 return False | |
123 _log.info('Triggering try jobs for:') | 116 _log.info('Triggering try jobs for:') |
124 for builder in sorted(builders): | 117 for builder in sorted(builders): |
125 _log.info(' %s', builder) | 118 _log.info(' %s', builder) |
126 self.git_cl().trigger_try_jobs(builders) | 119 self.git_cl().trigger_try_jobs(builders) |
120 _log.info('Once all pending try jobs have finished, please re-run\n' | |
121 'webkit-patch rebaseline-cl to fetch new baselines.') | |
122 return True | |
127 | 123 |
128 def builders_with_no_results(self, builds): | 124 def builders_with_no_results(self, builds): |
129 """Returns the set of builders that don't have finished results.""" | 125 """Returns the set of builders that don't have finished results.""" |
130 builders_with_no_builds = set(self._try_bots()) - {b.builder_name for b in builds} | 126 builders_with_no_builds = set(self._try_bots()) - {b.builder_name for b in builds} |
131 return builders_with_no_builds | self.builders_with_pending_builds(build s) | 127 return builders_with_no_builds | self.builders_with_pending_builds(build s) |
132 | 128 |
129 def _log_pending_builds(self, builds): | |
130 builders = self.builders_with_pending_builds(builds) | |
131 if not builders: | |
132 return | |
133 _log.info('There are existing pending builds for:') | |
134 for builder in sorted(builders): | |
135 _log.info(' %s', builder) | |
136 | |
133 def builders_with_pending_builds(self, builds): | 137 def builders_with_pending_builds(self, builds): |
134 """Returns the set of builders that have pending builds.""" | 138 """Returns the set of builders that have pending builds.""" |
135 return {b.builder_name for b in builds if b.build_number is None} | 139 return {b.builder_name for b in builds if b.build_number is None} |
136 | 140 |
137 def _try_bots(self): | 141 def _try_bots(self): |
138 """Returns a collection of try bot builders to fetch results for.""" | 142 """Returns a collection of try bot builders to fetch results for.""" |
139 return self._tool.builders.all_try_builder_names() | 143 return self._tool.builders.all_try_builder_names() |
140 | 144 |
141 def _fetch_results(self, builds): | 145 def _fetch_results(self, builds): |
142 """Fetches results for all of the given builds. | 146 """Fetches results for all of the given builds. |
(...skipping 17 matching lines...) Expand all Loading... | |
160 results_url = buildbot.results_url(build.builder_name, build.build_n umber) | 164 results_url = buildbot.results_url(build.builder_name, build.build_n umber) |
161 layout_test_results = buildbot.fetch_results(build) | 165 layout_test_results = buildbot.fetch_results(build) |
162 if layout_test_results is None: | 166 if layout_test_results is None: |
163 _log.info('Failed to fetch results for %s', build) | 167 _log.info('Failed to fetch results for %s', build) |
164 _log.info('Results URL: %s/results.html', results_url) | 168 _log.info('Results URL: %s/results.html', results_url) |
165 _log.info('Retry job by running: git cl try -b %s', build.builde r_name) | 169 _log.info('Retry job by running: git cl try -b %s', build.builde r_name) |
166 continue | 170 continue |
167 results[build] = layout_test_results | 171 results[build] = layout_test_results |
168 return results | 172 return results |
169 | 173 |
174 def _make_test_baseline_set_for_tests(self, tests, builds_to_results): | |
175 test_baseline_set = TestBaselineSet(self._tool) | |
176 for test in tests: | |
177 for build in builds_to_results: | |
178 test_baseline_set.add(test, build) | |
179 return test_baseline_set | |
180 | |
170 def _make_test_baseline_set(self, builds_to_results, only_changed_tests): | 181 def _make_test_baseline_set(self, builds_to_results, only_changed_tests): |
171 """Returns a dict which lists the set of baselines to fetch. | 182 """Returns a dict which lists the set of baselines to fetch. |
172 | 183 |
173 The dict that is returned is a dict of tests to Build objects | 184 The dict that is returned is a dict of tests to Build objects |
174 to baseline file extensions. | 185 to baseline file extensions. |
175 | 186 |
176 Args: | 187 Args: |
177 builds_to_results: A dict mapping Builds to LayoutTestResults. | 188 builds_to_results: A dict mapping Builds to LayoutTestResults. |
178 only_changed_tests: Whether to only include baselines for tests that | 189 only_changed_tests: Whether to only include baselines for tests that |
179 are changed in this CL. If False, all new baselines for failing | 190 are changed in this CL. If False, all new baselines for failing |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
266 | 277 |
267 # If any Build exists with the same OS, use the first one. | 278 # If any Build exists with the same OS, use the first one. |
268 target_os = os_name(target_port) | 279 target_os = os_name(target_port) |
269 same_os_builds = sorted(b for b, p in build_port_pairs if os_name(p) == target_os) | 280 same_os_builds = sorted(b for b, p in build_port_pairs if os_name(p) == target_os) |
270 if same_os_builds: | 281 if same_os_builds: |
271 return same_os_builds[0] | 282 return same_os_builds[0] |
272 | 283 |
273 # Otherwise, perhaps any build will do, for example if the results are | 284 # Otherwise, perhaps any build will do, for example if the results are |
274 # the same on all platforms. In this case, just return the first build. | 285 # the same on all platforms. In this case, just return the first build. |
275 return sorted(build_port_pairs)[0][0] | 286 return sorted(build_port_pairs)[0][0] |
OLD | NEW |