Skip to content

Commit

Permalink
build: add author's GitHub id to changelog file
Browse files Browse the repository at this point in the history
OPA uses the changelog file to recognize people who contribute to the
project by mentioning them in it. This commit introduces a way to fetch
the GitHub handle for the commit authors if they are not listed in the
MAINTAINERS.md file. It makes use of the GitHub API to do so, and thus
introduces an optional cli argument to pass the token to authenticate
requests, without which you might run into rate limit errors if you run
the script a couple of times.

Fixes #2323
Signed-off-by: Aditya <aditya10699@gmail.com>
  • Loading branch information
Syn3rman authored and patrick-east committed May 21, 2020
1 parent 56f0652 commit 6f947f1
Showing 1 changed file with 72 additions and 5 deletions.
77 changes: 72 additions & 5 deletions build/changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
import subprocess
import shlex
import re
import urllib2
import sys
import json


def run(cmd, *args, **kwargs):
return subprocess.check_output(shlex.split(cmd), *args, **kwargs)
return subprocess.check_output(shlex.split(cmd), *args, **kwargs).decode('utf-8')


def get_commit_ids(from_commit, to_commit):
Expand All @@ -26,6 +29,67 @@ def get_commit_message(commit_id):
return run(cmd)


def fetch(url, token):
req = urllib2.Request(url)
if token:
req.add_header('Authorization', "token {}".format(token))
try:
rsp = urllib2.urlopen(req)
result = json.loads(rsp.read())
except Exception as e:
if hasattr(e, 'reason'):
print >> sys.stderr, 'Failed to fetch URL {}: {}'.format(url, e.reason)
elif hasattr(e, 'code'):
print >> sys.stderr, 'Failed to fetch URL {}: Code {}'.format(url, e.code)
return {}
else:
return result


def get_maintainers():
with open("MAINTAINERS.md", "r") as f:
contents = f.read()
maintainers = re.findall(r"[^\s]+@[^\s]+", contents)
return maintainers

maintainers = get_maintainers()


def is_maintainer(commit_message):
author = author_email(commit_message)
return author in maintainers


def author_email(commit_message):
match = re.search(r"<(.*@.*)>", commit_message)
author = match.group(1)
return str(author)


github_ids = {}
def get_github_id(commit_message, commit_id, token):
email = author_email(commit_message)
if github_ids.get(email, ""):
return github_ids[email]
url = "https://api.github.com/repos/open-policy-agent/opa/commits/{}".format(commit_id)
r = fetch(url, token)
author = r.get('author', {})
if author is None:
return ""
login = author.get('login', '')
if login:
github_ids[email]=login
return login
return ""


def mention_author(commit_message, commit_id, token):
username = get_github_id(commit_message, commit_id, token)
if username:
return "authored by @[{author}](https://github.com/{author})".format(author=username)
return ""


def fixes_issue_id(commit_message):
match = re.search(r"Fixes:?\s*#(\d+)", commit_message)
if match:
Expand All @@ -36,11 +100,11 @@ def get_subject(commit_message):
return commit_message.splitlines()[0]


def get_changelog_message(commit_message, repo_url):
def get_changelog_message(commit_message, mention, repo_url):
issue_id = fixes_issue_id(commit_message)
if issue_id:
subject = get_subject(commit_message)
return "Fixes", "{subject} ([#{issue_id}]({repo_url}/issues/{issue_id}))".format(subject=subject, issue_id=issue_id, repo_url=repo_url)
return "Fixes", "{subject} ([#{issue_id}]({repo_url}/issues/{issue_id})) {mention}".format(subject=subject, issue_id=issue_id, repo_url=repo_url, mention=mention)
return None, get_subject(commit_message)


Expand All @@ -53,6 +117,7 @@ def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument(
"--repo_url", default="https://github.com/open-policy-agent/opa")
parser.add_argument("--token", default="", help="GitHub API token")
parser.add_argument("from_version", nargs="?",
default=get_latest_tag(), help="start of changes")
parser.add_argument("to_commit", nargs="?",
Expand All @@ -64,10 +129,12 @@ def main():

args = parse_args()
changelog = {}

for commit_id in get_commit_ids(args.from_version, args.to_commit):
mention = ""
commit_message = get_commit_message(commit_id)
group, line = get_changelog_message(commit_message, args.repo_url)
if not is_maintainer(commit_message):
mention = mention_author(commit_message, commit_id, args.token)
group, line = get_changelog_message(commit_message, mention, args.repo_url)
changelog.setdefault(group, []).append(line)

if "Fixes" in changelog:
Expand Down

0 comments on commit 6f947f1

Please sign in to comment.