blob: cf6e869a126af6d5daad335baf5da93373b5352f [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371# Copyright (C) 2014 Google Inc. All rights reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions are
5# met:
6#
7# * Redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer.
9# * Redistributions in binary form must reproduce the above
10# copyright notice, this list of conditions and the following disclaimer
11# in the documentation and/or other materials provided with the
12# distribution.
13# * Neither the name of Google Inc. nor the names of its
14# contributors may be used to endorse or promote products derived from
15# this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Yang Guo75beda92019-10-28 07:29:2528"""
29DevTools presubmit script
Blink Reformat4c46d092018-04-07 15:32:3730
31See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
32for more details about the presubmit API built into gcl.
33"""
34
35import sys
Tim van der Lippef515fdc2020-03-06 16:18:2536import six
Tim van der Lippefb023462020-08-21 13:10:0637import time
Blink Reformat4c46d092018-04-07 15:32:3738
Alex Rudenko4a7a3242024-04-18 10:36:5039from pathlib import Path
40
Liviu Rauf3028602023-11-10 10:52:0441# Depot tools imports
42import rdb_wrapper
43
Liviu Raufd2e3212019-12-18 15:38:2044AUTOROLL_ACCOUNT = "devtools-ci-autoroll-builder@chops-service-accounts.iam.gserviceaccount.com"
Tim van der Lippefb1dc172021-05-11 15:40:2645USE_PYTHON3 = True
Mathias Bynensa0a6e292019-12-17 12:24:0846
Alex Rudenko537c6312024-07-19 06:22:0547
Tim van der Lippe4d004ec2020-03-03 18:32:0148def _ExecuteSubProcess(input_api, output_api, script_path, args, results):
Tim van der Lippef515fdc2020-03-06 16:18:2549 if isinstance(script_path, six.string_types):
Philip Pfaffef4320aa2022-07-21 11:33:2450 script_path = [input_api.python3_executable, script_path]
Tim van der Lippef515fdc2020-03-06 16:18:2551
Tim van der Lippefb023462020-08-21 13:10:0652 start_time = time.time()
Sigurd Schneiderf3a1ecd2021-03-02 14:46:0353 process = input_api.subprocess.Popen(script_path + args,
54 stdout=input_api.subprocess.PIPE,
55 stderr=input_api.subprocess.STDOUT)
Tim van der Lippe4d004ec2020-03-03 18:32:0156 out, _ = process.communicate()
Tim van der Lippefb023462020-08-21 13:10:0657 end_time = time.time()
58
59 time_difference = end_time - start_time
60 time_info = "Script execution time was %.1fs seconds\n" % (time_difference)
Tim van der Lippe4d004ec2020-03-03 18:32:0161 if process.returncode != 0:
Tim van der Lippefb1dc172021-05-11 15:40:2662 results.append(
63 output_api.PresubmitError(time_info + out.decode('utf-8')))
Tim van der Lippe4d004ec2020-03-03 18:32:0164 else:
Tim van der Lippefb1dc172021-05-11 15:40:2665 results.append(
66 output_api.PresubmitNotifyResult(time_info + out.decode('utf-8')))
Tim van der Lippe4d004ec2020-03-03 18:32:0167 return results
68
69
Sigurd Schneider5c9b4f92021-01-22 10:09:5570def _CheckBugAssociation(input_api, output_api, is_committing):
71 results = [output_api.PresubmitNotifyResult('Bug Association Check:')]
72 bugs = input_api.change.BugsFromDescription()
73 message = (
74 "Each CL should be associated with a bug, use \'Bug:\' or \'Fixed:\' lines in\n"
75 "the footer of the commit description. If you explicitly don\'t want to\n"
76 "set a bug, use \'Bug: none\' in the footer of the commit description.\n\n"
77 "Note: The footer of the commit description is the last block of lines in\n"
78 "the commit description that doesn't contain empty lines. This means that\n"
79 "any \'Bug:\' or \'Fixed:\' lines that are eventually followed by an empty\n"
80 "line are not detected by this presubmit check.")
81
82 if not bugs:
83 if is_committing:
84 results.append(output_api.PresubmitError(message))
85 else:
86 results.append(output_api.PresubmitNotifyResult(message))
87
88 for bug in bugs:
89 results.append(output_api.PresubmitNotifyResult(('%s') % bug))
90
91 return results
92
93
Brandon Goddard33104372020-08-13 15:49:2394def _CheckExperimentTelemetry(input_api, output_api):
Brandon Goddard33104372020-08-13 15:49:2395 experiment_telemetry_files = [
96 input_api.os_path.join(input_api.PresubmitLocalPath(), 'front_end',
Christy Chenab9a44d2021-07-02 19:54:3097 'entrypoints', 'main', 'MainImpl.ts'),
Brandon Goddard33104372020-08-13 15:49:2398 input_api.os_path.join(input_api.PresubmitLocalPath(), 'front_end',
Tim van der Lippee0247312021-04-01 14:25:3099 'core', 'host', 'UserMetrics.ts')
Brandon Goddard33104372020-08-13 15:49:23100 ]
101 affected_main_files = _getAffectedFiles(input_api,
102 experiment_telemetry_files, [],
Christy Chenab9a44d2021-07-02 19:54:30103 ['.ts'])
Brandon Goddard33104372020-08-13 15:49:23104 if len(affected_main_files) == 0:
Tim van der Lippefb023462020-08-21 13:10:06105 return [
106 output_api.PresubmitNotifyResult(
107 'No affected files for telemetry check')
108 ]
Brandon Goddard33104372020-08-13 15:49:23109
Tim van der Lippefb023462020-08-21 13:10:06110 results = [
111 output_api.PresubmitNotifyResult('Running Experiment Telemetry check:')
112 ]
Brandon Goddard33104372020-08-13 15:49:23113 script_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
114 'scripts', 'check_experiments.js')
115 results.extend(_checkWithNodeScript(input_api, output_api, script_path))
116 return results
117
118
Jack Franklinb5a63092022-11-30 14:32:36119def _CheckESBuildVersion(input_api, output_api):
120 results = [
121 output_api.PresubmitNotifyResult('Running ESBuild version check:')
122 ]
123 script_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
124 'scripts',
125 'check_esbuild_versions.js')
126 results.extend(_checkWithNodeScript(input_api, output_api, script_path))
127 return results
128
129
Wolfgang Beyere57322c2024-02-08 12:04:24130def _CheckEnumeratedHistograms(input_api, output_api):
131 enumerated_histograms_files = [
132 input_api.os_path.join(input_api.PresubmitLocalPath(), 'front_end',
133 'devtools_compatibility.js'),
134 input_api.os_path.join(input_api.PresubmitLocalPath(), 'front_end',
135 'core', 'host', 'InspectorFrontendHostAPI.ts')
136 ]
137 affected_main_files = _getAffectedFiles(input_api,
138 enumerated_histograms_files, [],
139 ['.js', '.ts'])
140 if len(affected_main_files) == 0:
141 return [
142 output_api.PresubmitNotifyResult(
143 'No affected files for UMA Enumerated Histograms check')
144 ]
145
146 results = [
147 output_api.PresubmitNotifyResult(
148 'Running UMA Enumerated Histograms check:')
149 ]
150 script_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
151 'scripts',
152 'check_enumerated_histograms.js')
153 results.extend(_checkWithNodeScript(input_api, output_api, script_path))
154 return results
155
156
Blink Reformat4c46d092018-04-07 15:32:37157def _CheckFormat(input_api, output_api):
Simon Zündcc994132024-02-15 07:34:44158 files_with_potential_large_diffs = _getAffectedFiles(
159 input_api, [
160 input_api.os_path.join(input_api.PresubmitLocalPath(),
161 'node_modules'),
162 input_api.os_path.join(input_api.PresubmitLocalPath(), 'front_end',
163 'third_party'),
164 input_api.os_path.join(input_api.PresubmitLocalPath(), 'front_end',
165 'generated'),
166 input_api.os_path.join(input_api.PresubmitLocalPath(), 'front_end',
167 'models', 'javascript_metadata'),
168 ], [], [])
Tim van der Lippefdbd42e2020-04-07 14:14:36169
Simon Zündcc994132024-02-15 07:34:44170 # Changes to the above directories can produce large diffs. This is a problem on Windows,
171 # where clang-format-diff.py specifies all the diff ranges on the command line when invoking
172 # clang-format. Since command line length is limited on Win, the invocation fails.
173 # As a heuristic, we'll format all touched files fully if we suspect that the diff could
174 # be large.
Tim van der Lippefdbd42e2020-04-07 14:14:36175 # TODO(crbug.com/1068198): Remove once `git cl format --js` can handle large CLs.
Simon Zündcc994132024-02-15 07:34:44176 additional_args = []
177 if (len(files_with_potential_large_diffs) > 0):
178 additional_args = ['--full']
Tim van der Lippefdbd42e2020-04-07 14:14:36179
Brandon Goddarde7028672020-01-30 17:31:04180 results = [output_api.PresubmitNotifyResult('Running Format Checks:')]
Blink Reformat4c46d092018-04-07 15:32:37181
Simon Zündcc994132024-02-15 07:34:44182 return _ExecuteSubProcess(input_api, output_api,
183 ['git', 'cl', 'format', '--js'] +
184 additional_args, [], results)
Blink Reformat4c46d092018-04-07 15:32:37185
Jack Franklin1aa212d2021-09-10 14:20:08186
187def _CheckDevToolsRunESLintTests(input_api, output_api):
188 # Check for changes in the eslint_rules directory, and run the eslint rules
189 # tests if so.
190 # We don't do this on every CL as most do not touch the rules, but if we do
191 # change them we need to make sure all the tests are passing.
Jack Franklin03db63a2021-09-16 13:40:56192 original_sys_path = sys.path
193 try:
194 sys.path = sys.path + [
195 input_api.os_path.join(input_api.PresubmitLocalPath(), 'scripts')
196 ]
197 import devtools_paths
198 finally:
199 sys.path = original_sys_path
Jack Franklin1aa212d2021-09-10 14:20:08200 eslint_rules_dir_path = input_api.os_path.join(
201 input_api.PresubmitLocalPath(), 'scripts', 'eslint_rules')
202 eslint_rules_affected_files = _getAffectedFiles(input_api,
203 [eslint_rules_dir_path],
204 [], [])
205
206 if (len(eslint_rules_affected_files) == 0):
207 return []
208
Jack Franklin03db63a2021-09-16 13:40:56209 mocha_path = devtools_paths.mocha_path()
Jack Franklin1aa212d2021-09-10 14:20:08210 eslint_tests_path = input_api.os_path.join(eslint_rules_dir_path, 'tests',
211 '*_test.js')
212
213 results = [output_api.PresubmitNotifyResult('ESLint rules unit tests')]
214 results.extend(
215 # The dot reporter is more concise which is useful to not get LOADS of
216 # output when just one test fails.
217 _checkWithNodeScript(input_api, output_api, mocha_path,
218 ['--reporter', 'dot', eslint_tests_path]))
219 return results
220
221
Tim van der Lippe800d8752022-02-04 12:49:56222def _CheckDevToolsRunBuildTests(input_api, output_api):
223 # Check for changes in the build/tests directory, and run the tests if so.
224 # We don't do this on every CL as most do not touch the rules, but if we do
225 # change them we need to make sure all the tests are passing.
226 original_sys_path = sys.path
227 try:
228 sys.path = sys.path + [
229 input_api.os_path.join(input_api.PresubmitLocalPath(), 'scripts')
230 ]
231 import devtools_paths
232 finally:
233 sys.path = original_sys_path
234 scripts_build_dir_path = input_api.os_path.join(
235 input_api.PresubmitLocalPath(), 'scripts', 'build')
236 scripts_build_affected_files = _getAffectedFiles(input_api,
237 [scripts_build_dir_path],
238 [], [])
239
240 if len(scripts_build_affected_files) == 0:
241 return []
242
243 mocha_path = devtools_paths.mocha_path()
244 build_tests_path = input_api.os_path.join(scripts_build_dir_path, 'tests',
245 '*_test.js')
246
247 results = [output_api.PresubmitNotifyResult('Build plugins unit tests')]
248 results.extend(
249 # The dot reporter is more concise which is useful to not get LOADS of
250 # output when just one test fails.
251 _checkWithNodeScript(input_api, output_api, mocha_path,
252 ['--reporter', 'dot', build_tests_path]))
253 return results
254
255
Mathias Bynens1b2c5e42020-06-18 06:29:21256def _CheckDevToolsStyleJS(input_api, output_api):
Tim van der Lippefb023462020-08-21 13:10:06257 results = [output_api.PresubmitNotifyResult('JS style check:')]
Mathias Bynens1b2c5e42020-06-18 06:29:21258 lint_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
259 'scripts', 'test',
Tim van der Lippef9e565e2021-11-08 16:22:11260 'run_lint_check_js.mjs')
Tim van der Lippe4d004ec2020-03-03 18:32:01261
Mathias Bynens1b2c5e42020-06-18 06:29:21262 front_end_directory = input_api.os_path.join(
263 input_api.PresubmitLocalPath(), 'front_end')
Jack Franklinbcfd6ad2021-02-17 10:12:50264 component_docs_directory = input_api.os_path.join(front_end_directory,
Tim van der Lippee622f552021-04-14 14:15:18265 'ui', 'components',
266 'docs')
Alex Rudenko5556a902020-09-29 09:37:23267 inspector_overlay_directory = input_api.os_path.join(
268 input_api.PresubmitLocalPath(), 'inspector_overlay')
Mathias Bynens1b2c5e42020-06-18 06:29:21269 test_directory = input_api.os_path.join(input_api.PresubmitLocalPath(),
270 'test')
271 scripts_directory = input_api.os_path.join(input_api.PresubmitLocalPath(),
272 'scripts')
Tim van der Lippe2a4ae2b2020-03-11 17:28:06273
Mathias Bynens1b2c5e42020-06-18 06:29:21274 default_linted_directories = [
Alex Rudenko5556a902020-09-29 09:37:23275 front_end_directory, test_directory, scripts_directory,
276 inspector_overlay_directory
Mathias Bynens1b2c5e42020-06-18 06:29:21277 ]
Tim van der Lippe2a4ae2b2020-03-11 17:28:06278
279 eslint_related_files = [
Mathias Bynens1b2c5e42020-06-18 06:29:21280 input_api.os_path.join(input_api.PresubmitLocalPath(), 'node_modules',
281 'eslint'),
Tim van der Lippecf4ab402021-02-12 14:30:58282 input_api.os_path.join(input_api.PresubmitLocalPath(), 'node_modules',
283 '@typescript-eslint'),
Tim van der Lippe2a4ae2b2020-03-11 17:28:06284 input_api.os_path.join(input_api.PresubmitLocalPath(), '.eslintrc.js'),
Mathias Bynens1b2c5e42020-06-18 06:29:21285 input_api.os_path.join(input_api.PresubmitLocalPath(),
286 '.eslintignore'),
Tim van der Lippe33543ac2020-12-14 14:37:45287 input_api.os_path.join(front_end_directory, '.eslintrc.js'),
Jack Franklinbcfd6ad2021-02-17 10:12:50288 input_api.os_path.join(component_docs_directory, '.eslintrc.js'),
Tim van der Lippe406249f2020-12-14 14:59:10289 input_api.os_path.join(test_directory, '.eslintrc.js'),
Mathias Bynens1b2c5e42020-06-18 06:29:21290 input_api.os_path.join(scripts_directory, 'test',
291 'run_lint_check_js.py'),
292 input_api.os_path.join(scripts_directory, 'test',
Tim van der Lippef9e565e2021-11-08 16:22:11293 'run_lint_check_js.mjs'),
Tim van der Lippe2a4ae2b2020-03-11 17:28:06294 input_api.os_path.join(scripts_directory, '.eslintrc.js'),
295 input_api.os_path.join(scripts_directory, 'eslint_rules'),
296 ]
297
Mathias Bynens1b2c5e42020-06-18 06:29:21298 lint_config_files = _getAffectedFiles(input_api, eslint_related_files, [],
299 ['.js', '.py', '.eslintignore'])
Tim van der Lippe2a4ae2b2020-03-11 17:28:06300
Mathias Bynens0ec56612020-06-19 07:14:03301 should_bail_out, files_to_lint = _getFilesToLint(
302 input_api, output_api, lint_config_files, default_linted_directories,
303 ['.js', '.ts'], results)
304 if should_bail_out:
Mathias Bynens1b2c5e42020-06-18 06:29:21305 return results
Tim van der Lippe2a4ae2b2020-03-11 17:28:06306
Brandon Goddarde34e94f2021-04-12 17:58:26307 # If there are more than 50 files to check, don't bother and check
308 # everything, so as to not run into command line length limits on Windows.
309 if len(files_to_lint) > 50:
310 files_to_lint = []
311
Mathias Bynens1b2c5e42020-06-18 06:29:21312 results.extend(
313 _checkWithNodeScript(input_api, output_api, lint_path, files_to_lint))
Tim van der Lippe98132242020-04-14 16:16:54314 return results
Blink Reformat4c46d092018-04-07 15:32:37315
316
Mathias Bynens1b2c5e42020-06-18 06:29:21317def _CheckDevToolsStyleCSS(input_api, output_api):
Tim van der Lippefb023462020-08-21 13:10:06318 results = [output_api.PresubmitNotifyResult('CSS style check:')]
Mathias Bynens1b2c5e42020-06-18 06:29:21319 lint_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
320 'scripts', 'test',
Jack Franklinbc302342021-01-18 10:03:30321 'run_lint_check_css.js')
Mathias Bynens1b2c5e42020-06-18 06:29:21322
323 front_end_directory = input_api.os_path.join(
324 input_api.PresubmitLocalPath(), 'front_end')
Alex Rudenko5556a902020-09-29 09:37:23325 inspector_overlay_directory = input_api.os_path.join(
326 input_api.PresubmitLocalPath(), 'inspector_overlay')
327 default_linted_directories = [
328 front_end_directory, inspector_overlay_directory
329 ]
Mathias Bynens1b2c5e42020-06-18 06:29:21330
331 scripts_directory = input_api.os_path.join(input_api.PresubmitLocalPath(),
332 'scripts')
333
334 stylelint_related_files = [
335 input_api.os_path.join(input_api.PresubmitLocalPath(), 'node_modules',
336 'stylelint'),
337 input_api.os_path.join(input_api.PresubmitLocalPath(),
338 '.stylelintrc.json'),
339 input_api.os_path.join(input_api.PresubmitLocalPath(),
340 '.stylelintignore'),
341 input_api.os_path.join(scripts_directory, 'test',
Sigurd Schneider6523c512021-02-12 09:44:28342 'run_lint_check_css.js'),
Mathias Bynens1b2c5e42020-06-18 06:29:21343 ]
344
345 lint_config_files = _getAffectedFiles(input_api, stylelint_related_files,
Sigurd Schneider6523c512021-02-12 09:44:28346 [], [])
Mathias Bynens1b2c5e42020-06-18 06:29:21347
Sigurd Schneidere3bf6c22021-02-11 14:35:23348 css_should_bail_out, css_files_to_lint = _getFilesToLint(
Mathias Bynens0ec56612020-06-19 07:14:03349 input_api, output_api, lint_config_files, default_linted_directories,
350 ['.css'], results)
Mathias Bynens1b2c5e42020-06-18 06:29:21351
Sigurd Schneiderf3a1ecd2021-03-02 14:46:03352 # If there are more than 50 files to check, don't bother and check
353 # everything, so as to not run into command line length limits on Windows.
354 if not css_should_bail_out:
355 if len(css_files_to_lint) < 50:
356 script_args = ["--files"] + css_files_to_lint
357 else:
358 script_args = [] # The defaults check all CSS files.
359 results.extend(
360 _checkWithNodeScript(input_api, output_api, lint_path,
361 script_args))
362
Jack Franklinbc302342021-01-18 10:03:30363 return results
Mathias Bynens1b2c5e42020-06-18 06:29:21364
365
Tim van der Lippea53672d2021-07-08 14:52:35366def _CheckDevToolsNonJSFileLicenseHeaders(input_api, output_api):
Tim van der Lippe81752502021-05-26 14:38:12367 results = [
368 output_api.PresubmitNotifyResult(
369 'Python-like file license header check:')
370 ]
Tim van der Lippea53672d2021-07-08 14:52:35371 lint_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
372 'scripts', 'test',
373 'run_header_check_non_js_files.js')
Tim van der Lippe81752502021-05-26 14:38:12374
375 front_end_directory = input_api.os_path.join(
376 input_api.PresubmitLocalPath(), 'front_end')
377 inspector_overlay_directory = input_api.os_path.join(
378 input_api.PresubmitLocalPath(), 'inspector_overlay')
379 test_directory = input_api.os_path.join(input_api.PresubmitLocalPath(),
380 'test')
381 scripts_directory = input_api.os_path.join(input_api.PresubmitLocalPath(),
382 'scripts')
Tim van der Lippe8b929542021-05-26 14:54:20383 config_directory = input_api.os_path.join(input_api.PresubmitLocalPath(),
384 'config')
Tim van der Lippe81752502021-05-26 14:38:12385
386 default_linted_directories = [
387 front_end_directory, test_directory, scripts_directory,
Tim van der Lippe8b929542021-05-26 14:54:20388 inspector_overlay_directory, config_directory
Tim van der Lippe81752502021-05-26 14:38:12389 ]
390
391 check_related_files = [lint_path]
392
393 lint_config_files = _getAffectedFiles(input_api, check_related_files, [],
394 ['.js'])
395
396 should_bail_out, files_to_lint = _getFilesToLint(
397 input_api, output_api, lint_config_files, default_linted_directories,
Tim van der Lippea53672d2021-07-08 14:52:35398 ['BUILD.gn', '.gni', '.css'], results)
Tim van der Lippe81752502021-05-26 14:38:12399 if should_bail_out:
400 return results
401
402 # If there are more than 50 files to check, don't bother and check
403 # everything, so as to not run into command line length limits on Windows.
404 if len(files_to_lint) > 50:
405 files_to_lint = []
406
407 results.extend(
408 _checkWithNodeScript(input_api, output_api, lint_path, files_to_lint))
409 return results
410
411
Tim van der Lippe4d004ec2020-03-03 18:32:01412def _CheckGeneratedFiles(input_api, output_api):
Alex Rudenko537c6312024-07-19 06:22:05413 v8_directory_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
414 'v8')
415 blink_directory_path = input_api.os_path.join(
416 input_api.PresubmitLocalPath(), 'third_party', 'blink')
417 protocol_location = input_api.os_path.join(blink_directory_path, 'public',
418 'devtools_protocol')
419 scripts_build_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
420 'scripts', 'build')
421 scripts_generated_output_path = input_api.os_path.join(
422 input_api.PresubmitLocalPath(), 'front_end', 'generated')
Tim van der Lippeb3b90762020-03-04 15:21:52423
Alex Rudenko537c6312024-07-19 06:22:05424 generated_aria_path = input_api.os_path.join(scripts_build_path,
425 'generate_aria.py')
426 generated_supported_css_path = input_api.os_path.join(
427 scripts_build_path, 'generate_supported_css.py')
Simon Zünd2ce67542023-02-07 10:15:14428 generated_deprecation_path = input_api.os_path.join(
429 scripts_build_path, 'generate_deprecations.py')
Alex Rudenko537c6312024-07-19 06:22:05430 generated_protocol_path = input_api.os_path.join(
431 scripts_build_path, 'code_generator_frontend.py')
Tim van der Lippe2a1eac22021-05-13 15:19:29432 generated_protocol_typescript_path = input_api.os_path.join(
433 input_api.PresubmitLocalPath(), 'scripts', 'protocol_typescript')
Alex Rudenko537c6312024-07-19 06:22:05434 concatenate_protocols_path = input_api.os_path.join(
435 input_api.PresubmitLocalPath(), 'third_party', 'inspector_protocol',
436 'concatenate_protocols.py')
Tim van der Lippeb3b90762020-03-04 15:21:52437
438 affected_files = _getAffectedFiles(input_api, [
439 v8_directory_path,
440 blink_directory_path,
Tim van der Lippe2a1eac22021-05-13 15:19:29441 input_api.os_path.join(input_api.PresubmitLocalPath(), 'third_party',
442 'pyjson5'),
Tim van der Lippeb3b90762020-03-04 15:21:52443 generated_aria_path,
444 generated_supported_css_path,
Simon Zünd2ce67542023-02-07 10:15:14445 generated_deprecation_path,
Tim van der Lippeb3b90762020-03-04 15:21:52446 concatenate_protocols_path,
447 generated_protocol_path,
Tim van der Lippe5d2d79b2020-03-23 11:45:04448 scripts_generated_output_path,
Tim van der Lippe2a1eac22021-05-13 15:19:29449 generated_protocol_typescript_path,
450 ], [], ['.pdl', '.json5', '.py', '.js', '.ts'])
Tim van der Lippeb3b90762020-03-04 15:21:52451
452 if len(affected_files) == 0:
Tim van der Lippefb023462020-08-21 13:10:06453 return [
454 output_api.PresubmitNotifyResult(
455 'No affected files for generated files check')
456 ]
Tim van der Lippeb3b90762020-03-04 15:21:52457
Alex Rudenko537c6312024-07-19 06:22:05458 results = [
459 output_api.PresubmitNotifyResult('Running Generated Files Check:')
460 ]
461 generate_protocol_resources_path = input_api.os_path.join(
462 input_api.PresubmitLocalPath(), 'scripts', 'deps',
463 'generate_protocol_resources.py')
Tim van der Lippe4d004ec2020-03-03 18:32:01464
Alex Rudenko537c6312024-07-19 06:22:05465 return _ExecuteSubProcess(input_api, output_api,
466 generate_protocol_resources_path, [], results)
Tim van der Lippe4d004ec2020-03-03 18:32:01467
468
Simon Zünd9ff4da62022-11-22 09:25:59469def _CheckL10nStrings(input_api, output_api):
Christy Chen2d6d9a62020-09-22 16:04:09470 devtools_root = input_api.PresubmitLocalPath()
471 devtools_front_end = input_api.os_path.join(devtools_root, 'front_end')
Tim van der Lippe25f11082021-06-24 15:28:08472 script_path = input_api.os_path.join(devtools_root, 'third_party', 'i18n',
Simon Zünd9ff4da62022-11-22 09:25:59473 'check-strings.js')
Tim van der Lippe25f11082021-06-24 15:28:08474 affected_front_end_files = _getAffectedFiles(
475 input_api, [devtools_front_end, script_path], [], ['.js', '.ts'])
Christy Chen2d6d9a62020-09-22 16:04:09476 if len(affected_front_end_files) == 0:
477 return [
478 output_api.PresubmitNotifyResult(
Simon Zünd9ff4da62022-11-22 09:25:59479 'No affected files to run check-strings')
Christy Chen2d6d9a62020-09-22 16:04:09480 ]
481
482 results = [
Simon Zünd9ff4da62022-11-22 09:25:59483 output_api.PresubmitNotifyResult('Checking UI strings from front_end:')
Christy Chen2d6d9a62020-09-22 16:04:09484 ]
Tim van der Lippe25f11082021-06-24 15:28:08485 results.extend(
486 _checkWithNodeScript(input_api, output_api, script_path,
487 [devtools_front_end]))
Christy Chen2d6d9a62020-09-22 16:04:09488 return results
489
490
Tim van der Lippe5279f842020-01-14 16:26:38491def _CheckNoUncheckedFiles(input_api, output_api):
492 results = []
493 process = input_api.subprocess.Popen(['git', 'diff', '--exit-code'],
494 stdout=input_api.subprocess.PIPE,
495 stderr=input_api.subprocess.STDOUT)
496 out, _ = process.communicate()
497 if process.returncode != 0:
Jack Franklin324f3042020-09-03 10:28:29498 files_changed_process = input_api.subprocess.Popen(
Tim van der Lippe25f11082021-06-24 15:28:08499 ['git', 'diff'],
Jack Franklin324f3042020-09-03 10:28:29500 stdout=input_api.subprocess.PIPE,
501 stderr=input_api.subprocess.STDOUT)
Tim van der Lippe9bb1cf62020-03-06 16:17:02502 files_changed, _ = files_changed_process.communicate()
503
504 return [
Tim van der Lippefb1dc172021-05-11 15:40:26505 output_api.PresubmitError(
506 'You have changed files that need to be committed:'),
507 output_api.PresubmitError(files_changed.decode('utf-8'))
Tim van der Lippe9bb1cf62020-03-06 16:17:02508 ]
Tim van der Lippe5279f842020-01-14 16:26:38509 return []
510
Alex Rudenko537c6312024-07-19 06:22:05511
Tim van der Lippe8fdda112020-01-27 11:27:06512def _CheckForTooLargeFiles(input_api, output_api):
Christy Chen1ab87e02020-01-31 00:32:16513 """Avoid large files, especially binary files, in the repository since
Tim van der Lippe8fdda112020-01-27 11:27:06514 git doesn't scale well for those. They will be in everyone's repo
515 clones forever, forever making Chromium slower to clone and work
516 with."""
Christy Chen1ab87e02020-01-31 00:32:16517 # Uploading files to cloud storage is not trivial so we don't want
518 # to set the limit too low, but the upper limit for "normal" large
519 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
520 # anything over 20 MB is exceptional.
521 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
522 too_large_files = []
523 for f in input_api.AffectedFiles():
524 # Check both added and modified files (but not deleted files).
525 if f.Action() in ('A', 'M'):
526 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
527 if size > TOO_LARGE_FILE_SIZE_LIMIT:
528 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
529 if too_large_files:
530 message = (
Alex Rudenko537c6312024-07-19 06:22:05531 'Do not commit large files to git since git scales badly for those.\n'
532 +
533 'Instead put the large files in cloud storage and use DEPS to\n' +
534 'fetch them.\n' + '\n'.join(too_large_files))
535 return [
536 output_api.PresubmitError('Too large files found in commit',
537 long_text=message + '\n')
538 ]
Christy Chen1ab87e02020-01-31 00:32:16539 else:
540 return []
Tim van der Lippe8fdda112020-01-27 11:27:06541
Tim van der Lippe5279f842020-01-14 16:26:38542
Andrés Olivares205bf682023-02-01 10:47:13543def _CheckObsoleteScreenshotGoldens(input_api, output_api):
544 results = [
545 output_api.PresubmitNotifyResult('Obsolete screenshot images check')
546 ]
547 interaction_test_root_path = input_api.os_path.join(
548 input_api.PresubmitLocalPath(), 'test', 'interactions')
549 interaction_test_files = [interaction_test_root_path]
550
551 interaction_test_files_changed = _getAffectedFiles(input_api,
552 interaction_test_files,
553 [], [])
554
555 if len(interaction_test_files_changed) > 0:
556 script_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
557 'scripts', 'test',
558 'check_obsolete_goldens.js')
Andrés Olivares205bf682023-02-01 10:47:13559
Philip Pfaffece5afc02024-04-09 13:08:58560 script_args = []
Andrés Olivares205bf682023-02-01 10:47:13561 errors_from_script = _checkWithNodeScript(input_api, output_api,
562 script_path, script_args)
563 results.extend(errors_from_script)
564
565 return results
566
567
Liviu Rauf3028602023-11-10 10:52:04568def _WithArgs(checkType, **kwargs):
Alex Rudenko537c6312024-07-19 06:22:05569
Liviu Rauf3028602023-11-10 10:52:04570 def _WithArgsWrapper(input_api, output_api):
571 return checkType(input_api, output_api, **kwargs)
572
573 _WithArgsWrapper.__name__ = checkType.__name__
574 return _WithArgsWrapper
Tim van der Lippef8a87092020-09-14 12:01:18575
576
Liviu Rauf3028602023-11-10 10:52:04577def _CannedChecks(canned_checks):
578 return [
579 canned_checks.CheckForCommitObjects,
580 canned_checks.CheckOwnersFormat,
581 canned_checks.CheckOwners,
582 canned_checks.CheckChangeHasNoCrAndHasOnlyOneEol,
583 _WithArgs(canned_checks.CheckChangeHasNoStrayWhitespace,
584 source_file_filter=lambda file: not file.LocalPath().
585 startswith('node_modules')),
586 canned_checks.CheckGenderNeutral,
Jack Franklin6bc1cbd2024-07-09 10:44:09587 canned_checks.CheckDoNotSubmitInFiles,
Liviu Rauf3028602023-11-10 10:52:04588 ]
Jack Franklinb10193f2021-03-19 10:25:08589
Liviu Rauf3028602023-11-10 10:52:04590
591def _CommonChecks(canned_checks):
592 local_checks = [
593 _WithArgs(canned_checks.CheckAuthorizedAuthor,
594 bot_allowlist=[AUTOROLL_ACCOUNT]), _CheckExperimentTelemetry,
595 _CheckGeneratedFiles, _CheckDevToolsStyleJS, _CheckDevToolsStyleCSS,
596 _CheckDevToolsRunESLintTests, _CheckDevToolsRunBuildTests,
597 _CheckDevToolsNonJSFileLicenseHeaders, _CheckFormat,
Wolfgang Beyere57322c2024-02-08 12:04:24598 _CheckESBuildVersion, _CheckEnumeratedHistograms,
Alex Rudenko4a7a3242024-04-18 10:36:50599 _CheckObsoleteScreenshotGoldens, _CheckNodeModules
Liviu Rauf3028602023-11-10 10:52:04600 ]
Tim van der Lippef8a87092020-09-14 12:01:18601 # Run the canned checks from `depot_tools` after the custom DevTools checks.
602 # The canned checks for example check that lines have line endings. The
603 # DevTools presubmit checks automatically fix these issues. If we would run
604 # the canned checks before the DevTools checks, they would erroneously conclude
605 # that there are issues in the code. Since the canned checks are allowed to be
606 # ignored, a confusing message is shown that asks if the failed presubmit can
607 # be continued regardless. By fixing the issues before we reach the canned checks,
608 # we don't show the message to suppress these errors, which would otherwise be
609 # causing CQ to fail.
Liviu Rauf3028602023-11-10 10:52:04610 return local_checks + _CannedChecks(canned_checks)
Kalon Hindsd44fddf2020-12-10 13:43:25611
612
613def _SideEffectChecks(input_api, output_api):
614 """Check side effects caused by other checks"""
615 results = []
Tim van der Lippe5279f842020-01-14 16:26:38616 results.extend(_CheckNoUncheckedFiles(input_api, output_api))
Tim van der Lippe8fdda112020-01-27 11:27:06617 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Blink Reformat4c46d092018-04-07 15:32:37618 return results
619
620
Liviu Rauf3028602023-11-10 10:52:04621def _RunAllChecks(checks, input_api, output_api):
622 with rdb_wrapper.client("presubmit:") as sink:
623 results = []
624 for check in checks:
625 start_time = time.time()
626
627 result = check(input_api, output_api)
628
629 elapsed_time = time.time() - start_time
630 results.extend(result)
631
632 if not sink:
633 continue
634 failure_reason = None
635 status = rdb_wrapper.STATUS_PASS
636 if any(r.fatal for r in result):
637 status = rdb_wrapper.STATUS_FAIL
638 failure_reasons = []
639 for r in result:
640 fields = r.json_format()
641 message = fields['message']
642 items = '\n'.join(' %s' % item
643 for item in fields['items'])
644 failure_reasons.append('\n'.join([message, items]))
645 if failure_reasons:
646 failure_reason = '\n'.join(failure_reasons)
647 sink.report(check.__name__, status, elapsed_time, failure_reason)
648
649 return results
650
651
Liviu Raud614e092020-01-08 09:56:33652def CheckChangeOnUpload(input_api, output_api):
Liviu Rauf3028602023-11-10 10:52:04653 checks = _CommonChecks(input_api.canned_checks) + [
654 _CheckL10nStrings,
655 # Run checks that rely on output from other DevTool checks
656 _SideEffectChecks,
657 _WithArgs(_CheckBugAssociation, is_committing=False),
658 ]
Riley Wongf0be6ec2024-05-21 20:12:54659 # Remove check for git once initworkspace is supported in internal repositories
660 # in Cider. We need this because the subsequent checks will rely on a
661 # node hook generated by gclient sync.
662 # TODO(rgw): Remove below check once glcient sync is supported.
663 if input_api.change.scm != 'git':
664 return [
665 output_api.PresubmitNotifyResult(
666 'Non-git workspace detected, skipping CheckChangeOnUpload.' +
667 'Remove this check once glcient is supported in internal repositories in Cider.'
668 )
669 ]
Liviu Rauf3028602023-11-10 10:52:04670 return _RunAllChecks(checks, input_api, output_api)
Liviu Raud614e092020-01-08 09:56:33671
672
Blink Reformat4c46d092018-04-07 15:32:37673def CheckChangeOnCommit(input_api, output_api):
Liviu Rauf3028602023-11-10 10:52:04674 checks = _CommonChecks(input_api.canned_checks) + [
675 _CheckL10nStrings,
676 # Run checks that rely on output from other DevTool checks
677 _SideEffectChecks,
678 input_api.canned_checks.CheckChangeHasDescription,
679 _WithArgs(_CheckBugAssociation, is_committing=True),
680 ]
681 return _RunAllChecks(checks, input_api, output_api)
Blink Reformat4c46d092018-04-07 15:32:37682
683
Alex Rudenko537c6312024-07-19 06:22:05684def _getAffectedFiles(input_api, parent_directories, excluded_actions,
685 accepted_endings): # pylint: disable=invalid-name
Yang Guo75beda92019-10-28 07:29:25686 """Return absolute file paths of affected files (not due to an excluded action)
Mandy Chena6be46a2019-07-09 17:06:27687 under a parent directory with an accepted file ending.
Yang Guo75beda92019-10-28 07:29:25688 """
Mandy Chena6be46a2019-07-09 17:06:27689 local_paths = [
Alex Rudenko537c6312024-07-19 06:22:05690 f.AbsoluteLocalPath() for f in input_api.AffectedFiles()
691 if all(f.Action() != action for action in excluded_actions)
Mandy Chena6be46a2019-07-09 17:06:27692 ]
693 affected_files = [
Tim van der Lippefb1dc172021-05-11 15:40:26694 file_name for file_name in local_paths
695 if any(parent_directory in file_name
696 for parent_directory in parent_directories) and (
697 len(accepted_endings) == 0 or any(
698 file_name.endswith(accepted_ending)
699 for accepted_ending in accepted_endings))
Mandy Chena6be46a2019-07-09 17:06:27700 ]
701 return affected_files
702
703
Alex Rudenko537c6312024-07-19 06:22:05704def _checkWithNodeScript(input_api,
705 output_api,
706 script_path,
707 script_arguments=[]): # pylint: disable=invalid-name
Blink Reformat4c46d092018-04-07 15:32:37708 original_sys_path = sys.path
709 try:
Alex Rudenko537c6312024-07-19 06:22:05710 sys.path = sys.path + [
711 input_api.os_path.join(input_api.PresubmitLocalPath(), 'scripts')
712 ]
Yang Guod8176982019-10-04 20:30:35713 import devtools_paths
Blink Reformat4c46d092018-04-07 15:32:37714 finally:
715 sys.path = original_sys_path
716
Alex Rudenko537c6312024-07-19 06:22:05717 return _ExecuteSubProcess(input_api, output_api,
718 [devtools_paths.node_path(), script_path],
719 script_arguments, [])
Mathias Bynens1b2c5e42020-06-18 06:29:21720
721
722def _getFilesToLint(input_api, output_api, lint_config_files,
723 default_linted_directories, accepted_endings, results):
Mathias Bynens0ec56612020-06-19 07:14:03724 run_full_check = False
Mathias Bynens1b2c5e42020-06-18 06:29:21725 files_to_lint = []
726
727 # We are changing the lint configuration; run the full check.
Tim van der Lippefb1dc172021-05-11 15:40:26728 if len(lint_config_files) != 0:
Mathias Bynens1b2c5e42020-06-18 06:29:21729 results.append(
730 output_api.PresubmitNotifyResult('Running full lint check'))
Mathias Bynens0ec56612020-06-19 07:14:03731 run_full_check = True
Mathias Bynens1b2c5e42020-06-18 06:29:21732 else:
733 # Only run the linter on files that are relevant, to save PRESUBMIT time.
734 files_to_lint = _getAffectedFiles(input_api,
735 default_linted_directories, ['D'],
736 accepted_endings)
737
Jack Franklin130d2ae2022-07-12 09:51:26738 # Exclude front_end/third_party and front_end/generated files.
Tim van der Lippefb1dc172021-05-11 15:40:26739 files_to_lint = [
Jack Franklin130d2ae2022-07-12 09:51:26740 file for file in files_to_lint
741 if "third_party" not in file or "generated" not in file
Tim van der Lippefb1dc172021-05-11 15:40:26742 ]
Paul Lewis2b9224f2020-09-08 17:13:10743
Tim van der Lippefb1dc172021-05-11 15:40:26744 if len(files_to_lint) == 0:
Mathias Bynens1b2c5e42020-06-18 06:29:21745 results.append(
746 output_api.PresubmitNotifyResult(
747 'No affected files for lint check'))
748
Tim van der Lippefb1dc172021-05-11 15:40:26749 should_bail_out = len(files_to_lint) == 0 and not run_full_check
Mathias Bynens0ec56612020-06-19 07:14:03750 return should_bail_out, files_to_lint
Alex Rudenko4a7a3242024-04-18 10:36:50751
752
753def _CheckNodeModules(input_api, output_api):
754
755 files = ['.clang-format', 'OWNERS', 'README.chromium']
756
757 results = []
758 for file in files:
759 file_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
760 'node_modules', file)
761 if not Path(file_path).is_file():
Alex Rudenko537c6312024-07-19 06:22:05762 results.extend([
Alex Rudenko4a7a3242024-04-18 10:36:50763 output_api.PresubmitError(
764 "node_modules/%s is missing. Use npm run install-deps to re-create it."
Alex Rudenko537c6312024-07-19 06:22:05765 % file)
766 ])
Alex Rudenko4a7a3242024-04-18 10:36:50767
Alex Rudenko537c6312024-07-19 06:22:05768 return results