Skip to content

Instantly share code, notes, and snippets.

@mbrehin
Last active Nov 24, 2017
Embed
What would you like to do?
Git `update` hook (server side)
#!/usr/bin/ruby
# Enforce custom commit message format
def check_message_format(refname, oldrev, newrev)
message_format_regex = /\[ref: (\d+)\]/
# You would probably have to adjust the way you're retrieving user identity.
# You can also load user identity from each analysed commit.
user = ENV['USER']
# Initialize empty map to store errors
errors = []
puts "Enforcing Policie on #{refname} (#{oldrev[0,6]}..#{newrev[0,6]})…"
missed_revs = `git rev-list #{oldrev}..#{newrev}`.split("\n")
missed_revs.each do |rev|
message = `git cat-file commit #{rev} | sed '1,/^$/d'`
# Check if current commit message matched expected format
if !message_format_regex.match(message)
# If user wasn't loaded, then try to load it from first commit
user = `git show -s --pretty=format:'%an' #{rev}` unless user
errors << rev[0,6]
end
end
# Print errors to STDOUT when something went wrong
if errors.any?
puts_red "[POLICY] 😡 Shame to #{user}!"
if errors.size > 1
puts_red "[POLICY] 😱 Some messages are not formatted correctly (commits #{errors.join(', ')})"
else
puts_red "[POLICY] 😨 Commit #{errors.first} message is not well formatted"
end
exit 1
end
end
# We don't want any user to push on master.
# This can be done using protecting branches on GitHub, GitLab and many other Git servers.
def prevent_master_update(refname)
if refname =~ /(refs\/)?(heads\/)?master/
puts_red "You are not allowed to push to `master`"
exit 1
end
end
# Print message in red
def puts_red(message)
puts "\e[31m#{message}\e[0m"
end
puts 'Running update hook…'
# Loads values from STDIN
refname, oldrev, newrev = *ARGV
prevent_master_update(refname)
check_message_format(refname, oldrev, newrev)
puts 'Everything went fine! 👏'
@mbrehin
Copy link
Author

mbrehin commented Nov 24, 2017

How to install on GitLab CE?

Here is a summary of GitLab custom hooks behavior.
Create a custom_hooks subdirectory in your project path with the expected file:

mkdir /var/opt/gitlab/git-data/repositories/<group>/<project>.git/custom_hooks
vi /var/opt/gitlab/git-data/repositories/<group>/<project>.git/custom_hooks/update

[copy/paste hook then save] 

chmod +x /var/opt/gitlab/git-data/repositories/<group>/<project>.git/custom_hooks/update

And you're done!

More about that example

That example has been inspired (not to say copy/pasted) from Git SCM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment