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 import logging | 5 import logging |
6 from webkitpy.w3c.local_wpt import LocalWPT | 6 from webkitpy.w3c.local_wpt import LocalWPT |
7 from webkitpy.w3c.chromium_wpt import ChromiumWPT | |
8 from webkitpy.w3c.chromium_commit import ChromiumCommit | 7 from webkitpy.w3c.chromium_commit import ChromiumCommit |
9 | 8 |
9 CHROMIUM_WPT_DIR = 'third_party/WebKit/LayoutTests/imported/wpt/' | |
10 _log = logging.getLogger(__name__) | 10 _log = logging.getLogger(__name__) |
11 | 11 |
12 # TODO(jeffcarp): integrate chromium_wpt_unittests into this module's tests | |
13 # TODO(jeffcarp): have the script running this fetch Chromium origin/master | |
12 | 14 |
13 class TestExporter(object): | 15 class TestExporter(object): |
14 | 16 |
15 def __init__(self, host, wpt_github, dry_run=False): | 17 def __init__(self, host, wpt_github, dry_run=False): |
16 self.host = host | 18 self.host = host |
17 self.wpt_github = wpt_github | 19 self.wpt_github = wpt_github |
20 self.local_wpt = LocalWPT(self.host) | |
18 self.dry_run = dry_run | 21 self.dry_run = dry_run |
19 | 22 |
20 def run(self): | 23 def run(self): |
21 # First, poll for an in-flight pull request and merge if exists | |
22 pull_requests = self.wpt_github.in_flight_pull_requests() | 24 pull_requests = self.wpt_github.in_flight_pull_requests() |
23 | 25 |
24 if len(pull_requests) == 1: | 26 if len(pull_requests) == 1: |
25 pull_request = pull_requests.pop() | 27 pull_request = pull_requests.pop() |
26 | 28 |
27 _log.info('In-flight PR found: #%d', pull_request['number']) | 29 _log.info('In-flight PR found: #%d', pull_request['number']) |
28 _log.info(pull_request['title']) | 30 _log.info(pull_request['title']) |
29 | 31 |
30 # TODO(jeffcarp): Check the PR status here | 32 # TODO(jeffcarp): Check the PR status here |
31 | 33 |
32 if self.dry_run: | 34 if self.dry_run: |
33 _log.info('[dry_run] Would have attempted to merge PR') | 35 _log.info('[dry_run] Would have attempted to merge PR') |
34 else: | 36 else: |
35 _log.info('Merging...') | 37 _log.info('Merging...') |
36 self.wpt_github.merge_pull_request(pull_request['number']) | 38 self.wpt_github.merge_pull_request(pull_request['number']) |
37 _log.info('PR merged!') | 39 _log.info('PR merged!') |
40 # TODO(jeffcarp): Delete remote branch after merging | |
41 | |
42 # The script needs to stop here since the Chromium | |
43 # WPT mirror lags behind a little bit. Also, it's probably safer | |
44 # to not be merging and creating a PR in the same run. | |
45 return | |
38 elif len(pull_requests) > 1: | 46 elif len(pull_requests) > 1: |
39 _log.error(pull_requests) | 47 _log.error(pull_requests) |
40 # TODO(jeffcarp): Print links to PRs | 48 # TODO(jeffcarp): Print links to PRs |
41 raise Exception('More than two in-flight PRs!') | 49 raise Exception('More than two in-flight PRs!') |
50 else: | |
51 self.create_export_pull_request() | |
42 | 52 |
43 # Second, look for exportable commits in Chromium | 53 def merge_pull_request(self, pull_request): |
44 # At this point, no in-flight PRs should exist | 54 """Attempts to merge an in-flight PR. |
45 # If there was an issue merging, it should have errored out | |
46 local_wpt = LocalWPT(self.host, use_github=False) | |
47 chromium_wpt = ChromiumWPT(self.host) | |
48 | 55 |
49 # TODO(jeffcarp): have the script running this fetch Chromium origin/mas ter | 56 Args: |
50 # TODO(jeffcarp): move WPT fetch out of its constructor to match planned ChromiumWPT pattern | 57 pull_request: a dict representing the pull request. |
58 """ | |
59 _log.info('In-flight PR found: #%d', pull_request['number']) | |
60 _log.info(pull_request['title']) | |
51 | 61 |
52 wpt_commit, chromium_commit = local_wpt.most_recent_chromium_commit() | 62 # TODO(jeffcarp): Check the PR status here |
53 assert chromium_commit, 'No Chromium commit found, this is impossible' | |
54 | 63 |
55 wpt_behind_master = local_wpt.commits_behind_master(wpt_commit) | 64 if self.dry_run: |
65 _log.info('[dry run] Would attempt to merge PR.') | |
66 else: | |
67 _log.info('Merging...') | |
68 self.wpt_github.merge_pull_request(pull_request['number']) | |
69 _log.info('PR merged!') | |
70 # TODO(jeffcarp): Delete remote branch after merging | |
56 | 71 |
57 _log.info('\nLast Chromium export commit in web-platform-tests:') | 72 def create_export_pull_request(self): |
58 _log.info('web-platform-tests@%s', wpt_commit) | 73 """Creates a PR for the earliest exportable commit in Chromium if there is one. |
59 _log.info('(%d behind web-platform-tests@origin/master)', wpt_behind_mas ter) | |
60 | 74 |
61 _log.info('\nThe above WPT commit points to the following Chromium commi t:') | 75 This will create a branch on w3c/web-platform-tests and make a request |
62 _log.info('chromium@%s', chromium_commit.sha) | 76 to the GitHub API to create a pull request. |
63 _log.info('(%d behind chromium@origin/master)', chromium_commit.num_behi nd_master()) | |
64 | 77 |
65 # TODO(jeffcarp): Have this function return ChromiumCommits | 78 At this point, no in-flight PRs should exist. |
66 exportable_commits = chromium_wpt.exportable_commits_since(chromium_comm it.sha) | 79 |
80 Returns: | |
81 None | |
82 """ | |
83 exportable_commits = self.exportable_commits() | |
67 | 84 |
68 if not exportable_commits: | 85 if not exportable_commits: |
69 _log.info('No exportable commits found in Chromium, stopping.') | 86 _log.info('No exportable commits found in Chromium, stopping.') |
70 return | 87 return |
71 | 88 |
72 _log.info('Found %d exportable commits in Chromium:', len(exportable_com mits)) | 89 _log.info('Found %d exportable commits in Chromium:', len(exportable_com mits)) |
73 for commit in exportable_commits: | 90 for commit in exportable_commits: |
74 _log.info('- %s %s', commit, chromium_wpt.subject(commit)) | 91 _log.info('- %s %s', commit, commit.subject()) |
75 | 92 |
76 outbound_commit = ChromiumCommit(self.host, sha=exportable_commits[0]) | |
77 _log.info('Picking the earliest commit and creating a PR') | 93 _log.info('Picking the earliest commit and creating a PR') |
94 outbound_commit = exportable_commits[0] | |
78 _log.info('- %s %s', outbound_commit.sha, outbound_commit.subject()) | 95 _log.info('- %s %s', outbound_commit.sha, outbound_commit.subject()) |
79 | 96 |
80 patch = outbound_commit.format_patch() | 97 patch = outbound_commit.format_patch() |
81 message = outbound_commit.message() | 98 message = outbound_commit.message() |
82 | 99 |
83 # TODO: now do a test comparison of patch against local WPT | |
84 | |
85 if self.dry_run: | 100 if self.dry_run: |
86 _log.info('[dry_run] Stopping before creating PR') | 101 _log.info('[dry_run] Stopping before creating PR') |
87 _log.info('\n\n[dry_run] message:') | 102 _log.info('\n\n[dry_run] message:') |
88 _log.info(message) | 103 _log.info(message) |
89 _log.info('\n\n[dry_run] patch:') | 104 _log.info('\n\n[dry_run] patch:') |
90 _log.info(patch) | 105 _log.info(patch) |
91 return | 106 return |
92 | 107 |
93 local_branch_name = local_wpt.create_branch_with_patch(message, patch) | 108 remote_branch_name = self.local_wpt.create_branch_with_patch(message, pa tch) |
94 | 109 |
95 response_data = self.wpt_github.create_pr( | 110 response_data = self.wpt_github.create_pr( |
96 local_branch_name=local_branch_name, | 111 remote_branch_name=remote_branch_name, |
97 desc_title=outbound_commit.subject(), | 112 desc_title=outbound_commit.subject(), |
98 body=outbound_commit.body()) | 113 body=outbound_commit.body()) |
99 | 114 |
100 _log.info('Create PR response: %s', response_data) | 115 _log.info('Create PR response: %s', response_data) |
116 | |
117 if response_data: | |
118 data, status_code = self.wpt_github.add_label(response_data['number' ]) | |
119 _log.info('Add label response (status %s): %s', status_code, data) | |
120 | |
121 # TODO(jeffcarp): Create a comment on the PR to CC foolip and qyearsley | |
122 # also explain that this is an automated export and will be auto-merge d if green | |
123 | |
124 def exportable_commits(self): | |
125 """Returns all exportable Chromium commits, earliest first. | |
126 | |
qyearsley
2016/12/15 20:59:14
Possible extra comment: this looks at commits in C
| |
127 Returns: | |
128 A list of ChromiumCommits | |
qyearsley
2016/12/15 20:59:14
Nit: period
| |
129 """ | |
130 wpt_commit, chromium_commit = self.local_wpt.most_recent_chromium_commit () | |
131 assert chromium_commit, 'No Chromium commit found, this is impossible.' | |
132 | |
133 _log.info('\nLast Chromium export commit in web-platform-tests:') | |
134 _log.info('web-platform-tests@%s', wpt_commit) | |
135 _log.info('(%d behind web-platform-tests@origin/master)', | |
136 self.local_wpt.commits_behind_master(wpt_commit)) | |
137 | |
138 _log.info('\nThe above WPT commit points to the following Chromium commi t:') | |
139 _log.info('chromium@%s', chromium_commit.sha) | |
140 _log.info('(%d behind chromium@origin/master)', chromium_commit.num_behi nd_master()) | |
qyearsley
2016/12/15 20:59:14
This could potentially be changed to debug-level r
| |
141 | |
142 chromium_commits = [ChromiumCommit(self.host, sha=sha) | |
143 for sha in self.commits_with_changes_in_wpt_since(ch romium_commit.sha)] | |
144 | |
145 def is_exportable(commit): | |
146 patch = commit.format_patch() | |
147 return ( | |
148 patch | |
149 and self.local_wpt.test_patch(patch) | |
150 and 'NOEXPORT=true' not in commit.message() | |
151 and not commit.message().startswith('Import ') | |
152 ) | |
153 | |
154 return [c for c in chromium_commits if is_exportable(c)] | |
155 | |
156 def commits_with_changes_in_wpt_since(self, sha): | |
157 toplevel = self.host.executive.run_command([ | |
158 'git', 'rev-parse', '--show-toplevel' | |
159 ]).strip() | |
160 | |
161 return self.host.executive.run_command([ | |
162 'git', 'rev-list', '{}..HEAD'.format(sha), '--reverse', | |
163 '--', toplevel + '/' + CHROMIUM_WPT_DIR | |
164 ]).splitlines() | |
OLD | NEW |