blob: 82fa56c5eb5cb54d545433bd7d80aca175958b30 [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
Benedikt Meurerbc9da612024-08-19 10:44:4931See http://goo.gle/devtools-testing-guide#Presubmit-checks for more how to
32run presubmit checks in DevTools.
33
Blink Reformat4c46d092018-04-07 15:32:3734See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
35for more details about the presubmit API built into gcl.
36"""
37
38import sys
Tim van der Lippef515fdc2020-03-06 16:18:2539import six
Tim van der Lippefb023462020-08-21 13:10:0640import time
Blink Reformat4c46d092018-04-07 15:32:3741
Alex Rudenko4a7a3242024-04-18 10:36:5042from pathlib import Path
43
Liviu Rauf3028602023-11-10 10:52:0444# Depot tools imports
45import rdb_wrapper
46
Liviu Raufd2e3212019-12-18 15:38:2047AUTOROLL_ACCOUNT = "devtools-ci-autoroll-builder@chops-service-accounts.iam.gserviceaccount.com"
Tim van der Lippefb1dc172021-05-11 15:40:2648USE_PYTHON3 = True
Mathias Bynensa0a6e292019-12-17 12:24:0849
Alex Rudenko537c6312024-07-19 06:22:0550
Tim van der Lippe4d004ec2020-03-03 18:32:0151def _ExecuteSubProcess(input_api, output_api, script_path, args, results):
Tim van der Lippef515fdc2020-03-06 16:18:2552 if isinstance(script_path, six.string_types):
Philip Pfaffef4320aa2022-07-21 11:33:2453 script_path = [input_api.python3_executable, script_path]
Tim van der Lippef515fdc2020-03-06 16:18:2554
Tim van der Lippefb023462020-08-21 13:10:0655 start_time = time.time()
Sigurd Schneiderf3a1ecd2021-03-02 14:46:0356 process = input_api.subprocess.Popen(script_path + args,
57 stdout=input_api.subprocess.PIPE,
58 stderr=input_api.subprocess.STDOUT)
Tim van der Lippe4d004ec2020-03-03 18:32:0159 out, _ = process.communicate()
Tim van der Lippefb023462020-08-21 13:10:0660 end_time = time.time()
61
62 time_difference = end_time - start_time
63 time_info = "Script execution time was %.1fs seconds\n" % (time_difference)
Tim van der Lippe4d004ec2020-03-03 18:32:0164 if process.returncode != 0:
Tim van der Lippefb1dc172021-05-11 15:40:2665 results.append(
66 output_api.PresubmitError(time_info + out.decode('utf-8')))
Tim van der Lippe4d004ec2020-03-03 18:32:0167 else:
Tim van der Lippefb1dc172021-05-11 15:40:2668 results.append(
69 output_api.PresubmitNotifyResult(time_info + out.decode('utf-8')))
Tim van der Lippe4d004ec2020-03-03 18:32:0170 return results
71
72
Gavin Mak4a41e482024-07-31 17:16:4473def _IsEnvCog(input_api):
74 old_sys_path = sys.path[:]
75 devtools_root = input_api.PresubmitLocalPath()
76 depot_tools = input_api.os_path.join(devtools_root, 'third_party',
77 'depot_tools')
78 try:
79 sys.path.append(depot_tools)
80 from gclient_utils import IsEnvCog
81 if IsEnvCog():
82 return True
83 finally:
84 sys.path = old_sys_path
85 return False
86
87
Sigurd Schneider5c9b4f92021-01-22 10:09:5588def _CheckBugAssociation(input_api, output_api, is_committing):
89 results = [output_api.PresubmitNotifyResult('Bug Association Check:')]
90 bugs = input_api.change.BugsFromDescription()
91 message = (
92 "Each CL should be associated with a bug, use \'Bug:\' or \'Fixed:\' lines in\n"
93 "the footer of the commit description. If you explicitly don\'t want to\n"
94 "set a bug, use \'Bug: none\' in the footer of the commit description.\n\n"
95 "Note: The footer of the commit description is the last block of lines in\n"
96 "the commit description that doesn't contain empty lines. This means that\n"
97 "any \'Bug:\' or \'Fixed:\' lines that are eventually followed by an empty\n"
98 "line are not detected by this presubmit check.")
99
100 if not bugs:
101 if is_committing:
102 results.append(output_api.PresubmitError(message))
103 else:
104 results.append(output_api.PresubmitNotifyResult(message))
105
106 for bug in bugs:
107 results.append(output_api.PresubmitNotifyResult(('%s') % bug))
108
109 return results
110
111
Brandon Goddard33104372020-08-13 15:49:23112def _CheckExperimentTelemetry(input_api, output_api):
Brandon Goddard33104372020-08-13 15:49:23113 experiment_telemetry_files = [
114 input_api.os_path.join(input_api.PresubmitLocalPath(), 'front_end',
Christy Chenab9a44d2021-07-02 19:54:30115 'entrypoints', 'main', 'MainImpl.ts'),
Brandon Goddard33104372020-08-13 15:49:23116 input_api.os_path.join(input_api.PresubmitLocalPath(), 'front_end',
Tim van der Lippee0247312021-04-01 14:25:30117 'core', 'host', 'UserMetrics.ts')
Brandon Goddard33104372020-08-13 15:49:23118 ]
119 affected_main_files = _getAffectedFiles(input_api,
120 experiment_telemetry_files, [],
Christy Chenab9a44d2021-07-02 19:54:30121 ['.ts'])
Brandon Goddard33104372020-08-13 15:49:23122 if len(affected_main_files) == 0:
Tim van der Lippefb023462020-08-21 13:10:06123 return [
124 output_api.PresubmitNotifyResult(
125 'No affected files for telemetry check')
126 ]
Brandon Goddard33104372020-08-13 15:49:23127
Tim van der Lippefb023462020-08-21 13:10:06128 results = [
129 output_api.PresubmitNotifyResult('Running Experiment Telemetry check:')
130 ]
Brandon Goddard33104372020-08-13 15:49:23131 script_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
132 'scripts', 'check_experiments.js')
133 results.extend(_checkWithNodeScript(input_api, output_api, script_path))
134 return results
135
136
Jack Franklinb5a63092022-11-30 14:32:36137def _CheckESBuildVersion(input_api, output_api):
138 results = [
139 output_api.PresubmitNotifyResult('Running ESBuild version check:')
140 ]
141 script_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
142 'scripts',
143 'check_esbuild_versions.js')
144 results.extend(_checkWithNodeScript(input_api, output_api, script_path))
145 return results
146
147
Wolfgang Beyere57322c2024-02-08 12:04:24148def _CheckEnumeratedHistograms(input_api, output_api):
149 enumerated_histograms_files = [
150 input_api.os_path.join(input_api.PresubmitLocalPath(), 'front_end',
151 'devtools_compatibility.js'),
152 input_api.os_path.join(input_api.PresubmitLocalPath(), 'front_end',
153 'core', 'host', 'InspectorFrontendHostAPI.ts')
154 ]
155 affected_main_files = _getAffectedFiles(input_api,
156 enumerated_histograms_files, [],
157 ['.js', '.ts'])
158 if len(affected_main_files) == 0:
159 return [
160 output_api.PresubmitNotifyResult(
161 'No affected files for UMA Enumerated Histograms check')
162 ]
163
164 results = [
165 output_api.PresubmitNotifyResult(
166 'Running UMA Enumerated Histograms check:')
167 ]
168 script_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
169 'scripts',
170 'check_enumerated_histograms.js')
171 results.extend(_checkWithNodeScript(input_api, output_api, script_path))
172 return results
173
174
Blink Reformat4c46d092018-04-07 15:32:37175def _CheckFormat(input_api, output_api):
Gavin Mak4a41e482024-07-31 17:16:44176 if _IsEnvCog(input_api):
177 return [
178 output_api.PresubmitPromptWarning(
179 'Non-git environment detected, skipping _CheckFormat.')
180 ]
181
Brandon Goddarde7028672020-01-30 17:31:04182 results = [output_api.PresubmitNotifyResult('Running Format Checks:')]
Blink Reformat4c46d092018-04-07 15:32:37183
Simon Zündcc994132024-02-15 07:34:44184 return _ExecuteSubProcess(input_api, output_api,
Alex Rudenko518bfae2024-12-02 13:04:52185 ['git', 'cl', 'format', '--js'], [], results)
Blink Reformat4c46d092018-04-07 15:32:37186
Jack Franklin1aa212d2021-09-10 14:20:08187
188def _CheckDevToolsRunESLintTests(input_api, output_api):
189 # Check for changes in the eslint_rules directory, and run the eslint rules
190 # tests if so.
191 # We don't do this on every CL as most do not touch the rules, but if we do
192 # change them we need to make sure all the tests are passing.
Jack Franklin03db63a2021-09-16 13:40:56193 original_sys_path = sys.path
194 try:
195 sys.path = sys.path + [
196 input_api.os_path.join(input_api.PresubmitLocalPath(), 'scripts')
197 ]
198 import devtools_paths
199 finally:
200 sys.path = original_sys_path
Jack Franklin1aa212d2021-09-10 14:20:08201 eslint_rules_dir_path = input_api.os_path.join(
202 input_api.PresubmitLocalPath(), 'scripts', 'eslint_rules')
203 eslint_rules_affected_files = _getAffectedFiles(input_api,
204 [eslint_rules_dir_path],
205 [], [])
206
207 if (len(eslint_rules_affected_files) == 0):
208 return []
209
Jack Franklin03db63a2021-09-16 13:40:56210 mocha_path = devtools_paths.mocha_path()
Jack Franklin1aa212d2021-09-10 14:20:08211 eslint_tests_path = input_api.os_path.join(eslint_rules_dir_path, 'tests',
Benedikt Meurer586a9a52024-12-27 10:28:21212 '*.test.js')
Jack Franklin1aa212d2021-09-10 14:20:08213
214 results = [output_api.PresubmitNotifyResult('ESLint rules unit tests')]
215 results.extend(
216 # The dot reporter is more concise which is useful to not get LOADS of
217 # output when just one test fails.
218 _checkWithNodeScript(input_api, output_api, mocha_path,
219 ['--reporter', 'dot', eslint_tests_path]))
220 return results
221
222
Tim van der Lippe800d8752022-02-04 12:49:56223def _CheckDevToolsRunBuildTests(input_api, output_api):
224 # Check for changes in the build/tests directory, and run the tests if so.
225 # We don't do this on every CL as most do not touch the rules, but if we do
226 # change them we need to make sure all the tests are passing.
227 original_sys_path = sys.path
228 try:
229 sys.path = sys.path + [
230 input_api.os_path.join(input_api.PresubmitLocalPath(), 'scripts')
231 ]
232 import devtools_paths
233 finally:
234 sys.path = original_sys_path
235 scripts_build_dir_path = input_api.os_path.join(
236 input_api.PresubmitLocalPath(), 'scripts', 'build')
237 scripts_build_affected_files = _getAffectedFiles(input_api,
238 [scripts_build_dir_path],
239 [], [])
240
241 if len(scripts_build_affected_files) == 0:
242 return []
243
244 mocha_path = devtools_paths.mocha_path()
245 build_tests_path = input_api.os_path.join(scripts_build_dir_path, 'tests',
246 '*_test.js')
247
248 results = [output_api.PresubmitNotifyResult('Build plugins unit tests')]
249 results.extend(
250 # The dot reporter is more concise which is useful to not get LOADS of
251 # output when just one test fails.
252 _checkWithNodeScript(input_api, output_api, mocha_path,
253 ['--reporter', 'dot', build_tests_path]))
254 return results
255
256
Benedikt Meurer6dd23b62024-08-20 12:08:43257def _CheckDevToolsLint(input_api, output_api):
258 results = [output_api.PresubmitNotifyResult('Lint Check:')]
Mathias Bynens1b2c5e42020-06-18 06:29:21259 lint_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
Nikolay Vitkov2a1b3b32025-01-03 10:18:46260 'scripts', 'test', 'run_lint_check.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 = [
Benedikt Meurer6dd23b62024-08-20 12:08:43275 front_end_directory,
276 test_directory,
277 scripts_directory,
278 inspector_overlay_directory,
Mathias Bynens1b2c5e42020-06-18 06:29:21279 ]
Tim van der Lippe2a4ae2b2020-03-11 17:28:06280
Benedikt Meurer6dd23b62024-08-20 12:08:43281 lint_related_files = [
Mathias Bynens1b2c5e42020-06-18 06:29:21282 input_api.os_path.join(input_api.PresubmitLocalPath(), 'node_modules',
283 'eslint'),
Tim van der Lippecf4ab402021-02-12 14:30:58284 input_api.os_path.join(input_api.PresubmitLocalPath(), 'node_modules',
Benedikt Meurer6dd23b62024-08-20 12:08:43285 'stylelint'),
286 input_api.os_path.join(input_api.PresubmitLocalPath(), 'node_modules',
Tim van der Lippecf4ab402021-02-12 14:30:58287 '@typescript-eslint'),
Mathias Bynens1b2c5e42020-06-18 06:29:21288 input_api.os_path.join(input_api.PresubmitLocalPath(),
Nikolay Vitkov55adf672025-01-02 12:07:33289 'eslint.config.mjs'),
Tim van der Lippe2a4ae2b2020-03-11 17:28:06290 input_api.os_path.join(scripts_directory, 'eslint_rules'),
Benedikt Meurer6dd23b62024-08-20 12:08:43291 input_api.os_path.join(input_api.PresubmitLocalPath(),
292 '.stylelintrc.json'),
293 input_api.os_path.join(input_api.PresubmitLocalPath(),
294 '.stylelintignore'),
Nikolay Vitkov2a1b3b32025-01-03 10:18:46295 input_api.os_path.join(scripts_directory, 'test',
296 'run_lint_check.mjs'),
Tim van der Lippe2a4ae2b2020-03-11 17:28:06297 ]
298
Benedikt Meurer6dd23b62024-08-20 12:08:43299 lint_config_files = _getAffectedFiles(input_api, lint_related_files, [],
Nikolay Vitkov55adf672025-01-02 12:07:33300 ['.js', '.py'])
Tim van der Lippe2a4ae2b2020-03-11 17:28:06301
Mathias Bynens0ec56612020-06-19 07:14:03302 should_bail_out, files_to_lint = _getFilesToLint(
303 input_api, output_api, lint_config_files, default_linted_directories,
Benedikt Meurer6dd23b62024-08-20 12:08:43304 ['.css', '.js', '.ts'], results)
Mathias Bynens0ec56612020-06-19 07:14:03305 if should_bail_out:
Mathias Bynens1b2c5e42020-06-18 06:29:21306 return results
Tim van der Lippe2a4ae2b2020-03-11 17:28:06307
Brandon Goddarde34e94f2021-04-12 17:58:26308 # If there are more than 50 files to check, don't bother and check
309 # everything, so as to not run into command line length limits on Windows.
310 if len(files_to_lint) > 50:
311 files_to_lint = []
312
Mathias Bynens1b2c5e42020-06-18 06:29:21313 results.extend(
314 _checkWithNodeScript(input_api, output_api, lint_path, files_to_lint))
Tim van der Lippe98132242020-04-14 16:16:54315 return results
Blink Reformat4c46d092018-04-07 15:32:37316
Nikolay Vitkov55adf672025-01-02 12:07:33317
Tim van der Lippea53672d2021-07-08 14:52:35318def _CheckDevToolsNonJSFileLicenseHeaders(input_api, output_api):
Tim van der Lippe81752502021-05-26 14:38:12319 results = [
320 output_api.PresubmitNotifyResult(
321 'Python-like file license header check:')
322 ]
Tim van der Lippea53672d2021-07-08 14:52:35323 lint_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
324 'scripts', 'test',
325 'run_header_check_non_js_files.js')
Tim van der Lippe81752502021-05-26 14:38:12326
327 front_end_directory = input_api.os_path.join(
328 input_api.PresubmitLocalPath(), 'front_end')
329 inspector_overlay_directory = input_api.os_path.join(
330 input_api.PresubmitLocalPath(), 'inspector_overlay')
331 test_directory = input_api.os_path.join(input_api.PresubmitLocalPath(),
332 'test')
333 scripts_directory = input_api.os_path.join(input_api.PresubmitLocalPath(),
334 'scripts')
Tim van der Lippe8b929542021-05-26 14:54:20335 config_directory = input_api.os_path.join(input_api.PresubmitLocalPath(),
336 'config')
Tim van der Lippe81752502021-05-26 14:38:12337
338 default_linted_directories = [
339 front_end_directory, test_directory, scripts_directory,
Tim van der Lippe8b929542021-05-26 14:54:20340 inspector_overlay_directory, config_directory
Tim van der Lippe81752502021-05-26 14:38:12341 ]
342
343 check_related_files = [lint_path]
344
345 lint_config_files = _getAffectedFiles(input_api, check_related_files, [],
346 ['.js'])
347
348 should_bail_out, files_to_lint = _getFilesToLint(
349 input_api, output_api, lint_config_files, default_linted_directories,
Tim van der Lippea53672d2021-07-08 14:52:35350 ['BUILD.gn', '.gni', '.css'], results)
Tim van der Lippe81752502021-05-26 14:38:12351 if should_bail_out:
352 return results
353
354 # If there are more than 50 files to check, don't bother and check
355 # everything, so as to not run into command line length limits on Windows.
356 if len(files_to_lint) > 50:
357 files_to_lint = []
358
359 results.extend(
360 _checkWithNodeScript(input_api, output_api, lint_path, files_to_lint))
361 return results
362
363
Tim van der Lippe4d004ec2020-03-03 18:32:01364def _CheckGeneratedFiles(input_api, output_api):
Alex Rudenko537c6312024-07-19 06:22:05365 v8_directory_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
366 'v8')
367 blink_directory_path = input_api.os_path.join(
368 input_api.PresubmitLocalPath(), 'third_party', 'blink')
369 protocol_location = input_api.os_path.join(blink_directory_path, 'public',
370 'devtools_protocol')
371 scripts_build_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
372 'scripts', 'build')
373 scripts_generated_output_path = input_api.os_path.join(
374 input_api.PresubmitLocalPath(), 'front_end', 'generated')
Tim van der Lippeb3b90762020-03-04 15:21:52375
Alex Rudenko537c6312024-07-19 06:22:05376 generated_aria_path = input_api.os_path.join(scripts_build_path,
377 'generate_aria.py')
378 generated_supported_css_path = input_api.os_path.join(
379 scripts_build_path, 'generate_supported_css.py')
Simon Zünd2ce67542023-02-07 10:15:14380 generated_deprecation_path = input_api.os_path.join(
381 scripts_build_path, 'generate_deprecations.py')
Alex Rudenko537c6312024-07-19 06:22:05382 generated_protocol_path = input_api.os_path.join(
383 scripts_build_path, 'code_generator_frontend.py')
Tim van der Lippe2a1eac22021-05-13 15:19:29384 generated_protocol_typescript_path = input_api.os_path.join(
385 input_api.PresubmitLocalPath(), 'scripts', 'protocol_typescript')
Alex Rudenko537c6312024-07-19 06:22:05386 concatenate_protocols_path = input_api.os_path.join(
387 input_api.PresubmitLocalPath(), 'third_party', 'inspector_protocol',
388 'concatenate_protocols.py')
Tim van der Lippeb3b90762020-03-04 15:21:52389
390 affected_files = _getAffectedFiles(input_api, [
391 v8_directory_path,
392 blink_directory_path,
Tim van der Lippe2a1eac22021-05-13 15:19:29393 input_api.os_path.join(input_api.PresubmitLocalPath(), 'third_party',
394 'pyjson5'),
Tim van der Lippeb3b90762020-03-04 15:21:52395 generated_aria_path,
396 generated_supported_css_path,
Simon Zünd2ce67542023-02-07 10:15:14397 generated_deprecation_path,
Tim van der Lippeb3b90762020-03-04 15:21:52398 concatenate_protocols_path,
399 generated_protocol_path,
Tim van der Lippe5d2d79b2020-03-23 11:45:04400 scripts_generated_output_path,
Tim van der Lippe2a1eac22021-05-13 15:19:29401 generated_protocol_typescript_path,
402 ], [], ['.pdl', '.json5', '.py', '.js', '.ts'])
Tim van der Lippeb3b90762020-03-04 15:21:52403
404 if len(affected_files) == 0:
Tim van der Lippefb023462020-08-21 13:10:06405 return [
406 output_api.PresubmitNotifyResult(
407 'No affected files for generated files check')
408 ]
Tim van der Lippeb3b90762020-03-04 15:21:52409
Alex Rudenko537c6312024-07-19 06:22:05410 results = [
411 output_api.PresubmitNotifyResult('Running Generated Files Check:')
412 ]
413 generate_protocol_resources_path = input_api.os_path.join(
414 input_api.PresubmitLocalPath(), 'scripts', 'deps',
415 'generate_protocol_resources.py')
Tim van der Lippe4d004ec2020-03-03 18:32:01416
Alex Rudenko537c6312024-07-19 06:22:05417 return _ExecuteSubProcess(input_api, output_api,
418 generate_protocol_resources_path, [], results)
Tim van der Lippe4d004ec2020-03-03 18:32:01419
420
Simon Zünd9ff4da62022-11-22 09:25:59421def _CheckL10nStrings(input_api, output_api):
Christy Chen2d6d9a62020-09-22 16:04:09422 devtools_root = input_api.PresubmitLocalPath()
423 devtools_front_end = input_api.os_path.join(devtools_root, 'front_end')
Tim van der Lippe25f11082021-06-24 15:28:08424 script_path = input_api.os_path.join(devtools_root, 'third_party', 'i18n',
Simon Zünd9ff4da62022-11-22 09:25:59425 'check-strings.js')
Tim van der Lippe25f11082021-06-24 15:28:08426 affected_front_end_files = _getAffectedFiles(
427 input_api, [devtools_front_end, script_path], [], ['.js', '.ts'])
Christy Chen2d6d9a62020-09-22 16:04:09428 if len(affected_front_end_files) == 0:
429 return [
430 output_api.PresubmitNotifyResult(
Simon Zünd9ff4da62022-11-22 09:25:59431 'No affected files to run check-strings')
Christy Chen2d6d9a62020-09-22 16:04:09432 ]
433
434 results = [
Simon Zünd9ff4da62022-11-22 09:25:59435 output_api.PresubmitNotifyResult('Checking UI strings from front_end:')
Christy Chen2d6d9a62020-09-22 16:04:09436 ]
Tim van der Lippe25f11082021-06-24 15:28:08437 results.extend(
438 _checkWithNodeScript(input_api, output_api, script_path,
439 [devtools_front_end]))
Christy Chen2d6d9a62020-09-22 16:04:09440 return results
441
442
Tim van der Lippe5279f842020-01-14 16:26:38443def _CheckNoUncheckedFiles(input_api, output_api):
Gavin Mak4a41e482024-07-31 17:16:44444 if _IsEnvCog(input_api):
445 return [
446 output_api.PresubmitPromptWarning(
447 'Non-git environment detected, skipping '
448 '_CheckNoUncheckedFiles.')
449 ]
450
Tim van der Lippe5279f842020-01-14 16:26:38451 process = input_api.subprocess.Popen(['git', 'diff', '--exit-code'],
452 stdout=input_api.subprocess.PIPE,
453 stderr=input_api.subprocess.STDOUT)
454 out, _ = process.communicate()
455 if process.returncode != 0:
Jack Franklin324f3042020-09-03 10:28:29456 files_changed_process = input_api.subprocess.Popen(
Tim van der Lippe25f11082021-06-24 15:28:08457 ['git', 'diff'],
Jack Franklin324f3042020-09-03 10:28:29458 stdout=input_api.subprocess.PIPE,
459 stderr=input_api.subprocess.STDOUT)
Tim van der Lippe9bb1cf62020-03-06 16:17:02460 files_changed, _ = files_changed_process.communicate()
461
462 return [
Tim van der Lippefb1dc172021-05-11 15:40:26463 output_api.PresubmitError(
464 'You have changed files that need to be committed:'),
465 output_api.PresubmitError(files_changed.decode('utf-8'))
Tim van der Lippe9bb1cf62020-03-06 16:17:02466 ]
Tim van der Lippe5279f842020-01-14 16:26:38467 return []
468
Alex Rudenko537c6312024-07-19 06:22:05469
Tim van der Lippe8fdda112020-01-27 11:27:06470def _CheckForTooLargeFiles(input_api, output_api):
Christy Chen1ab87e02020-01-31 00:32:16471 """Avoid large files, especially binary files, in the repository since
Tim van der Lippe8fdda112020-01-27 11:27:06472 git doesn't scale well for those. They will be in everyone's repo
473 clones forever, forever making Chromium slower to clone and work
474 with."""
Christy Chen1ab87e02020-01-31 00:32:16475 # Uploading files to cloud storage is not trivial so we don't want
476 # to set the limit too low, but the upper limit for "normal" large
477 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
478 # anything over 20 MB is exceptional.
479 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
480 too_large_files = []
481 for f in input_api.AffectedFiles():
482 # Check both added and modified files (but not deleted files).
483 if f.Action() in ('A', 'M'):
484 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
485 if size > TOO_LARGE_FILE_SIZE_LIMIT:
486 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
487 if too_large_files:
488 message = (
Alex Rudenko537c6312024-07-19 06:22:05489 'Do not commit large files to git since git scales badly for those.\n'
490 +
491 'Instead put the large files in cloud storage and use DEPS to\n' +
492 'fetch them.\n' + '\n'.join(too_large_files))
493 return [
494 output_api.PresubmitError('Too large files found in commit',
495 long_text=message + '\n')
496 ]
Christy Chen1ab87e02020-01-31 00:32:16497 else:
498 return []
Tim van der Lippe8fdda112020-01-27 11:27:06499
Tim van der Lippe5279f842020-01-14 16:26:38500
Andrés Olivares205bf682023-02-01 10:47:13501def _CheckObsoleteScreenshotGoldens(input_api, output_api):
502 results = [
503 output_api.PresubmitNotifyResult('Obsolete screenshot images check')
504 ]
505 interaction_test_root_path = input_api.os_path.join(
506 input_api.PresubmitLocalPath(), 'test', 'interactions')
507 interaction_test_files = [interaction_test_root_path]
508
509 interaction_test_files_changed = _getAffectedFiles(input_api,
510 interaction_test_files,
511 [], [])
512
513 if len(interaction_test_files_changed) > 0:
514 script_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
515 'scripts', 'test',
516 'check_obsolete_goldens.js')
Andrés Olivares205bf682023-02-01 10:47:13517
Philip Pfaffece5afc02024-04-09 13:08:58518 script_args = []
Andrés Olivares205bf682023-02-01 10:47:13519 errors_from_script = _checkWithNodeScript(input_api, output_api,
520 script_path, script_args)
521 results.extend(errors_from_script)
522
523 return results
524
525
Liviu Rauf3028602023-11-10 10:52:04526def _WithArgs(checkType, **kwargs):
Alex Rudenko537c6312024-07-19 06:22:05527
Liviu Rauf3028602023-11-10 10:52:04528 def _WithArgsWrapper(input_api, output_api):
529 return checkType(input_api, output_api, **kwargs)
530
531 _WithArgsWrapper.__name__ = checkType.__name__
532 return _WithArgsWrapper
Tim van der Lippef8a87092020-09-14 12:01:18533
534
Liviu Rauf3028602023-11-10 10:52:04535def _CannedChecks(canned_checks):
536 return [
537 canned_checks.CheckForCommitObjects,
538 canned_checks.CheckOwnersFormat,
539 canned_checks.CheckOwners,
540 canned_checks.CheckChangeHasNoCrAndHasOnlyOneEol,
541 _WithArgs(canned_checks.CheckChangeHasNoStrayWhitespace,
542 source_file_filter=lambda file: not file.LocalPath().
543 startswith('node_modules')),
544 canned_checks.CheckGenderNeutral,
Jack Franklin6bc1cbd2024-07-09 10:44:09545 canned_checks.CheckDoNotSubmitInFiles,
Liviu Rauf3028602023-11-10 10:52:04546 ]
Jack Franklinb10193f2021-03-19 10:25:08547
Liviu Rauf3028602023-11-10 10:52:04548
549def _CommonChecks(canned_checks):
550 local_checks = [
551 _WithArgs(canned_checks.CheckAuthorizedAuthor,
Benedikt Meurer6dd23b62024-08-20 12:08:43552 bot_allowlist=[AUTOROLL_ACCOUNT]),
553 _CheckExperimentTelemetry,
554 _CheckGeneratedFiles,
555 _CheckDevToolsLint,
556 _CheckDevToolsRunESLintTests,
557 _CheckDevToolsRunBuildTests,
558 _CheckDevToolsNonJSFileLicenseHeaders,
559 _CheckFormat,
560 _CheckESBuildVersion,
561 _CheckEnumeratedHistograms,
562 _CheckObsoleteScreenshotGoldens,
563 _CheckNodeModules,
Liviu Rauf3028602023-11-10 10:52:04564 ]
Tim van der Lippef8a87092020-09-14 12:01:18565 # Run the canned checks from `depot_tools` after the custom DevTools checks.
566 # The canned checks for example check that lines have line endings. The
567 # DevTools presubmit checks automatically fix these issues. If we would run
568 # the canned checks before the DevTools checks, they would erroneously conclude
569 # that there are issues in the code. Since the canned checks are allowed to be
570 # ignored, a confusing message is shown that asks if the failed presubmit can
571 # be continued regardless. By fixing the issues before we reach the canned checks,
572 # we don't show the message to suppress these errors, which would otherwise be
573 # causing CQ to fail.
Liviu Rauf3028602023-11-10 10:52:04574 return local_checks + _CannedChecks(canned_checks)
Kalon Hindsd44fddf2020-12-10 13:43:25575
576
577def _SideEffectChecks(input_api, output_api):
578 """Check side effects caused by other checks"""
579 results = []
Tim van der Lippe5279f842020-01-14 16:26:38580 results.extend(_CheckNoUncheckedFiles(input_api, output_api))
Tim van der Lippe8fdda112020-01-27 11:27:06581 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Blink Reformat4c46d092018-04-07 15:32:37582 return results
583
584
Liviu Rauf3028602023-11-10 10:52:04585def _RunAllChecks(checks, input_api, output_api):
586 with rdb_wrapper.client("presubmit:") as sink:
587 results = []
588 for check in checks:
589 start_time = time.time()
590
591 result = check(input_api, output_api)
592
593 elapsed_time = time.time() - start_time
594 results.extend(result)
595
596 if not sink:
597 continue
598 failure_reason = None
599 status = rdb_wrapper.STATUS_PASS
600 if any(r.fatal for r in result):
601 status = rdb_wrapper.STATUS_FAIL
602 failure_reasons = []
603 for r in result:
604 fields = r.json_format()
605 message = fields['message']
606 items = '\n'.join(' %s' % item
607 for item in fields['items'])
608 failure_reasons.append('\n'.join([message, items]))
609 if failure_reasons:
610 failure_reason = '\n'.join(failure_reasons)
611 sink.report(check.__name__, status, elapsed_time, failure_reason)
612
613 return results
614
615
Liviu Raud614e092020-01-08 09:56:33616def CheckChangeOnUpload(input_api, output_api):
Liviu Rauf3028602023-11-10 10:52:04617 checks = _CommonChecks(input_api.canned_checks) + [
618 _CheckL10nStrings,
619 # Run checks that rely on output from other DevTool checks
620 _SideEffectChecks,
621 _WithArgs(_CheckBugAssociation, is_committing=False),
622 ]
623 return _RunAllChecks(checks, input_api, output_api)
Liviu Raud614e092020-01-08 09:56:33624
625
Blink Reformat4c46d092018-04-07 15:32:37626def CheckChangeOnCommit(input_api, output_api):
Liviu Rauf3028602023-11-10 10:52:04627 checks = _CommonChecks(input_api.canned_checks) + [
628 _CheckL10nStrings,
629 # Run checks that rely on output from other DevTool checks
630 _SideEffectChecks,
631 input_api.canned_checks.CheckChangeHasDescription,
632 _WithArgs(_CheckBugAssociation, is_committing=True),
633 ]
634 return _RunAllChecks(checks, input_api, output_api)
Blink Reformat4c46d092018-04-07 15:32:37635
636
Alex Rudenko537c6312024-07-19 06:22:05637def _getAffectedFiles(input_api, parent_directories, excluded_actions,
638 accepted_endings): # pylint: disable=invalid-name
Yang Guo75beda92019-10-28 07:29:25639 """Return absolute file paths of affected files (not due to an excluded action)
Mandy Chena6be46a2019-07-09 17:06:27640 under a parent directory with an accepted file ending.
Yang Guo75beda92019-10-28 07:29:25641 """
Mandy Chena6be46a2019-07-09 17:06:27642 local_paths = [
Alex Rudenko537c6312024-07-19 06:22:05643 f.AbsoluteLocalPath() for f in input_api.AffectedFiles()
644 if all(f.Action() != action for action in excluded_actions)
Mandy Chena6be46a2019-07-09 17:06:27645 ]
646 affected_files = [
Tim van der Lippefb1dc172021-05-11 15:40:26647 file_name for file_name in local_paths
648 if any(parent_directory in file_name
649 for parent_directory in parent_directories) and (
650 len(accepted_endings) == 0 or any(
651 file_name.endswith(accepted_ending)
652 for accepted_ending in accepted_endings))
Mandy Chena6be46a2019-07-09 17:06:27653 ]
654 return affected_files
655
656
Alex Rudenko537c6312024-07-19 06:22:05657def _checkWithNodeScript(input_api,
658 output_api,
659 script_path,
660 script_arguments=[]): # pylint: disable=invalid-name
Blink Reformat4c46d092018-04-07 15:32:37661 original_sys_path = sys.path
662 try:
Alex Rudenko537c6312024-07-19 06:22:05663 sys.path = sys.path + [
664 input_api.os_path.join(input_api.PresubmitLocalPath(), 'scripts')
665 ]
Yang Guod8176982019-10-04 20:30:35666 import devtools_paths
Blink Reformat4c46d092018-04-07 15:32:37667 finally:
668 sys.path = original_sys_path
669
Alex Rudenko537c6312024-07-19 06:22:05670 return _ExecuteSubProcess(input_api, output_api,
671 [devtools_paths.node_path(), script_path],
672 script_arguments, [])
Mathias Bynens1b2c5e42020-06-18 06:29:21673
674
675def _getFilesToLint(input_api, output_api, lint_config_files,
676 default_linted_directories, accepted_endings, results):
Mathias Bynens0ec56612020-06-19 07:14:03677 run_full_check = False
Mathias Bynens1b2c5e42020-06-18 06:29:21678 files_to_lint = []
679
680 # We are changing the lint configuration; run the full check.
Tim van der Lippefb1dc172021-05-11 15:40:26681 if len(lint_config_files) != 0:
Mathias Bynens1b2c5e42020-06-18 06:29:21682 results.append(
683 output_api.PresubmitNotifyResult('Running full lint check'))
Mathias Bynens0ec56612020-06-19 07:14:03684 run_full_check = True
Mathias Bynens1b2c5e42020-06-18 06:29:21685 else:
686 # Only run the linter on files that are relevant, to save PRESUBMIT time.
687 files_to_lint = _getAffectedFiles(input_api,
688 default_linted_directories, ['D'],
689 accepted_endings)
690
Jack Franklin130d2ae2022-07-12 09:51:26691 # Exclude front_end/third_party and front_end/generated files.
Tim van der Lippefb1dc172021-05-11 15:40:26692 files_to_lint = [
Jack Franklin130d2ae2022-07-12 09:51:26693 file for file in files_to_lint
694 if "third_party" not in file or "generated" not in file
Tim van der Lippefb1dc172021-05-11 15:40:26695 ]
Paul Lewis2b9224f2020-09-08 17:13:10696
Tim van der Lippefb1dc172021-05-11 15:40:26697 if len(files_to_lint) == 0:
Mathias Bynens1b2c5e42020-06-18 06:29:21698 results.append(
699 output_api.PresubmitNotifyResult(
700 'No affected files for lint check'))
701
Tim van der Lippefb1dc172021-05-11 15:40:26702 should_bail_out = len(files_to_lint) == 0 and not run_full_check
Mathias Bynens0ec56612020-06-19 07:14:03703 return should_bail_out, files_to_lint
Alex Rudenko4a7a3242024-04-18 10:36:50704
705
706def _CheckNodeModules(input_api, output_api):
707
708 files = ['.clang-format', 'OWNERS', 'README.chromium']
709
710 results = []
711 for file in files:
712 file_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
713 'node_modules', file)
714 if not Path(file_path).is_file():
Alex Rudenko537c6312024-07-19 06:22:05715 results.extend([
Alex Rudenko4a7a3242024-04-18 10:36:50716 output_api.PresubmitError(
717 "node_modules/%s is missing. Use npm run install-deps to re-create it."
Alex Rudenko537c6312024-07-19 06:22:05718 % file)
719 ])
Alex Rudenko4a7a3242024-04-18 10:36:50720
Alex Rudenko537c6312024-07-19 06:22:05721 return results