diff options
author | Mike Frysinger <vapier@google.com> | 2017-11-10 21:28:41 -0500 |
---|---|---|
committer | Mike Frysinger <vapier@google.com> | 2017-11-10 21:53:59 -0500 |
commit | 84e7e16d35f7300bc5f4b6cca85deaf1b5a45263 (patch) | |
tree | 68d7dd3ec95ecaa64b6eb55747dbe7cda7e81b02 /docs/repo-hooks.md | |
parent | f46902a800f508061322a36b1969f51a7e95df16 (diff) | |
download | git-repo-84e7e16d35f7300bc5f4b6cca85deaf1b5a45263.tar.gz |
document repo hooks mechanism
Change-Id: I9e25b92c846f887f515efcc706cf5a869645e0ec
Diffstat (limited to 'docs/repo-hooks.md')
-rw-r--r-- | docs/repo-hooks.md | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/docs/repo-hooks.md b/docs/repo-hooks.md new file mode 100644 index 00000000..c8eb945f --- /dev/null +++ b/docs/repo-hooks.md | |||
@@ -0,0 +1,105 @@ | |||
1 | # repo hooks | ||
2 | |||
3 | [TOC] | ||
4 | |||
5 | Repo provides a mechanism to hook specific stages of the runtime with custom | ||
6 | python modules. All the hooks live in one git project which is checked out by | ||
7 | the manifest (specified during `repo init`), and the manifest itself defines | ||
8 | which hooks are registered. | ||
9 | |||
10 | These are useful to run linters, check formatting, and run quick unittests | ||
11 | before allowing a step to proceed (e.g. before uploading a commit to Gerrit). | ||
12 | |||
13 | A complete example can be found in the Android project. It can be easily | ||
14 | re-used by any repo based project and is not specific to Android.<br> | ||
15 | https://android.googlesource.com/platform/tools/repohooks | ||
16 | |||
17 | ## Approvals | ||
18 | |||
19 | When a hook is processed the first time, the user is prompted for approval. | ||
20 | We don't want to execute arbitrary code without explicit consent. For manifests | ||
21 | fetched via secure protocols (e.g. https://), the user is prompted once. For | ||
22 | insecure protocols (e.g. http://), the user is prompted whenever the registered | ||
23 | repohooks project is updated and a hook is triggered. | ||
24 | |||
25 | ## Manifest Settings | ||
26 | |||
27 | For the full syntax, see the [repo manifest format](./manifest-format.txt). | ||
28 | |||
29 | Here's a short example from | ||
30 | [Android](https://android.googlesource.com/platform/manifest/+/master/default.xml). | ||
31 | The `<project>` line checks out the repohooks git repo to the local | ||
32 | `tools/repohooks/` path. The `<repo-hooks>` line says to look in the project | ||
33 | with the name `platform/tools/repohooks` for hooks to run during the | ||
34 | `pre-upload` phase. | ||
35 | |||
36 | ```xml | ||
37 | <project path="tools/repohooks" name="platform/tools/repohooks" /> | ||
38 | <repo-hooks in-project="platform/tools/repohooks" enabled-list="pre-upload" /> | ||
39 | ``` | ||
40 | |||
41 | ## Source Layout | ||
42 | |||
43 | The repohooks git repo should have a python file with the same name as the hook. | ||
44 | So if you want to support the `pre-upload` hook, you'll need to create a file | ||
45 | named `pre-upload.py`. Repo will dynamically load that module when processing | ||
46 | the hook and then call the `main` function in it. | ||
47 | |||
48 | Hooks should have their `main` accept `**kwargs` for future compatibility. | ||
49 | |||
50 | ## Runtime | ||
51 | |||
52 | Hook return values are ignored. | ||
53 | |||
54 | Any uncaught exceptions from the hook will cause the step to fail. This is | ||
55 | intended as a fallback safety check though rather than the normal flow. If | ||
56 | you want your hook to trigger a failure, it should call `sys.exit()` (after | ||
57 | displaying relevant diagnostics). | ||
58 | |||
59 | Output (stdout & stderr) are not filtered in any way. Hooks should generally | ||
60 | not be too verbose. A short summary is nice, and some status information when | ||
61 | long running operations occur, but long/verbose output should be used only if | ||
62 | the hook ultimately fails. | ||
63 | |||
64 | The hook runs from the top level of the git repo where the operation is started. | ||
65 | e.g. If you're in the git repo `src/foo/`, that is where the hook runs, even if | ||
66 | the `repo` command was started from a subdir like `src/foo/bar/`. | ||
67 | |||
68 | Python's `sys.path` is modified so that the top of repohooks directory comes | ||
69 | first. This should help simplify the hook logic to easily allow importing of | ||
70 | local modules. | ||
71 | |||
72 | Repo does not modify the state of the git checkout. This means that the hooks | ||
73 | might be running in a dirty git repo with many commits and checked out to the | ||
74 | latest one. If the hook wants to operate on specific git commits, it needs to | ||
75 | manually discover the list of pending commits, extract the diff/commit, and | ||
76 | then check it directly. Hooks should not normally modify the active git repo | ||
77 | (such as checking out a specific commit to run checks) without first prompting | ||
78 | the user. Although user interaction is discouraged in the common case, it can | ||
79 | be useful when deploying automatic fixes. | ||
80 | |||
81 | ## Hooks | ||
82 | |||
83 | Here are all the points available for hooking. | ||
84 | |||
85 | ### pre-upload | ||
86 | |||
87 | This hook runs when people run `repo upload`. | ||
88 | |||
89 | The `pre-upload.py` file should be defined like: | ||
90 | |||
91 | ```py | ||
92 | def main(project_list, worktree_list=None, **kwargs): | ||
93 | """Main function invoked directly by repo. | ||
94 | |||
95 | We must use the name "main" as that is what repo requires. | ||
96 | |||
97 | Args: | ||
98 | project_list: List of projects to run on. | ||
99 | worktree_list: A list of directories. It should be the same length as | ||
100 | project_list, so that each entry in project_list matches with a | ||
101 | directory in worktree_list. If None, we will attempt to calculate | ||
102 | the directories automatically. | ||
103 | kwargs: Leave this here for forward-compatibility. | ||
104 | """ | ||
105 | ``` | ||