README.md
1# AOSP Presubmit Hooks
2
3[TOC]
4
5This repo holds hooks that get run by repo during the upload phase. They
6perform various checks automatically such as running linters on your code.
7
8Note: Currently all hooks are disabled by default. Each repo must explicitly
9turn on any hook it wishes to enforce.
10
11## Usage
12
13Normally these execute automatically when you run `repo upload`. If you want to
14run them by hand, you can execute `pre-upload.py` directly. By default, that
15will scan the active repo and process all commits that haven't yet been merged.
16See its help for more info.
17
18### Bypassing
19
20Sometimes you might want to bypass the upload checks. While this is **strongly
21discouraged** (often failures you add will affect others and block them too),
22sometimes there are valid reasons for this. You can simply use the option
23`--no-verify` when running `repo upload` to skip all upload checks. This will
24skip **all** checks and not just specific ones. It should be used only after
25having run & evaluated the upload output previously.
26
27# Config Files
28
29There are two types of config files:
30* Repo project-wide settings (e.g. all of AOSP). These set up defaults for all
31 projects that are checked out via a single manifest.
32* Project-local settings (e.g. a single .git repo). These control settings for
33 the local project you're working on.
34
35The merging of these config files control the hooks/checks that get run when
36running `repo upload`.
37
38## GLOBAL-PREUPLOAD.cfg
39
40These are the manifest-wide defaults and can be located in two places:
41* `.repo/manifests/GLOBAL-PREUPLOAD.cfg`: The manifest git repo.
42 Simply check this in to the manifest git repo and you're done.
43* `GLOBAL-PREUPLOAD.cfg`: The top level of the repo checkout.
44 For manifests that don't have a project checked out at the top level,
45 you can use repo's `<copyfile>` directive.
46
47These config files will be loaded first before stacking `PREUPLOAD.cfg`
48settings on top.
49
50## PREUPLOAD.cfg
51
52This file are checked in the top of a specific git repository. Stacking them
53in subdirectories (to try and override parent settings) is not supported.
54
55## Example
56
57```
58[Options]
59ignore_merged_commits = true
60
61[Hook Scripts]
62name = script --with args ${PREUPLOAD_FILES}
63
64[Builtin Hooks]
65cpplint = true
66
67[Builtin Hooks Options]
68cpplint = --filter=-x ${PREUPLOAD_FILES}
69
70[Tool Paths]
71clang-format = /usr/bin/clang-format
72```
73
74## Environment
75
76Hooks are executed in the top directory of the git repository. All paths should
77generally be relative to that point.
78
79A few environment variables are set so scripts don't need to discover things.
80
81* `REPO_PROJECT`: The name of the project.
82 e.g. `platform/tools/repohooks`
83* `REPO_PATH`: The path to the project relative to the root.
84 e.g. `tools/repohooks`
85* `REPO_REMOTE`: The name of the git remote.
86 e.g. `aosp`.
87* `REPO_LREV`: The name of the remote revision, translated to a local tracking
88 branch. This is typically latest commit in the remote-tracking branch.
89 e.g. `ec044d3e9b608ce275f02092f86810a3ba13834e`
90* `REPO_RREV`: The remote revision.
91 e.g. `master`
92* `PREUPLOAD_COMMIT`: The commit that is currently being checked.
93 e.g. `1f89dce0468448fa36f632d2fc52175cd6940a91`
94
95## Placeholders
96
97A few keywords are recognized to pass down settings. These are **not**
98environment variables, but are expanded inline. Files with whitespace and
99such will be expanded correctly via argument positions, so do not try to
100force your own quote handling.
101
102* `${PREUPLOAD_FILES}`: List of files to operate on.
103* `${PREUPLOAD_COMMIT}`: Commit hash.
104* `${PREUPLOAD_COMMIT_MESSAGE}`: Commit message.
105
106Some variables are available to make it easier to handle OS differences. These
107are automatically expanded for you:
108
109* `${REPO_ROOT}`: The absolute path of the root of the repo checkout.
110* `${BUILD_OS}`: The string `darwin-x86` for macOS and the string `linux-x86`
111 for Linux/x86.
112
113## [Options]
114
115This section allows for setting options that affect the overall behavior of the
116pre-upload checks. The following options are recognized:
117
118* `ignore_merged_commits`: If set to `true`, the hooks will not run on commits
119 that are merged. Hooks will still run on the merge commit itself.
120
121## [Hook Scripts]
122
123This section allows for completely arbitrary hooks to run on a per-repo basis.
124
125The key can be any name (as long as the syntax is valid), as can the program
126that is executed. The key is used as the name of the hook for reporting purposes,
127so it should be at least somewhat descriptive.
128
129```
130[Hook Scripts]
131my_first_hook = program --gogog ${PREUPLOAD_FILES}
132another_hook = funtimes --i-need "some space" ${PREUPLOAD_FILES}
133some_fish = linter --ate-a-cat ${PREUPLOAD_FILES}
134some_cat = formatter --cat-commit ${PREUPLOAD_COMMIT}
135some_dog = tool --no-cat-in-commit-message ${PREUPLOAD_COMMIT_MESSAGE}
136```
137
138## [Builtin Hooks]
139
140This section allows for turning on common/builtin hooks. There are a bunch of
141canned hooks already included geared towards AOSP style guidelines.
142
143* `checkpatch`: Run commits through the Linux kernel's `checkpatch.pl` script.
144* `clang_format`: Run git-clang-format against the commit. The default style is
145 `file`.
146* `commit_msg_bug_field`: Require a valid `Bug:` line.
147* `commit_msg_changeid_field`: Require a valid `Change-Id:` Gerrit line.
148* `commit_msg_prebuilt_apk_fields`: Require badging and build information for
149 prebuilt APKs.
150* `commit_msg_test_field`: Require a `Test:` line.
151* `cpplint`: Run through the cpplint tool (for C++ code).
152* `gofmt`: Run Go code through `gofmt`.
153* `google_java_format`: Run Java code through
154 [`google-java-format`](https://github.com/google/google-java-format)
155* `jsonlint`: Verify JSON code is sane.
156* `pylint`: Run Python code through `pylint`.
157* `xmllint`: Run XML code through `xmllint`.
158* `android_test_mapping_format`: Validate TEST_MAPPING files in Android source
159 code. Refer to go/test-mapping for more details.
160
161Note: Builtin hooks tend to match specific filenames (e.g. `.json`). If no
162files match in a specific commit, then the hook will be skipped for that commit.
163
164```
165[Builtin Hooks]
166# Turn on cpplint checking.
167cpplint = true
168# Turn off gofmt checking.
169gofmt = false
170```
171
172## [Builtin Hooks Options]
173
174Used to customize the behavior of specific `[Builtin Hooks]`. Any arguments set
175here will be passed directly to the linter in question. This will completely
176override any existing default options, so be sure to include everything you need
177(especially `${PREUPLOAD_FILES}` -- see below).
178
179Quoting is handled naturally. i.e. use `"a b c"` to pass an argument with
180whitespace.
181
182See [Placeholders](#Placeholders) for variables you can expand automatically.
183
184```
185[Builtin Hooks Options]
186# Pass more filter args to cpplint.
187cpplint = --filter=-x ${PREUPLOAD_FILES}
188```
189
190## [Tool Paths]
191
192Some builtin hooks need to call external executables to work correctly. By
193default it will call those tools from the user's `$PATH`, but the paths of those
194executables can be overridden through `[Tool Paths]`. This is helpful to
195provide consistent behavior for developers across different OS and Linux
196distros/versions. The following tools are recognized:
197
198* `clang-format`: used for the `clang_format` builtin hook.
199* `cpplint`: used for the `cpplint` builtin hook.
200* `git-clang-format`: used for the `clang_format` builtin hook.
201* `gofmt`: used for the `gofmt` builtin hook.
202* `google-java-format`: used for the `google_java_format` builtin hook.
203* `google-java-format-diff`: used for the `google_java_format` builtin hook.
204* `pylint`: used for the `pylint` builtin hook.
205* `android-test-mapping-format`: used for the `android_test_mapping_format`
206 builtin hook.
207
208See [Placeholders](#Placeholders) for variables you can expand automatically.
209
210```
211[Tool Paths]
212# Pass absolute paths.
213clang-format = /usr/bin/clang-format
214# Or paths relative to the top of the git project.
215clang-format = prebuilts/bin/clang-format
216# Or paths relative to the repo root.
217clang-format = ${REPO_ROOT}/prebuilts/clang/host/${BUILD_OS}/clang-stable/bin/clang-format
218```
219
220# Hook Developers
221
222These are notes for people updating the `pre-upload.py` hook itself:
223
224* Don't worry about namespace collisions. The `pre-upload.py` script is loaded
225 and exec-ed in its own context. The only entry-point that matters is `main`.
226* New hooks can be added in `rh/hooks.py`. Be sure to keep the list up-to-date
227 with the documentation in this file.
228
229### Warnings
230
231If the return code of a hook is 77, then it is assumed to be a warning. The
232output will be printed to the terminal, but uploading will still be allowed
233without a bypass being required.
234
235## TODO/Limitations
236
237* `pylint` should support per-directory pylintrc files.
238* Some checkers operate on the files as they exist in the filesystem. This is
239 not easy to fix because the linters require not just the modified file but the
240 entire repo in order to perform full checks. e.g. `pylint` needs to know what
241 other modules exist locally to verify their API. We can support this case by
242 doing a full checkout of the repo in a temp dir, but this can slow things down
243 a lot. Will need to consider a `PREUPLOAD.cfg` knob.
244* We need to add `pylint` tool to the AOSP manifest and use that local copy
245 instead of relying on the version that is in $PATH.
246* Should make file extension filters configurable. All hooks currently declare
247 their own list of files like `.cc` and `.py` and `.xml`.
248* Add more checkers.
249 * `clang-check`: Runs static analyzers against code.
250 * License checking (like require AOSP header).
251 * Whitespace checking (trailing/tab mixing/etc...).
252 * Long line checking.
253 * Commit message checks (correct format/BUG/TEST/SOB tags/etc...).
254 * Markdown (gitiles) validator.
255 * Spell checker.
256