mirror of
https://gerrit.googlesource.com/git-repo
synced 2024-12-21 07:16:21 +00:00
84e7e16d35
Change-Id: I9e25b92c846f887f515efcc706cf5a869645e0ec
106 lines
4.2 KiB
Markdown
106 lines
4.2 KiB
Markdown
# repo hooks
|
|
|
|
[TOC]
|
|
|
|
Repo provides a mechanism to hook specific stages of the runtime with custom
|
|
python modules. All the hooks live in one git project which is checked out by
|
|
the manifest (specified during `repo init`), and the manifest itself defines
|
|
which hooks are registered.
|
|
|
|
These are useful to run linters, check formatting, and run quick unittests
|
|
before allowing a step to proceed (e.g. before uploading a commit to Gerrit).
|
|
|
|
A complete example can be found in the Android project. It can be easily
|
|
re-used by any repo based project and is not specific to Android.<br>
|
|
https://android.googlesource.com/platform/tools/repohooks
|
|
|
|
## Approvals
|
|
|
|
When a hook is processed the first time, the user is prompted for approval.
|
|
We don't want to execute arbitrary code without explicit consent. For manifests
|
|
fetched via secure protocols (e.g. https://), the user is prompted once. For
|
|
insecure protocols (e.g. http://), the user is prompted whenever the registered
|
|
repohooks project is updated and a hook is triggered.
|
|
|
|
## Manifest Settings
|
|
|
|
For the full syntax, see the [repo manifest format](./manifest-format.txt).
|
|
|
|
Here's a short example from
|
|
[Android](https://android.googlesource.com/platform/manifest/+/master/default.xml).
|
|
The `<project>` line checks out the repohooks git repo to the local
|
|
`tools/repohooks/` path. The `<repo-hooks>` line says to look in the project
|
|
with the name `platform/tools/repohooks` for hooks to run during the
|
|
`pre-upload` phase.
|
|
|
|
```xml
|
|
<project path="tools/repohooks" name="platform/tools/repohooks" />
|
|
<repo-hooks in-project="platform/tools/repohooks" enabled-list="pre-upload" />
|
|
```
|
|
|
|
## Source Layout
|
|
|
|
The repohooks git repo should have a python file with the same name as the hook.
|
|
So if you want to support the `pre-upload` hook, you'll need to create a file
|
|
named `pre-upload.py`. Repo will dynamically load that module when processing
|
|
the hook and then call the `main` function in it.
|
|
|
|
Hooks should have their `main` accept `**kwargs` for future compatibility.
|
|
|
|
## Runtime
|
|
|
|
Hook return values are ignored.
|
|
|
|
Any uncaught exceptions from the hook will cause the step to fail. This is
|
|
intended as a fallback safety check though rather than the normal flow. If
|
|
you want your hook to trigger a failure, it should call `sys.exit()` (after
|
|
displaying relevant diagnostics).
|
|
|
|
Output (stdout & stderr) are not filtered in any way. Hooks should generally
|
|
not be too verbose. A short summary is nice, and some status information when
|
|
long running operations occur, but long/verbose output should be used only if
|
|
the hook ultimately fails.
|
|
|
|
The hook runs from the top level of the git repo where the operation is started.
|
|
e.g. If you're in the git repo `src/foo/`, that is where the hook runs, even if
|
|
the `repo` command was started from a subdir like `src/foo/bar/`.
|
|
|
|
Python's `sys.path` is modified so that the top of repohooks directory comes
|
|
first. This should help simplify the hook logic to easily allow importing of
|
|
local modules.
|
|
|
|
Repo does not modify the state of the git checkout. This means that the hooks
|
|
might be running in a dirty git repo with many commits and checked out to the
|
|
latest one. If the hook wants to operate on specific git commits, it needs to
|
|
manually discover the list of pending commits, extract the diff/commit, and
|
|
then check it directly. Hooks should not normally modify the active git repo
|
|
(such as checking out a specific commit to run checks) without first prompting
|
|
the user. Although user interaction is discouraged in the common case, it can
|
|
be useful when deploying automatic fixes.
|
|
|
|
## Hooks
|
|
|
|
Here are all the points available for hooking.
|
|
|
|
### pre-upload
|
|
|
|
This hook runs when people run `repo upload`.
|
|
|
|
The `pre-upload.py` file should be defined like:
|
|
|
|
```py
|
|
def main(project_list, worktree_list=None, **kwargs):
|
|
"""Main function invoked directly by repo.
|
|
|
|
We must use the name "main" as that is what repo requires.
|
|
|
|
Args:
|
|
project_list: List of projects to run on.
|
|
worktree_list: A list of directories. It should be the same length as
|
|
project_list, so that each entry in project_list matches with a
|
|
directory in worktree_list. If None, we will attempt to calculate
|
|
the directories automatically.
|
|
kwargs: Leave this here for forward-compatibility.
|
|
"""
|
|
```
|