Мы используем Gitlab, поэтому для нас имеет смысл проверять авторов на наличие членов группы Gitlab.
Следующий скрипт (на основе ответа @ dsvensson), который должен быть установлен как ловушка предварительного приема, делает именно это:
from __future__ import print_function
from __future__ import unicode_literals
import sys
import os
import subprocess
import urllib2
import json
import contextlib
import codecs
from itertools import islice, izip
GITLAB_SERVER = 'https://localhost'
GITLAB_TOKEN = 'SECRET'
GITLAB_GROUP = 4
EMAIL_DOMAIN = 'example.com'
def main():
commits = get_commits_from_push()
authors = get_gitlab_group_members()
for commit, author, email in commits:
if author not in authors:
die('Unknown author', author, commit, authors)
if email != authors[author]:
die('Unknown email', email, commit, authors)
def get_commits_from_push():
old, new, branch = sys.stdin.read().split()
rev_format = '--pretty=format:%an%n%ae'
command = ['git', 'rev-list', rev_format, '{0}..{1}'.format(old, new)]
# branch delete, let it through
if new == '0000000000000000000000000000000000000000':
sys.exit(0)
# new branch
if old == '0000000000000000000000000000000000000000':
command = ['git', 'rev-list', rev_format, new, '--not', '--branches=*']
output = subprocess.check_output(command)
commits = [line.strip() for line in unicode(output, 'utf-8').split('\n') if line.strip()]
return izip(islice(commits, 0, None, 3),
islice(commits, 1, None, 3),
islice(commits, 2, None, 3))
def get_gitlab_group_members():
url = '{0}/api/v3/groups/{1}/members'.format(GITLAB_SERVER, GITLAB_GROUP)
headers = {'PRIVATE-TOKEN': GITLAB_TOKEN}
request = urllib2.Request(url, None, headers)
with contextlib.closing(urllib2.urlopen(request)) as response:
members = json.load(response)
return dict((member['name'], '{}@{}'.format(member['username'], EMAIL_DOMAIN))
for member in members)
def die(reason, invalid_value, commit, authors):
message = []
message.append('*' * 80)
message.append("ERROR: {0} '{1}' in {2}"
.format(reason, invalid_value, commit))
message.append('-' * 80)
message.append('Allowed authors and emails:')
print('\n'.join(message), file=sys.stderr)
for name, email in authors.items():
print(u" '{0} <{1}>'".format(name, email), file=sys.stderr)
sys.exit(1)
def set_locale(stream):
return codecs.getwriter('utf-8')(stream)
if __name__ == '__main__':
# avoid Unicode errors in output
sys.stdout = set_locale(sys.stdout)
sys.stderr = set_locale(sys.stderr)
# you may want to skip HTTPS certificate validation:
# import ssl
# if hasattr(ssl, '_create_unverified_context'):
# ssl._create_default_https_context = ssl._create_unverified_context
main()
См. GitLab custom Git hooks docs для инструкций по установке.
Только get_gitlab_group_members()
является специфичным для Gitlab, другая логика применяется к любой ловушке перед получением (включая обработку удалений и созданий ветвей).
Сценарий теперь доступен в GitHub , пожалуйста, не стесняйтесь посылать запросы на извлечение для любых ошибок / улучшений.