Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(287)

Side by Side Diff: third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl.py

Issue 2237083002: In rebaseline-cl: add option to only rebaseline tests changed in the CL. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 a Rietveld issue. 5 """A command to fetch new baselines from try jobs for a Rietveld issue.
6 6
7 This command interacts with the Rietveld API to get information about try jobs 7 This command interacts with the Rietveld API to get information about try jobs
8 with layout test results. 8 with layout test results.
9 """ 9 """
10 10
11 import logging 11 import logging
12 import optparse 12 import optparse
13 13
14 from webkitpy.common.checkout.scm.git import Git 14 from webkitpy.common.checkout.scm.git import Git
15 from webkitpy.common.net.rietveld import latest_try_jobs 15 from webkitpy.common.net.buildbot import Build
16 from webkitpy.common.net.rietveld import latest_try_jobs, changed_files
16 from webkitpy.common.net.web import Web 17 from webkitpy.common.net.web import Web
18 from webkitpy.common.webkit_finder import WebKitFinder
17 from webkitpy.layout_tests.models.test_expectations import BASELINE_SUFFIX_LIST 19 from webkitpy.layout_tests.models.test_expectations import BASELINE_SUFFIX_LIST
18 from webkitpy.tool.commands.rebaseline import AbstractParallelRebaselineCommand 20 from webkitpy.tool.commands.rebaseline import AbstractParallelRebaselineCommand
19 from webkitpy.tool.commands.rebaseline import Build
20 21
21 22
22 _log = logging.getLogger(__name__) 23 _log = logging.getLogger(__name__)
23 24
24 25
25 class RebaselineCL(AbstractParallelRebaselineCommand): 26 class RebaselineCL(AbstractParallelRebaselineCommand):
26 name = "rebaseline-cl" 27 name = "rebaseline-cl"
27 help_text = "Fetches new baselines for one CL, from layout test runs on try bots." 28 help_text = "Fetches new baselines for a CL from test runs on try bots."
29 long_help = ("By default, this command will check the latest try results "
30 "and download new baselines for any tests that have been "
31 "changed in the given CL that have failed and have new "
32 "baselines. After downloading, the baselines for different "
33 "platforms should be optimized (conslidated).")
28 show_in_main_help = True 34 show_in_main_help = True
29 35
30 def __init__(self): 36 def __init__(self):
31 super(RebaselineCL, self).__init__(options=[ 37 super(RebaselineCL, self).__init__(options=[
32 optparse.make_option( 38 optparse.make_option(
33 '--issue', type='int', default=None, 39 '--issue', type='int', default=None,
34 help='Rietveld issue number; if none given, this will be obtaine d via `git cl issue`.'), 40 help='Rietveld issue number; if none given, this will be obtaine d via `git cl issue`.'),
35 optparse.make_option( 41 optparse.make_option(
36 '--dry-run', action='store_true', default=False, 42 '--dry-run', action='store_true', default=False,
37 help='Dry run mode; list actions that would be performed but do not do anything.'), 43 help='Dry run mode; list actions that would be performed but do not do anything.'),
44 optparse.make_option(
45 '--only-changed-tests', action='store_true', default=False,
46 help='Only download new baselines for tests that are changed in the CL.'),
38 self.no_optimize_option, 47 self.no_optimize_option,
39 self.results_directory_option, 48 self.results_directory_option,
40 ]) 49 ])
41 self.web = Web() 50 self.web = Web()
42 51
43 def execute(self, options, args, tool): 52 def execute(self, options, args, tool):
44 issue_number = self._get_issue_number(options) 53 issue_number = self._get_issue_number(options)
45 if not issue_number: 54 if not issue_number:
46 return 55 return
47 if args: 56 if args:
48 test_prefix_list = {} 57 test_prefix_list = {}
49 try_jobs = latest_try_jobs(issue_number, self._try_bots(), self.web) 58 try_jobs = latest_try_jobs(issue_number, self._try_bots(), self.web)
50 builds = [Build(j.builder_name, j.build_number) for j in try_jobs] 59 builds = [Build(j.builder_name, j.build_number) for j in try_jobs]
51 for test in args: 60 for test in args:
52 test_prefix_list[test] = {b: BASELINE_SUFFIX_LIST for b in build s} 61 test_prefix_list[test] = {b: BASELINE_SUFFIX_LIST for b in build s}
53 else: 62 else:
54 test_prefix_list = self._test_prefix_list(issue_number) 63 test_prefix_list = self._test_prefix_list(
64 issue_number, only_changed_tests=options.only_changed_tests)
55 self._log_test_prefix_list(test_prefix_list) 65 self._log_test_prefix_list(test_prefix_list)
56 66
57 if options.dry_run: 67 if options.dry_run:
58 return 68 return
59 self._rebaseline(options, test_prefix_list) 69 self._rebaseline(options, test_prefix_list)
60 70
61 def _get_issue_number(self, options): 71 def _get_issue_number(self, options):
62 """Gets the Rietveld CL number from either |options| or from the current local branch.""" 72 """Gets the Rietveld CL number from either |options| or from the current local branch."""
63 if options.issue: 73 if options.issue:
64 return options.issue 74 return options.issue
65 issue_number = self.git().get_issue_number() 75 issue_number = self.git().get_issue_number()
66 _log.debug('Issue number for current branch: %s', issue_number) 76 _log.debug('Issue number for current branch: %s', issue_number)
67 if not issue_number.isdigit(): 77 if not issue_number.isdigit():
68 _log.error('No issue number given and no issue for current branch.') 78 _log.error('No issue number given and no issue for current branch.')
69 return None 79 return None
70 return int(issue_number) 80 return int(issue_number)
71 81
72 def git(self): 82 def git(self):
73 """Returns a Git instance; can be overridden for tests.""" 83 """Returns a Git instance; can be overridden for tests."""
74 # Pass in a current working directory inside of the repo so 84 # Pass in a current working directory inside of the repo so
75 # that this command can be called from outside of the repo. 85 # that this command can be called from outside of the repo.
76 return Git(cwd=self._tool.filesystem.dirname(self._tool.path())) 86 return Git(cwd=self._tool.filesystem.dirname(self._tool.path()))
77 87
78 def _test_prefix_list(self, issue_number): 88 def _test_prefix_list(self, issue_number, only_changed_tests):
79 """Returns a collection of test, builder and file extensions to get new baselines for.""" 89 """Returns a collection of test, builder and file extensions to get new baselines for.
90
91 Args:
92 issue_number: The CL number of the change which needs new baselines.
93 only_changed_tests: Whether to only include baselines for tests that
94 are changed in this CL. If False, all new baselines for failing
95 tests will be downloaded, even for tests that were not modified.
96
97 Returns:
98 A dict containing information about which new baselines to download.
99 """
80 builds_to_tests = self._builds_to_tests(issue_number) 100 builds_to_tests = self._builds_to_tests(issue_number)
101 if only_changed_tests:
102 files_in_cl = changed_files(issue_number, self.web)
103 finder = WebKitFinder(self._tool.filesystem)
104 tests_in_cl = [finder.layout_test_name(f) for f in files_in_cl]
81 result = {} 105 result = {}
82 for build, tests in builds_to_tests.iteritems(): 106 for build, tests in builds_to_tests.iteritems():
83 for test in tests: 107 for test in tests:
108 if only_changed_tests and test not in tests_in_cl:
109 continue
84 if test not in result: 110 if test not in result:
85 result[test] = {} 111 result[test] = {}
86 result[test][build] = BASELINE_SUFFIX_LIST 112 result[test][build] = BASELINE_SUFFIX_LIST
87 return result 113 return result
88 114
89 def _builds_to_tests(self, issue_number): 115 def _builds_to_tests(self, issue_number):
90 """Fetches a list of try bots, and for each, fetches tests with new base lines.""" 116 """Fetches a list of try bots, and for each, fetches tests with new base lines."""
91 _log.debug('Getting results for Rietveld issue %d.', issue_number) 117 _log.debug('Getting results for Rietveld issue %d.', issue_number)
92 try_jobs = latest_try_jobs(issue_number, self._try_bots(), self.web) 118 try_jobs = latest_try_jobs(issue_number, self._try_bots(), self.web)
93 if not try_jobs: 119 if not try_jobs:
94 _log.debug('No try job results for builders in: %r.', self._try_bots ()) 120 _log.debug('No try job results for builders in: %r.', self._try_bots ())
95 builds_to_tests = {} 121 builds_to_tests = {}
96 for job in try_jobs: 122 for job in try_jobs:
97 test_results = self._unexpected_mismatch_results(job) 123 test_results = self._unexpected_mismatch_results(job)
98 build = Build(job.builder_name, job.build_number) 124 build = Build(job.builder_name, job.build_number)
99 builds_to_tests[build] = sorted(r.test_name() for r in test_results) 125 builds_to_tests[build] = sorted(r.test_name() for r in test_results)
100 return builds_to_tests 126 return builds_to_tests
101 127
102 def _try_bots(self): 128 def _try_bots(self):
103 """Retuns a collection of try bot builders to fetch results for.""" 129 """Returns a collection of try bot builders to fetch results for."""
104 return self._tool.builders.all_try_builder_names() 130 return self._tool.builders.all_try_builder_names()
105 131
106 def _unexpected_mismatch_results(self, try_job): 132 def _unexpected_mismatch_results(self, try_job):
107 """Fetches a list of LayoutTestResult objects for unexpected results wit h new baselines.""" 133 """Fetches a list of LayoutTestResult objects for unexpected results wit h new baselines."""
108 buildbot = self._tool.buildbot 134 buildbot = self._tool.buildbot
109 results_url = buildbot.results_url(try_job.builder_name, try_job.build_n umber) 135 results_url = buildbot.results_url(try_job.builder_name, try_job.build_n umber)
110 layout_test_results = buildbot.fetch_layout_test_results(results_url) 136 layout_test_results = buildbot.fetch_layout_test_results(results_url)
111 if layout_test_results is None: 137 if layout_test_results is None:
112 _log.warning('Failed to request layout test results from "%s".', res ults_url) 138 _log.warning('Failed to request layout test results from "%s".', res ults_url)
113 return [] 139 return []
114 return layout_test_results.unexpected_mismatch_results() 140 return layout_test_results.unexpected_mismatch_results()
115 141
116 @staticmethod 142 @staticmethod
117 def _log_test_prefix_list(test_prefix_list): 143 def _log_test_prefix_list(test_prefix_list):
118 """Logs the tests to download new baselines for.""" 144 """Logs the tests to download new baselines for."""
119 if not test_prefix_list: 145 if not test_prefix_list:
120 _log.info('No tests to rebaseline.') 146 _log.info('No tests to rebaseline.')
121 return 147 return
122 _log.info('Tests to rebaseline:') 148 _log.info('Tests to rebaseline:')
123 for test, builds in test_prefix_list.iteritems(): 149 for test, builds in test_prefix_list.iteritems():
124 builds_str = ', '.join(sorted('%s (%s)' % (b.builder_name, b.build_n umber) for b in builds)) 150 builds_str = ', '.join(sorted('%s (%s)' % (b.builder_name, b.build_n umber) for b in builds))
125 _log.info(' %s: %s', test, builds_str) 151 _log.info(' %s: %s', test, builds_str)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698