Skip to content

Instantly share code, notes, and snippets.

@frakman1
Last active November 15, 2022 17:16
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frakman1/7d70fb15d0d8900e9028788579bec9f7 to your computer and use it in GitHub Desktop.
Save frakman1/7d70fb15d0d8900e9028788579bec9f7 to your computer and use it in GitHub Desktop.
pre-receive hook in python to enforce commit message rules (and log violations)
#!/usr/bin/python
# coding: utf-8
import sys
import re
import subprocess
import datetime
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKCYAN = '\033[96m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BLINK = '\033[5m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
# Return a timestamped version of an input stirng
def timeStamped(fname, fmt='%Y-%m-%d-%H-%M-%S: {fname}'):
return datetime.datetime.now().strftime(fmt).format(fname=fname)
#Format: "oldref newref branch"
line = sys.stdin.read() ; #print("input line:", line)
(base, commit, ref) = line.strip().split() ; #print("base:",base); #print("commit:",commit); #print("ref:",ref)
new_branch_push = re.match(r'[0]{40}', base) #if base/oldref is all zeros
branch_deleted = re.match(r'[0]{40}', commit) #if commit/newref is all zeros
contains_commit_msg = False
if branch_deleted:
#print("This is a Deleted Branch. Return success")
exit(0)
if new_branch_push:
revs = commit
#print("New branch")
else:
revs = base + "..." + commit
#print("NOT New branch")
#print("revs:", revs)
proc = subprocess.Popen(['git', 'rev-list','--oneline','--first-parent', revs], stdout=subprocess.PIPE)
lines = proc.stdout.readlines() ; #print("lines:",lines)
lastline = lines[0] ; #print("lastline:",lastline)
rev = str(lastline) ; #print("rev:",rev)
match = re.search(r'DPK2-[0-9]+|DPK-[0-9]+|TDETS-[0-9]+|[Ff]ix.*[Bb]uild [eE]rror|CCIFE|<tidy>|<force>|<cleanup>|<hotfix>|Merge branch', rev) ; #print("match:",match)
if match is not None:
contains_commit_msg = True
print(bcolors.OKGREEN + "<<Commit Message Accepted>>" + bcolors.ENDC)
#print("contains_commit_msg:",contains_commit_msg, "new_branch_push:",new_branch_push)
if contains_commit_msg:
print(bcolors.OKGREEN + "<<Commit Message Accepted>>" + bcolors.ENDC)
exit(0)
else:
# print "Commit does not contain the ticket associated with the commit in the format: TDETS-123 or DPK2-1234"
# sys.stderr.write(" ***REJECTED***\n")
print (bcolors.FAIL + bcolors.BLINK + " ================================================================= " + bcolors.ENDC);
print (bcolors.FAIL + bcolors.BLINK + " ██████╗ ███████╗ ██╗███████╗ ██████╗████████╗███████╗██████╗ " + bcolors.ENDC);
print (bcolors.FAIL + bcolors.BLINK + " ██╔══██╗██╔════╝ ██║██╔════╝██╔════╝╚══██╔══╝██╔════╝██╔══██╗ " + bcolors.ENDC);
print (bcolors.FAIL + bcolors.BLINK + " ██████╔╝█████╗ ██║█████╗ ██║ ██║ █████╗ ██║ ██║ " + bcolors.ENDC);
print (bcolors.FAIL + bcolors.BLINK + " ██╔══██╗██╔══╝ ██ ██║██╔══╝ ██║ ██║ ██╔══╝ ██║ ██║ " + bcolors.ENDC);
print (bcolors.FAIL + bcolors.BLINK + " ██║ ██║███████╗╚█████╔╝███████╗╚██████╗ ██║ ███████╗██████╔╝ " + bcolors.ENDC);
print (bcolors.FAIL + bcolors.BLINK + " ╚═╝ ╚═╝╚══════╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚══════╝╚═════╝ " + bcolors.ENDC);
print (bcolors.FAIL + bcolors.BLINK + " ================================================================= " + bcolors.ENDC);
print (bcolors.FAIL + " You forgot to add a JIRA issue number to the commit title. " + bcolors.ENDC);
print (bcolors.FAIL + " eg. TDETS-1234 or DPK2-1234 or DPK-1234 or CCIFE tag " + bcolors.ENDC);
print (bcolors.FAIL + " do a 'git commit --amend' and try again " + bcolors.ENDC);
print (bcolors.FAIL + " Commit Message: " + bcolors.ENDC);
print (bcolors.FAIL + " " + rev + bcolors.ENDC);
print (bcolors.FAIL + " ================================================================= " + bcolors.ENDC);
#log the violation to a file
proc = subprocess.Popen(['git', '--no-pager','show','-s','--format="%an <%ae>"',commit ], stdout=subprocess.PIPE)
lines = proc.stdout.readlines(); #print (lines)
with open("./violationLog.txt", "a") as myfile:
myfile.write(timeStamped(str(rev).rstrip('\n'))+" by: " + str(lines[0].rstrip('\n')))
myfile.write("\n")
exit(1)
@frakman1
Copy link
Author

frakman1 commented Apr 30, 2018

Written for Gitlab. Handles New Branches, Deleted Branches and Merge Requests

Place this file in your project's xxx.git/custom_hooks folder.

  • Ensure that the custom_hooks folder exists and create it if it doesn't.
  • Ensure that the pre-receive file exists and create it if it doesn't.
  • Ensure both folder and file owner:group is git:git using chown -R git:git custom_hooks/
  • Ensure it is executable using chmod +x custom_hooks/pre-receive

It will look like this:

Alt Text

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