2019-04-29 16:43:54 -04:00
|
|
|
# Custom server-side Git hooks
|
2016-07-05 08:04:44 -04:00
|
|
|
|
2019-04-29 16:43:54 -04:00
|
|
|
NOTE: **Note:**
|
|
|
|
Custom Git hooks must be configured on the filesystem of the GitLab
|
2016-07-05 08:04:44 -04:00
|
|
|
server. Only GitLab server administrators will be able to complete these tasks.
|
2018-05-30 05:01:24 -04:00
|
|
|
Please explore [webhooks] and [CI] as an option if you do not
|
2018-02-22 11:13:35 -05:00
|
|
|
have filesystem access. For a user configurable Git hook interface, see
|
|
|
|
[Push Rules](https://docs.gitlab.com/ee/push_rules/push_rules.html),
|
|
|
|
available in GitLab Enterprise Edition.
|
2016-07-05 08:04:44 -04:00
|
|
|
|
2019-05-05 11:21:25 -04:00
|
|
|
NOTE: **Note:**
|
|
|
|
Custom Git hooks won't be replicated to secondary nodes if you use [GitLab Geo][gitlab-geo]
|
|
|
|
|
2016-07-05 08:04:44 -04:00
|
|
|
Git natively supports hooks that are executed on different actions.
|
|
|
|
Examples of server-side git hooks include pre-receive, post-receive, and update.
|
|
|
|
See [Git SCM Server-Side Hooks][hooks] for more information about each hook type.
|
|
|
|
|
|
|
|
As of gitlab-shell version 2.2.0 (which requires GitLab 7.5+), GitLab
|
|
|
|
administrators can add custom git hooks to any GitLab project.
|
|
|
|
|
2019-04-29 16:43:54 -04:00
|
|
|
## Create a custom Git hook for a repository
|
2016-07-05 08:04:44 -04:00
|
|
|
|
2019-04-29 16:43:54 -04:00
|
|
|
Server-side Git hooks are typically placed in the repository's `hooks`
|
|
|
|
subdirectory. In GitLab, hook directories are are symlinked to the gitlab-shell
|
|
|
|
`hooks` directory for ease of maintenance between gitlab-shell upgrades.
|
|
|
|
Custom hooks are implemented differently, but the behavior is exactly the same
|
|
|
|
once the hook is created. Follow the steps below to set up a custom hook for a
|
|
|
|
repository:
|
2016-07-05 08:04:44 -04:00
|
|
|
|
|
|
|
1. Pick a project that needs a custom Git hook.
|
|
|
|
1. On the GitLab server, navigate to the project's repository directory.
|
|
|
|
For an installation from source the path is usually
|
|
|
|
`/home/git/repositories/<group>/<project>.git`. For Omnibus installs the path is
|
|
|
|
usually `/var/opt/gitlab/git-data/repositories/<group>/<project>.git`.
|
|
|
|
1. Create a new directory in this location called `custom_hooks`.
|
|
|
|
1. Inside the new `custom_hooks` directory, create a file with a name matching
|
|
|
|
the hook type. For a pre-receive hook the file name should be `pre-receive`
|
|
|
|
with no extension.
|
|
|
|
1. Make the hook file executable and make sure it's owned by git.
|
|
|
|
1. Write the code to make the Git hook function as expected. Hooks can be
|
|
|
|
in any language. Ensure the 'shebang' at the top properly reflects the language
|
|
|
|
type. For example, if the script is in Ruby the shebang will probably be
|
|
|
|
`#!/usr/bin/env ruby`.
|
|
|
|
|
|
|
|
That's it! Assuming the hook code is properly implemented the hook will fire
|
|
|
|
as appropriate.
|
|
|
|
|
2019-04-29 16:43:54 -04:00
|
|
|
## Set a global Git hook for all repositories
|
|
|
|
|
|
|
|
To create a Git hook that applies to all of your repositories in
|
|
|
|
your instance, set a global Git hook. Since all the repositories' `hooks`
|
|
|
|
directories are symlinked to gitlab-shell's `hooks` directory, adding any hook
|
|
|
|
to the gitlab-shell `hooks` directory will also apply it to all repositories. Follow
|
2019-05-05 11:21:25 -04:00
|
|
|
the steps below to properly set up a custom hook for all repositories:
|
2019-04-29 16:43:54 -04:00
|
|
|
|
|
|
|
1. On the GitLab server, navigate to the configured custom hook directory. The
|
|
|
|
default is in the gitlab-shell directory. The gitlab-shell `hook` directory
|
|
|
|
for an installation from source the path is usually
|
|
|
|
`/home/git/gitlab-shell/hooks`. For Omnibus installs the path is usually
|
|
|
|
`/opt/gitlab/embedded/service/gitlab-shell/hooks`.
|
|
|
|
To look in a different directory for the global custom hooks,
|
|
|
|
set `custom_hooks_dir` in the gitlab-shell config. For
|
|
|
|
Omnibus installations, this can be set in `gitlab.rb`; and in source
|
|
|
|
installations, this can be set in `gitlab-shell/config.yml`.
|
|
|
|
1. Create a new directory in this location. Depending on your hook, it will be
|
|
|
|
either a `pre-receive.d`, `post-receive.d`, or `update.d` directory.
|
|
|
|
1. Inside this new directory, add your hook. Hooks can be
|
|
|
|
in any language. Ensure the 'shebang' at the top properly reflects the language
|
|
|
|
type. For example, if the script is in Ruby the shebang will probably be
|
|
|
|
`#!/usr/bin/env ruby`.
|
|
|
|
1. Make the hook file executable and make sure it's owned by Git.
|
|
|
|
|
|
|
|
Now test the hook to see that it's functioning properly.
|
|
|
|
|
2016-10-06 13:50:47 -04:00
|
|
|
## Chained hooks support
|
|
|
|
|
2016-12-12 08:30:50 -05:00
|
|
|
> [Introduced][93] in GitLab Shell 4.1.0 and GitLab 8.15.
|
2016-10-06 13:50:47 -04:00
|
|
|
|
2019-04-29 16:43:54 -04:00
|
|
|
Hooks can be also global or be set per project directories and support a chained
|
2016-12-12 08:30:50 -05:00
|
|
|
execution of the hooks.
|
|
|
|
|
2019-04-29 16:43:54 -04:00
|
|
|
NOTE: **Note:**
|
|
|
|
`<hook_name>.d` would need to be either `pre-receive.d`,
|
2019-03-20 00:08:51 -04:00
|
|
|
`post-receive.d`, or `update.d` to work properly. Any other names will be ignored.
|
2018-10-08 07:41:35 -04:00
|
|
|
|
2019-04-29 16:43:54 -04:00
|
|
|
NOTE: **Note:**
|
|
|
|
Files in `.d` directories need to be executable and not match the backup file
|
|
|
|
pattern (`*~`).
|
2016-10-06 13:50:47 -04:00
|
|
|
|
|
|
|
The hooks are searched and executed in this order:
|
2016-12-12 08:30:50 -05:00
|
|
|
|
2018-11-09 03:33:56 -05:00
|
|
|
1. `gitlab-shell/hooks` directory as known to Gitaly
|
2019-04-29 16:43:54 -04:00
|
|
|
1. `<project>.git/hooks/<hook_name>` - executed by `git` itself, this is symlinked to `gitlab-shell/hooks/<hook_name>`
|
2016-10-06 13:50:47 -04:00
|
|
|
1. `<project>.git/custom_hooks/<hook_name>` - per project hook (this is already existing behavior)
|
|
|
|
1. `<project>.git/custom_hooks/<hook_name>.d/*` - per project hooks
|
2016-12-12 08:30:50 -05:00
|
|
|
1. `<project>.git/hooks/<hook_name>.d/*` OR `<custom_hooks_dir>/<hook_name.d>/*` - global hooks: all executable files (minus editor backup files)
|
2016-10-06 13:50:47 -04:00
|
|
|
|
2016-12-12 08:30:50 -05:00
|
|
|
The hooks of the same type are executed in order and execution stops on the
|
|
|
|
first script exiting with a non-zero value.
|
2016-10-06 13:50:47 -04:00
|
|
|
|
2016-07-05 08:04:44 -04:00
|
|
|
## Custom error messages
|
|
|
|
|
2016-08-08 04:09:54 -04:00
|
|
|
> [Introduced][5073] in GitLab 8.10.
|
2016-07-05 08:04:44 -04:00
|
|
|
|
2019-03-20 00:08:51 -04:00
|
|
|
To have custom error messages appear in GitLab's UI when the commit is
|
|
|
|
declined or an error occurs during the Git hook, your script should:
|
|
|
|
|
|
|
|
- Send the custom error messages to either the script's `stdout` or `stderr`.
|
|
|
|
- Prefix each message with `GL-HOOK-ERR:` with no characters appearing before the prefix.
|
|
|
|
|
|
|
|
### Example custom error message
|
|
|
|
|
|
|
|
This hook script written in bash will generate the following message in GitLab's UI:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
#!/bin/sh
|
|
|
|
echo "GL-HOOK-ERR: My custom error message.";
|
|
|
|
exit 1
|
|
|
|
```
|
2016-07-05 08:04:44 -04:00
|
|
|
|
|
|
|
![Custom message from custom Git hook](img/custom_hooks_error_msg.png)
|
|
|
|
|
2018-05-30 07:47:30 -04:00
|
|
|
[CI]: ../ci/README.md
|
2016-07-05 08:04:44 -04:00
|
|
|
[hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#Server-Side-Hooks
|
2017-02-03 13:26:48 -05:00
|
|
|
[webhooks]: ../user/project/integrations/webhooks.md
|
2019-05-05 11:21:25 -04:00
|
|
|
[gitlab-geo]: https://docs.gitlab.com/ee/administration/geo/replication/index.html
|
2016-07-05 08:04:44 -04:00
|
|
|
[5073]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5073
|
2016-10-06 13:50:47 -04:00
|
|
|
[93]: https://gitlab.com/gitlab-org/gitlab-shell/merge_requests/93
|