Git server hooks (FREE SELF)

  • Introduced in GitLab 12.8 replacing Custom Hooks.
  • Renamed from server hooks to Git server hooks in GitLab 15.6.

Git server hooks (not to be confused with system hooks or file hooks) run custom logic on the GitLab server. You can use them to run Git-related tasks such as:

  • Enforcing specific commit policies.
  • Performing tasks based on the state of the repository.

Git server hooks use pre-receive, post-receive, and update Git server-side hooks.

GitLab administrators configure server hooks on the file system of the GitLab server. If you don't have file system access, alternatives to server hooks include:

Geo doesn't replicate server hooks to secondary nodes.

Set server hooks for a repository

::Tabs

:::TabTitle GitLab 15.11 and later

Introduced in GitLab 15.11, hooks set command replaces direct file system access.

Prerequisites:

To set server hooks for a repository:

  1. Create tarball containing custom hooks:

    1. Write the code to make the server hook function as expected. Git server hooks can be in any programming language. Ensure the shebang at the top reflects the language type. For example, if the script is in Ruby the shebang is probably #!/usr/bin/env ruby.

      • To create a single server hook, create a file with a name that matches the hook type. For example, for a pre-receive server hook, the filename should be pre-receive with no extension.
      • To create many server hooks, create a directory for the hooks that matches the hook type. For example, for a pre-receive server hook, the directory name should be pre-receive.d. Put the files for the hook in that directory.
    2. Ensure the server hook files are executable and do not match the backup file pattern (*~). The server hooks be in a custom_hooks directory that is at the root of the tarball.

    3. Create the custom hooks archive with the tar command. For example, tar -cf custom_hooks.tar custom_hooks.

  2. Run the hooks set command with required options to set the Git hooks for the repository. For example, cat hooks.tar | gitaly hooks set --storage <storage> --repository <relative path> --config <config path>.

    • A path to a valid Gitaly configuration for the node is required to connect to the node and provided to the --config flag.
    • Custom hooks tarball must be passed via stdin. For example, cat hooks.tar | gitaly hooks set --storage <storage> --repository <relative path> --config <config path>.

If you implemented the server hook code correctly, it should execute when the Git hook is next triggered.

:::TabTitle GitLab 15.10 and earlier

To create server hooks for a repository:

  1. On the top bar, select Main menu > Admin.
  2. Go to Overview > Projects and select the project you want to add a server hook to.
  3. On the page that appears, locate the value of Gitaly relative path. This path is where server hooks must be located.
    • If you are using hashed storage, see Translate hashed storage paths for information on interpreting the relative path.
    • If you are not using hashed storage:
      • For Omnibus GitLab installations, the path is usually /var/opt/gitlab/git-data/repositories/<group>/<project>.git.
      • For an installation from source, the path is usually /home/git/repositories/<group>/<project>.git.
  4. On the file system, create a new directory in the correct location called custom_hooks.
  5. In the new custom_hooks directory:
    • To create a single server hook, create a file with a name that matches the hook type. For example, for a pre-receive server hook, the filename should be pre-receive with no extension.
    • To create many server hooks, create a directory for the hooks that matches the hook type. For example, for a pre-receive server hook, the directory name should be pre-receive.d. Put the files for the hook in that directory.
  6. Make the server hook files executable and ensure that they are owned by the Git user.
  7. Write the code to make the server hook function as expected. Git server hooks can be in any programming language. Ensure the shebang at the top reflects the language type. For example, if the script is in Ruby the shebang is probably #!/usr/bin/env ruby.
  8. Ensure the hook file does not match the backup file pattern (*~).

If the server hook code is properly implemented, it should execute when the Git hook is next triggered.

::EndTabs

Gitaly Cluster

If you use Gitaly Cluster, the scripts must be copied to every Gitaly node that has a replica of the repository. Every Gitaly node needs a copy because any node can be made a primary at any time. Server hooks only run on primary nodes.

The location to copy the scripts to depends on where repositories are stored:

Create global server hooks for all repositories

To create a Git hook that applies to all repositories, set a global server hook. Global server hooks also apply to:

  • Project and group wiki repositories. Their storage directory names are in the format <id>.wiki.git.
  • Design management repositories under a project. Their storage directory names are in the format <id>.design.git.

Choose a server hook directory

