blob: e575ce1cbc8e074ba2ef5fa914ff203933f092d6 [file] [log] [blame]
[email protected]ca8d1982009-02-19 16:33:121# Copyright (c) 2009 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
[email protected]50d7d721e2009-11-15 17:56:188for more details about the presubmit API built into gcl.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]4306417642009-06-11 00:33:4011EXCLUDED_PATHS = (
[email protected]33478702009-03-05 14:03:1412 r"breakpad[\\\/].*",
[email protected]33478702009-03-05 14:03:1413 r"skia[\\\/].*",
[email protected]33478702009-03-05 14:03:1414 r"v8[\\\/].*",
[email protected]4306417642009-06-11 00:33:4015)
[email protected]ca8d1982009-02-19 16:33:1216
[email protected]ca8d1982009-02-19 16:33:1217
[email protected]ca8d1982009-02-19 16:33:1218def CheckChangeOnUpload(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:5419 results = []
[email protected]4306417642009-06-11 00:33:4020 # What does this code do?
21 # It loads the default black list (e.g. third_party, experimental, etc) and
22 # add our black list (breakpad, skia and v8 are still not following
23 # google style and are not really living this repository).
24 # See presubmit_support.py InputApi.FilterSourceFile for the (simple) usage.
25 black_list = input_api.DEFAULT_BLACK_LIST + EXCLUDED_PATHS
26 sources = lambda x: input_api.FilterSourceFile(x, black_list=black_list)
27 results.extend(input_api.canned_checks.CheckLongLines(
28 input_api, output_api, sources))
29 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(
30 input_api, output_api, sources))
31 results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
32 input_api, output_api, sources))
33 results.extend(input_api.canned_checks.CheckChangeHasBugField(
34 input_api, output_api))
35 results.extend(input_api.canned_checks.CheckChangeHasTestField(
36 input_api, output_api))
37 results.extend(input_api.canned_checks.CheckChangeSvnEolStyle(
38 input_api, output_api, sources))
[email protected]40cdf8b32009-06-26 23:00:3739 results.extend(input_api.canned_checks.CheckSvnForCommonMimeTypes(
40 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:5441 return results
[email protected]ca8d1982009-02-19 16:33:1242
43
44def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:5445 results = []
[email protected]4306417642009-06-11 00:33:4046 black_list = input_api.DEFAULT_BLACK_LIST + EXCLUDED_PATHS
47 sources = lambda x: input_api.FilterSourceFile(x, black_list=black_list)
48 results.extend(input_api.canned_checks.CheckLongLines(
49 input_api, output_api, sources))
50 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(
51 input_api, output_api, sources))
52 results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
53 input_api, output_api, sources))
54 results.extend(input_api.canned_checks.CheckChangeHasBugField(
55 input_api, output_api))
56 results.extend(input_api.canned_checks.CheckChangeHasTestField(
57 input_api, output_api))
58 results.extend(input_api.canned_checks.CheckChangeSvnEolStyle(
59 input_api, output_api, sources))
[email protected]40cdf8b32009-06-26 23:00:3760 results.extend(input_api.canned_checks.CheckSvnForCommonMimeTypes(
61 input_api, output_api))
[email protected]dd805fe2009-10-01 08:11:5162 # TODO(thestig) temporarily disabled, doesn't work in third_party/
63 #results.extend(input_api.canned_checks.CheckSvnModifiedDirectories(
64 # input_api, output_api, sources))
[email protected]fe5f57c52009-06-05 14:25:5465 # Make sure the tree is 'open'.
[email protected]4306417642009-06-11 00:33:4066 # TODO(maruel): Run it in a separate thread to parallelize checks?
[email protected]7f238152009-08-12 19:00:3467 results.extend(CheckTreeIsOpen(
68 input_api,
69 output_api,
70 'http://chromium-status.appspot.com/status',
71 '0',
72 'http://chromium-status.appspot.com/current?format=raw'))
[email protected]70ac4982009-06-08 17:31:5173 results.extend(CheckTryJobExecution(input_api, output_api))
[email protected]7fa42f12009-11-09 20:54:1674 # These builders are just too slow.
75 IGNORED_BUILDERS = [
76 'Chromium XP',
77 'XP Unit (purify)',
78 'Modules XP (purify)',
79 'Webkit (purify)',
80 'Chromium Mac',
81 'Chromium Mac (valgrind)',
82 'Chromium Mac UI (valgrind)(1)',
83 'Chromium Mac UI (valgrind)(2)',
84 'Chromium Mac UI (valgrind)(3)',
85 'Chromium Mac (tsan)',
86 'Webkit Mac (valgrind)',
87 'Chromium Linux',
88 'Chromium Linux x64',
89 'Linux Tests (valgrind)(1)',
90 'Linux Tests (valgrind)(2)',
91 'Linux Tests (valgrind)(3)',
92 'Linux Tests (valgrind)(4)',
93 'Webkit Linux (valgrind layout)',
94 ]
95 results.extend(CheckPendingBuilds(
96 input_api,
97 output_api,
98 'http://build.chromium.org/buildbot/waterfall/json/builders',
99 6,
100 IGNORED_BUILDERS))
[email protected]fe5f57c52009-06-05 14:25:54101 return results
[email protected]ca8d1982009-02-19 16:33:12102
103
[email protected]70ac4982009-06-08 17:31:51104def CheckTryJobExecution(input_api, output_api):
[email protected]4306417642009-06-11 00:33:40105 outputs = []
106 if not input_api.change.issue or not input_api.change.patchset:
107 return outputs
[email protected]70ac4982009-06-08 17:31:51108 url = "http://codereview.chromium.org/%d/get_build_results/%d" % (
109 input_api.change.issue, input_api.change.patchset)
[email protected]7f238152009-08-12 19:00:34110 PLATFORMS = ('win', 'linux', 'mac')
[email protected]70ac4982009-06-08 17:31:51111 try:
112 connection = input_api.urllib2.urlopen(url)
113 # platform|status|url
114 values = [item.split('|', 2) for item in connection.read().splitlines()]
115 connection.close()
[email protected]71cdeb482009-09-18 18:55:03116 if not values:
117 # It returned an empty list. Probably a private review.
118 return outputs
[email protected]7f238152009-08-12 19:00:34119 # Reformat as an dict of platform: [status, url]
120 values = dict([[v[0], [v[1], v[2]]] for v in values])
121 for platform in PLATFORMS:
122 values.setdefault(platform, ['not started', ''])
[email protected]72303832009-07-10 19:09:08123 message = None
[email protected]7f238152009-08-12 19:00:34124 non_success = [k.upper() for k,v in values.iteritems() if v[0] != 'success']
125 if 'failure' in [v[0] for v in values.itervalues()]:
126 message = 'Try job failures on %s!\n' % ', '.join(non_success)
127 elif non_success:
128 message = ('Unfinished (or not even started) try jobs on '
129 '%s.\n') % ', '.join(non_success)
[email protected]72303832009-07-10 19:09:08130 if message:
131 message += (
132 'Is try server wrong or broken? Please notify [email protected]. '
133 'Thanks.\n')
[email protected]7f238152009-08-12 19:00:34134 outputs.append(output_api.PresubmitPromptWarning(message=message))
[email protected]70ac4982009-06-08 17:31:51135 except input_api.urllib2.HTTPError, e:
136 if e.code == 404:
137 # Fallback to no try job.
138 # TODO(maruel): Change to a PresubmitPromptWarning once the try server is
139 # stable enough and it seems to work fine.
140 outputs.append(output_api.PresubmitNotifyResult(
141 'You should try the patch first.'))
142 else:
143 # Another HTTP error happened, warn the user.
144 # TODO(maruel): Change to a PresubmitPromptWarning once it deemed to work
145 # fine.
146 outputs.append(output_api.PresubmitNotifyResult(
147 'Got %s while looking for try job status.' % str(e)))
148 return outputs
[email protected]04a39f7c2009-06-11 00:41:32149
150
151def CheckTreeIsOpen(input_api, output_api, url, closed, url_text):
152 """Similar to the one in presubmit_canned_checks except it shows an helpful
153 status text instead.
154 """
155 assert(input_api.is_committing)
156 try:
157 connection = input_api.urllib2.urlopen(url)
158 status = connection.read()
159 connection.close()
160 if input_api.re.match(closed, status):
161 long_text = status + '\n' + url
162 try:
163 connection = input_api.urllib2.urlopen(url_text)
[email protected]7f238152009-08-12 19:00:34164 long_text = connection.read().strip()
[email protected]04a39f7c2009-06-11 00:41:32165 connection.close()
[email protected]04a39f7c2009-06-11 00:41:32166 except IOError:
167 pass
[email protected]b3fbe1c2009-07-29 18:44:39168 return [output_api.PresubmitError("The tree is closed.",
169 long_text=long_text)]
[email protected]04a39f7c2009-06-11 00:41:32170 except IOError:
171 pass
172 return []
[email protected]5fa06292009-09-29 01:55:00173
174
[email protected]7fa42f12009-11-09 20:54:16175def CheckPendingBuilds(input_api, output_api, url, max_pendings, ignored):
176 try:
177 connection = input_api.urllib2.urlopen(url)
178 raw_data = connection.read()
179 connection.close()
180 try:
181 import simplejson
[email protected]9d660ad62009-11-09 21:21:47182 data = simplejson.loads(raw_data)
[email protected]7fa42f12009-11-09 20:54:16183 except ImportError:
184 # simplejson is much safer. But we should be just fine enough with that:
185 data = eval(raw_data.replace('null', 'None'))
186 out = []
187 for (builder_name, builder) in data.iteritems():
188 if builder_name in ignored:
189 continue
190 pending_builds_len = len(builder.get('pending_builds', []))
191 if pending_builds_len > max_pendings:
192 out.append('%s has %d build(s) pending' %
193 (builder_name, pending_builds_len))
194 if out:
195 return [output_api.PresubmitPromptWarning(
196 'Build(s) pending. It is suggested to wait that no more than %d '
197 'builds are pending.' % max_pendings,
198 long_text='\n'.join(out))]
199 except IOError:
200 # Silently pass.
201 pass
202 return []
203
204
[email protected]5fa06292009-09-29 01:55:00205def GetPreferredTrySlaves():
206 return ['win', 'linux', 'mac']