User Tools

Site Tools


git_hooks

Git Hooks

pre-receive Hook (Server-Side)

This is a hook i use along with Gitlab. Its global and will be triggerd for all repositories when data is send to the server. When data is send to the server old and new revs will be compared depending on the changed files. If the changed files contain a file named

.do_not_merge__WHAT-EVER-YOUR-BRANCH-IS

the hook will check if the branch you are pushing to is not equal to WHAT-EVER-YOUR-BRANCH-IS and will refuse to merge.

In case WHAT-EVER-YOUR-BRANCH-IS is equal to the branch you try to push to the merge will not be refuse. This is because we want to be able to create the .do_not_merge file where necessary.

Setup

For Gitlab Omnibus installations place pre-receive file in this Folder (if it does not exist, create it) /opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d/

Make sure the file ist executable using chmod +x pre-receive

How it works

The branch you do not want to be merged in any other branch create a file named

.do_not_merge__THE-BRANCH-NAME

Make sure THE-BRANCH-NAME its exactly the same name as the Branch.

Given you have the branch develop and want to avoid merge into any other branch, simply create a file named

.do_not_merge__develop

Expected output in CLI

The Hook

pre-receive
#!/opt/gitlab/embedded/bin/ruby --disable-gems
# Fix the PATH so that gitlab-shell can find git-upload-pack and friends.
ENV['PATH'] = '/opt/gitlab/bin:/opt/gitlab/embedded/bin:' + ENV['PATH']
 
require 'net/http'
require 'json'
require 'cgi'
 
###################
# General variables
###################
refs = $stdin.read
key_id = ENV.delete('GL_ID')
proto = $stdin
protocol = ENV.delete('GL_PROTOCOL')
repo_path = Dir.pwd
gl_repository = ENV['GL_REPOSITORY']
 
# Read given hashes
hash = refs.split(' ')
hash_from = hash[0]
hash_to = hash[1]
@branch = hash[2]
 
#################
# Colorize output
#################
class String
    def red;            "\033[31m#{self}\033[0m" end
    def green;          "\033[32m#{self}\033[0m" end
    def blue;           "\033[34m#{self}\033[0m" end
end
 
##########################
# Pull a Chuck Norris Joke
##########################
def get_joke(author = '')
    begin
        plain_uri = 'http://api.icndb.com/jokes/random'        
        url = URI.parse(plain_uri)
        req = Net::HTTP::Get.new(url.to_s)
 
        res = Net::HTTP.start(url.host, url.port) {|http|
            http.request(req)
        }
        joke = CGI.unescapeHTML(JSON.parse(res.body)['value']['joke'])
 
    rescue StandardError
    	joke = "Chuck Norris never sleeps? Well, even Chuck Norris needs a power nap every once in a while ..."
    end  
 
    return joke
end
 
# Get changed files between hashes - check if commits contain file named '.do_not_merge'
changed_files = `git diff --name-only --stat #{hash_from}..#{hash_to}`.chop
do_not_merge = changed_files.split(/\n/)
 
##################################################
# Check if this is the .do_not_merge__ORIGIN Branch
##################################################
def is_not_origin_branch(origin_branch)
    current_branch = @branch.split(/\//).last
    origin_branch = origin_branch.split(/__/).last
    return current_branch != origin_branch
end
 
######################################
# Decide whether to ban or not to ban
######################################
do_not_merge.each do |file|    
    if (file[/^.do_not_merge__/])
        if(is_not_origin_branch(file))
            puts "☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️"
            puts get_joke().blue
            puts ""
            puts "The file #{file} stops you from pushing your changes to remote.".red
            puts "You don't want to commit your changes done in DO_NOT_MERGE Branch to master or any other Branch.".red
            puts ""
            puts "To reset your branch use 'git reset --hard origin/#{@branch.split(/\//).last}'. This will reset your Branch to the state of the origin/remote branch"
            puts "\n☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️  ☠️"
            exit 1
        end
    end
end                                                                                                                                                                

ToDo

  • Find a way to make hook output look pretty in Gitlab
git_hooks.txt · Last modified: 2017/12/20 02:34 by admin