blob: cbb1aac7c85a552534c89e9c74f77887a6efcb46 [file] [log] [blame] [view]
Mike Frysinger84e7e162017-11-10 21:28:41 -05001# repo hooks
2
3[TOC]
4
5Repo provides a mechanism to hook specific stages of the runtime with custom
6python modules. All the hooks live in one git project which is checked out by
7the manifest (specified during `repo init`), and the manifest itself defines
8which hooks are registered.
9
10These are useful to run linters, check formatting, and run quick unittests
11before allowing a step to proceed (e.g. before uploading a commit to Gerrit).
12
13A complete example can be found in the Android project. It can be easily
14re-used by any repo based project and is not specific to Android.<br>
15https://android.googlesource.com/platform/tools/repohooks
16
17## Approvals
18
19When a hook is processed the first time, the user is prompted for approval.
20We don't want to execute arbitrary code without explicit consent. For manifests
21fetched via secure protocols (e.g. https://), the user is prompted once. For
22insecure protocols (e.g. http://), the user is prompted whenever the registered
23repohooks project is updated and a hook is triggered.
24
25## Manifest Settings
26
Mike Frysinger3891b752018-10-05 19:26:15 -040027For the full syntax, see the [repo manifest format](./manifest-format.md).
Mike Frysinger84e7e162017-11-10 21:28:41 -050028
29Here's a short example from
Mike Frysinger6e89c962020-11-15 18:42:26 -050030[Android](https://android.googlesource.com/platform/manifest/+/HEAD/default.xml).
Mike Frysinger84e7e162017-11-10 21:28:41 -050031The `` line checks out the repohooks git repo to the local
32`tools/repohooks/` path. The `` line says to look in the project
33with the name `platform/tools/repohooks` for hooks to run during the
34`pre-upload` phase.
35
36```xml
37
38
39```
40
41## Source Layout
42
43The repohooks git repo should have a python file with the same name as the hook.
44So if you want to support the `pre-upload` hook, you'll need to create a file
45named `pre-upload.py`. Repo will dynamically load that module when processing
46the hook and then call the `main` function in it.
47
48Hooks should have their `main` accept `**kwargs` for future compatibility.
49
50## Runtime
51
52Hook return values are ignored.
53
54Any uncaught exceptions from the hook will cause the step to fail. This is
55intended as a fallback safety check though rather than the normal flow. If
56you want your hook to trigger a failure, it should call `sys.exit()` (after
57displaying relevant diagnostics).
58
59Output (stdout & stderr) are not filtered in any way. Hooks should generally
60not be too verbose. A short summary is nice, and some status information when
61long running operations occur, but long/verbose output should be used only if
62the hook ultimately fails.
63
Mike Frysingered429c92018-03-20 20:00:14 -040064The hook runs from the top level of the repo client where the operation is
65started.
66For example, if the repo client is under `~/tree/`, then that is where the hook
67runs, even if you ran repo in a git repository at `~/tree/src/foo/`, or in a
68subdirectory of that git repository in `~/tree/src/foo/bar/`.
69Hooks frequently start off by doing a `os.chdir` to the specific project they're
70called on (see below) and then changing back to the original dir when they're
71finished.
Mike Frysinger84e7e162017-11-10 21:28:41 -050072
73Python's `sys.path` is modified so that the top of repohooks directory comes
74first. This should help simplify the hook logic to easily allow importing of
75local modules.
76
77Repo does not modify the state of the git checkout. This means that the hooks
78might be running in a dirty git repo with many commits and checked out to the
79latest one. If the hook wants to operate on specific git commits, it needs to
80manually discover the list of pending commits, extract the diff/commit, and
81then check it directly. Hooks should not normally modify the active git repo
82(such as checking out a specific commit to run checks) without first prompting
83the user. Although user interaction is discouraged in the common case, it can
84be useful when deploying automatic fixes.
85
Mike Frysingerf7c51602019-06-18 17:23:39 -040086### Shebang Handling
87
88*** note
89This is intended as a transitional feature. Hooks are expected to eventually
90migrate to Python 3 only as Python 2 is EOL & deprecated.
91***
92
93If the hook is written against a specific version of Python (either 2 or 3),
94the script can declare that explicitly. Repo will then attempt to execute it
95under the right version of Python regardless of the version repo itself might
96be executing under.
97
98Here are the shebangs that are recognized.
99
100* `#!/usr/bin/env python` & `#!/usr/bin/python`: The hook is compatible with
101 Python 2 & Python 3. For maximum compatibility, these are recommended.
102* `#!/usr/bin/env python2` & `#!/usr/bin/python2`: The hook requires Python 2.
103 Version specific names like `python2.7` are also recognized.
104* `#!/usr/bin/env python3` & `#!/usr/bin/python3`: The hook requires Python 3.
105 Version specific names like `python3.6` are also recognized.
106
107If no shebang is detected, or does not match the forms above, we assume that the
108hook is compatible with both Python 2 & Python 3 as if `#!/usr/bin/python` was
109used.
110
Mike Frysinger84e7e162017-11-10 21:28:41 -0500111## Hooks
112
113Here are all the points available for hooking.
114
115### pre-upload
116
117This hook runs when people run `repo upload`.
118
119The `pre-upload.py` file should be defined like:
120
121```py
122def main(project_list, worktree_list=None, **kwargs):
123 """Main function invoked directly by repo.
124
125 We must use the name "main" as that is what repo requires.
126
127 Args:
128 project_list: List of projects to run on.
129 worktree_list: A list of directories. It should be the same length as
130 project_list, so that each entry in project_list matches with a
131 directory in worktree_list. If None, we will attempt to calculate
132 the directories automatically.
133 kwargs: Leave this here for forward-compatibility.
134 """
135```