Overview
Presubmit scripts can perform automated checks on the files in your change and the description of your change, and either fail your attempt to upload or commit, show a warning that you must acknowledge before uploading/committing, or simply show an informational message as part of the output of Examples of things presubmit scripts may be useful for include:
Firstly, the commit bot can autofix various problems, so these problems only need to be checked on commit (to check that they have been fixed), not on upload (another good reason to use the commit queue!). Secondly, you can skip slow tests on upload and only run them on commit, if running these every time slows development too much, but this can result in problems only being caught at the last minute, and thus requiring last-minute changes after you think they're good to go. Bypassing testsTo skip the scripts on upload, use the git cl upload --bypass-hooks To skip the scripts on commit, use --bypass-hooks and directly commit your change. You should only do these if necessary, as the presubmit scripts are there for a reason, but they're not perfect. If you have trouble with a presubmit script, it's preferable to fix it, rather than simply bypassing it. See depot_tools: sending patches for how to contribute. DesignWhen you run For each such file, it will load the file into the Python interpreter and then call either the The same applies to Please note that presubmit scripts are a best-effort kind of thing; they do not prevent users from submitting without running the scripts, since one can always dcommit, and in fact there is a --bypass-hooks (formerly More subtly, presubmit scripts do not guarantee invariants: even if presubmit scripts pass prior to submission to CQ, once all changes land, the scripts may fail! This is because 2 changes may individually pass the tests, and the patches both apply cleanly together, but the combined change does not pass tests. Since presubmit/precommit scripts run at upload or at start of CQ steps, if two such changes are in the CQ at the same time, they can both pass, both be enqueued, and both land, at which point the tests start failing. A common example is change 1 adding a new test, and change 2 changing existing tests. After they both land, there is a new test in the old style (from change 1), which is out of sync with the new tests (from change 2). Writing testsTo create a new test, either create a new PRESUBMIT.py script or edit an existing one, adding a new function for your test. To check your changes, first commit locally (else To test the upload checks (i.e., to run git cl presubmit --upload To test the submit checks (i.e., to run git cl presubmit The functions must match these method signatures. You do not need to define both functions if you're only interested in one type of event, and if you want to run the same tests in both events, just have them both call a single underlying function: def CheckChangeOnUpload(input_api, output_api): pass def CheckChangeOnCommit(input_api, output_api): pass The Both InputApiThe This object can be used to transform from local to repository paths and vice versa, and to get information on the files in the change that are contained in the same directory as your The An The Files in the API are represented by an The if input_api.is_committing: message_type = output_api.PresubmitError else: message_type = output_api.PresubmitPromptWarning CaveatsIt is possible to run arbitrary Python code in the presubmit scripts. To avoid side effects and hard-to-debug errors, it is safest to run tests in subprocesses. The InputApi object provides various facilities to assist with this; see example below. Please note that you should not use any functions or attributes on the API objects that begin with an underscore (_) as these are private functions that may change, whereas all public functions will be retained through future versions of the API. Details and ExampleThe most detailed documentation for the presubmit API is in its implementation code. The canned checks are good examples of what you can do with the presubmit API. An example simple file might be as follows: def CheckChange(input_api, output_api): results = [] results += input_api.canned_checks.CheckDoNotSubmit(input_api, output_api) results += input_api.canned_checks.CheckChangeHasNoTabs(input_api, output_api) results += input_api.canned_checks.CheckLongLines(input_api, output_api) # Require a BUG= line and a HOW_TO_TEST= line. if not input_api.change.BUG or not input_api.change.HOW_TO_TEST: results += [output_api.PresubmitError( 'Must provide a BUG= line and a HOW_TO_TEST line.')] return results def CheckChangeOnUpload(input_api, output_api): return CheckChange(input_api, output_api) def CheckChangeOnCommit(input_api, output_api): return CheckChange(input_api, output_api) A simple example of a custom command (call from CheckChangeOnUpload or CheckChangeOnCommit ) is:def MyTest(input_api, output_api): test_path = input_api.os_path.join(input_api.PresubmitLocalPath(), 'my_test.py') cmd_name = 'my_test' if input_api.platform == 'win32': # Windows needs some help. cmd = [input_api.python_executable, test_path] else: cmd = [test_path] test_cmd = input_api.Command( name=cmd_name, cmd=cmd, kwargs={}, message=output_api.PresubmitPromptWarning) if input_api.verbose: print('Running ' + cmd_name) return input_api.RunTests([test_cmd]) You can look at existing scripts for examples (search: PRESUBMIT.py). Chromium's PRESUBMIT.py and Chromium-os PRESUBMIT.py are detailed examples, while the Blink bindings PRESUBMIT.py is a very simple example. |