Before creating a global server hook, you must choose a directory for it.

For Omnibus GitLab installations, the directory is set in gitlab.rb under gitaly['configuration'][:hooks][:custom_hooks_dir]. You can either:

  • Use the default suggestion of the /var/opt/gitlab/gitaly/custom_hooks directory by uncommenting it.
  • Add your own setting.

For installations from source:

  • The directory is set in a configuration file. The location of the configuration file depends on the GitLab version:
    • For GitLab 13.1 and later, the directory is set in gitaly/config.toml under the [hooks] section. However, GitLab honors the custom_hooks_dir value in gitlab-shell/config.yml if the value in gitaly/config.toml is blank or non-existent.
    • For GitLab 13.0 and earlier, the directory set in gitlab-shell/config.yml.
  • The default directory is /home/git/gitlab-shell/hooks.

Create the global server hook

To create a global server hook for all repositories:

  1. On the GitLab server, go to the configured global server hook directory.
  2. In the configured global server hook directory, create a directory for the hooks that matches the hook type. For example, for a pre-receive server hook, the directory name should be pre-receive.d.
  3. Inside this new directory, add your server hooks. Git server hooks can be in any programming language. Ensure the shebang at the top reflects the language type. For example, if the script is in Ruby the shebang is probably #!/usr/bin/env ruby.
  4. Make the hook file executable, ensure that it's owned by the Git user, and ensure it does not match the backup file pattern (*~).

If the server hook code is properly implemented, it should execute when the Git hook is next triggered. Hooks are executed in alphabetical order by filename in the hook type subdirectories.

Remove server hooks for a repository

::Tabs

:::TabTitle GitLab 15.11 and later

Introduced in GitLab 15.11, hooks set command replaces direct file system access.

Prerequisites:

To remove server hooks, pass an empty tarball to hook set to indicate that the repository should contain no hooks. For example:

cat empty_hooks.tar | gitaly hooks set --storage <storage> --repository <relative path> --config <config path>`.

:::TabTitle GitLab 15.10 and earlier

To remove server hooks:

  1. Go to the location of the repository on disk.
  2. Delete the server hooks in the custom_hooks directory.

::EndTabs

Chained server hooks

GitLab can execute server hooks in a chain. GitLab searches for and executes server hooks in the following order:

  • Built-in GitLab server hooks. These server hooks are not customizable by users.
  • <project>.git/custom_hooks/<hook_name>: Per-project hooks. This location is kept for backwards compatibility.
  • <project>.git/custom_hooks/<hook_name>.d/*: Location for per-project hooks.
  • <custom_hooks_dir>/<hook_name>.d/*: Location for all executable global hook files except editor backup files.

Within a server hooks directory, hooks:

  • Are executed in alphabetical order.
  • Stop executing when a hook exits with a non-zero value.

Environment variables available to server hooks

You can pass any environment variable to server hooks, but you should only rely on supported environment variables.

The following GitLab environment variables are supported for all server hooks:

Environment variable Description
GL_ID GitLab identifier of user that initiated the push. For example, user-2234.
GL_PROJECT_PATH (GitLab 13.2 and later) GitLab project path.
GL_PROTOCOL (GitLab 13.2 and later) Protocol used for this change. One of: http (Git push using HTTP), ssh (Git push using SSH), or web (all other actions).
GL_REPOSITORY project-<id> where id is the ID of the project.
GL_USERNAME GitLab username of the user that initiated the push.

The following Git environment variables are supported for pre-receive and post-receive server hooks:

Environment variable Description
GIT_ALTERNATE_OBJECT_DIRECTORIES Alternate object directories in the quarantine environment. See Git receive-pack documentation.
GIT_OBJECT_DIRECTORY GitLab project path in the quarantine environment. See Git receive-pack documentation.
GIT_PUSH_OPTION_COUNT Number of push options. See Git pre-receive documentation.
GIT_PUSH_OPTION_<i> Value of push options where i is from 0 to GIT_PUSH_OPTION_COUNT - 1. See Git pre-receive documentation.

Custom error messages

You can have custom error messages appear in the GitLab UI when a commit is declined or an error occurs during the Git hook. To display a custom error message, your script must:

  • 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.

For example:

#!/bin/sh
echo "GL-HOOK-ERR: My custom error message.";
exit 1