Server-side pre-receive hooks with GitLab

Posted by : on

Category : powershell   scripts   network


GitLab: Pre-receive hooks

In GitLab, adding a pre-receive hook is not as straightforward as on a self-hosted Git server because GitLab does not provide direct access to the Git repository on the server. However, you can still use custom Git hooks by leveraging the GitLab’s server hooks feature available for self-managed GitLab instances.

Here’s how you can add a pre-receive hook in GitLab:

1. Ensure You’re Using a Self-Managed GitLab Instance

  • This method is only available if you’re running a self-managed GitLab instance (not for GitLab.com or cloud-hosted GitLab).
  • You need administrator access to the GitLab server to configure custom hooks.

2. Locate the GitLab Hooks Directory

GitLab has a centralized hooks directory where you can place hooks for all repositories.

The default location for this directory is:

   /opt/gitlab/embedded/service/gitlab-shell/hooks

The hooks you place in this directory will be applied to all repositories managed by GitLab.

3. Create the Pre-Receive Hook

Inside the hooks directory, create a pre-receive hook. This script will be executed every time a push is made to the GitLab server.

   cd /opt/gitlab/embedded/service/gitlab-shell/hooks
   sudo touch pre-receive
   sudo chmod +x pre-receive

Open the pre-receive file using your preferred editor:

   sudo nano pre-receive

Add the necessary logic to the pre-receive hook script. For example, here’s a basic script that prevents force pushes to the main branch:

   #!/bin/sh
   # Prevent force pushes to the main branch

   while read oldrev newrev refname
   do
       if [ "$refname" = "refs/heads/main" ]; then
           # Ensure it's not a force push
           if ! git merge-base --is-ancestor $oldrev $newrev; then
               echo "Force pushing to the main branch is not allowed!"
               exit 1
           fi
       fi
   done

   exit 0

4. Make the Hook Executable

Make sure the hook script is executable:

   sudo chmod +x /opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive

5. Restart GitLab (Optional)

In most cases, GitLab will automatically pick up changes to hooks, but you may want to restart GitLab to ensure everything is loaded correctly:

   sudo gitlab-ctl restart

6. Testing the Hook

After setting up the pre-receive hook, you can test it by making a push to the repository. The pre-receive hook will run every time a user pushes to any repository on the GitLab instance.

For example, try force-pushing to the main branch from a client:

git push --force origin main

If the hook is configured properly, the push should be blocked with the message Force pushing to the main branch is not allowed!.


Advanced: Repository-Specific Hooks

If you want a pre-receive hook for specific repositories rather than all repositories on your GitLab instance, you can:

  1. Find the repository’s storage location: GitLab stores each repository as a bare Git repository on the server. You can find the repository path from the admin area or by checking the GitLab configuration files.

  2. Add hooks to that specific repository: After locating the repository’s .git/hooks directory, you can add the pre-receive hook there. Note that this is not recommended because GitLab periodically overwrites hooks in individual repositories, so using the global hooks directory is the preferred method.


GitLab Custom Hooks Using GitLab API or GitLab CI

If you are not on a self-managed GitLab instance or do not have server access, you can achieve similar results using GitLab CI or GitLab’s API:

  • GitLab CI: Instead of a pre-receive hook, you can create a GitLab CI pipeline that checks certain conditions on commits or branches (e.g., code style, commit messages, etc.), and fails the build if necessary.
  • GitLab API: Use the GitLab API to automate repository actions, such as preventing certain pushes or enforcing rules through bots or external scripts.

Summary:

  • Pre-receive hooks in GitLab are available only for self-managed GitLab instances.
  • Place the hook script in the global hooks directory (/opt/gitlab/embedded/service/gitlab-shell/hooks).
  • Write your pre-receive hook logic in a script and make it executable.
  • For more granular control, use GitLab CI or the GitLab API if server access is not available.

This method ensures that all repositories on your GitLab server are governed by the pre-receive hook.


About Guillaume Plante
Guillaume Plante

A developper with a passion for technology, music, astronomy and art. Coding range: hardware/drivers, security, ai,. c/c++, powershell

Email : guillaumeplante.qc@gmail.com

Website : https://arsscriptum.ddns.net

Useful Links