Skip to content

Auto create custom_hooks when create project

  1. custom_hooks hold all group and project hooks.

  2. custom_hooks project in gitlab

  3. custom_hook hook him self

  4. custom_hook auto update himself on gitlab.

  5. custom_hooks patch auto create custom_hooks when create project.

Patch for gitlab-shell:

--- gitlab-shell/lib/gitlab_projects.rb.bak	2015-12-22 14:23:31.583468111 +0800
+++ gitlab-shell/lib/gitlab_projects.rb	2015-12-22 14:49:03.271317753 +0800
@@ -6,6 +6,7 @@ require_relative 'gitlab_logger'
 
 class GitlabProjects
   GLOBAL_HOOKS_DIRECTORY = File.join(ROOT_PATH, 'hooks')
+  GLOBAL_CUSTOM_HOOKS_DIRECTORY = File.join(ROOT_PATH, 'custom_hooks')
 
   # Project name is a directory name for repository with .git at the end
   # It may be namespaced or not. Like repo.git or gitlab/repo.git
@@ -21,13 +22,21 @@ class GitlabProjects
 
   def self.create_hooks(path)
     local_hooks_directory = File.join(path, 'hooks')
+    local_custom_hooks_directory = File.join(path, 'custom_hooks')
     real_local_hooks_directory = :not_found
+    real_local_custom_hooks_directory = :not_found
     begin
       real_local_hooks_directory = File.realpath(local_hooks_directory)
     rescue Errno::ENOENT
       # real_local_hooks_directory == :not_found
     end
 
+    begin
+      real_local_hooks_directory = File.realpath(local_custom_hooks_directory)
+    rescue Errno::ENOENT
+      # real_local_custom_hooks_directory == :not_found
+    end
+
     if real_local_hooks_directory != File.realpath(GLOBAL_HOOKS_DIRECTORY)
       if File.exist?(local_hooks_directory)
         $logger.info "Moving existing hooks directory and symlinking global hooks directory for #{path}."
@@ -38,6 +47,17 @@ class GitlabProjects
       $logger.info "Hooks already exist for #{path}."
       true
     end
+
+    if real_local_custom_hooks_directory != File.realpath(GLOBAL_HOOKS_DIRECTORY)
+      if File.exist?(local_custom_hooks_directory)
+        $logger.info "Moving existing hooks directory and symlinking global hooks directory for #{path}."
+        FileUtils.mv(local_custom_hooks_directory, "#{local_custom_hooks_directory}.old.#{Time.now.to_i}")
+      end
+      FileUtils.ln_sf(GLOBAL_CUSTOM_HOOKS_DIRECTORY, local_custom_hooks_directory)
+    else
+      $logger.info "Custom hooks already exist for #{path}."
+      true
+    end
   end
 
   def initialize

custom_hooks project Files

custom_hooks
├── custom #Group name this is custom_hooks hook
│   ├── post-receive 
│   └── pre-receive 
├── other_group #Other Group name
│   └── pre-receive #Other Group post-receive
├── ...
├── ...
├── another_group
│   ├── post-receive
│   └── pre-receive
├── post-receive #hold group name and run group post-receive hooks
└── pre-receive  #hold group name and run group pre-receive

post-receive content:

#!/bin/bash
#BASH_SOURCE

#echo "Running $BASH_SOURCE"
CUR_HOOK_DIR=`dirname $BASH_SOURCE`
GIT_FULLPATH=$PWD
GIT_NAME=`basename $GIT_FULLPATH`
GIT_GROUPPATH=`dirname $GIT_FULLPATH`
GIT_GROUPNAME=`basename $GIT_GROUPPATH`
X_RECEIVE=post-receive
GROUP_HOOK=$CUR_HOOK_DIR/$GIT_GROUPNAME/$X_RECEIVE

export CUR_HOOK_DIR
export GIT_FULLPATH
export GIT_NAME
export GIT_GROUPPATH
export GIT_GROUPNAME
export X_RECEIVE
export GROUP_HOOK

echo "	check $X_RECEIVE"
if [ -f $GROUP_HOOK ]; then
	echo "	found $X_RECEIVE: run"
	echo "	$GIT_GROUPNAME/$X_RECEIVE"
	$GROUP_HOOK $@
else
	echo "$X_RECEIVE not found"
fi

pre-receive content:

#!/bin/bash
#BASH_SOURCE

#echo "Running $BASH_SOURCE"
CUR_HOOK_DIR=`dirname $BASH_SOURCE`
GIT_FULLPATH=$PWD
GIT_NAME=`basename $GIT_FULLPATH`
GIT_GROUPPATH=`dirname $GIT_FULLPATH`
GIT_GROUPNAME=`basename $GIT_GROUPPATH`
X_RECEIVE=pre-receive
GROUP_HOOK=$CUR_HOOK_DIR/$GIT_GROUPNAME/$X_RECEIVE

echo "-------------------------------------"
echo "     repo : $GIT_NAME"
echo "     group: $GIT_GROUPNAME"
echo "-------------------------------------"
echo "	check $X_RECEIVE"
if [ -f $GROUP_HOOK ]; then
	echo "	found $X_RECEIVE: found"
	echo "	$GIT_GROUPNAME/$X_RECEIVE"
	$GROUP_HOOK $@
else
	echo "$X_RECEIVE not found"
fi

custom/post-receive content:

#!/bin/bash

user=username
password=password
custom_hooks_path="/opt/gitlab/embedded/service/gitlab-shell/custom_hooks"
if [ $GIT_NAME = "custom_hooks.git" ]; then
    sshpass -p $password ssh username@gitlab.domain "cd $custom_hooks_path"; git pull"
fi

Auto create hooks result

gitlab:/opt/gitlab-opt/gitlab/git-data/repositories/gdzhang/test.git# ls ../test2.git/ -l
total 16
-rw-r--r-- 1 git git   91 12月 22 14:49 config
lrwxrwxrwx 1 git git   54 12月 22 14:49 custom_hooks -> /opt/gitlab/embedded/service/gitlab-shell/custom_hooks
-rw-r--r-- 1 git git   73 12月 22 14:49 description
-rw-r--r-- 1 git git   23 12月 22 14:49 HEAD
lrwxrwxrwx 1 git git   47 12月 22 14:49 hooks -> /opt/gitlab/embedded/service/gitlab-shell/hooks