mirror of https://github.com/lukechilds/damus.git
1 changed files with 171 additions and 0 deletions
@ -0,0 +1,171 @@ |
|||||
|
#!/usr/bin/env python3 |
||||
|
# Copied from ElementsProject/lightning, thanks! :) |
||||
|
|
||||
|
from collections import namedtuple |
||||
|
from datetime import datetime |
||||
|
from mako.template import Template |
||||
|
import argparse |
||||
|
import os |
||||
|
import re |
||||
|
import requests |
||||
|
import shlex |
||||
|
import subprocess |
||||
|
import sys |
||||
|
|
||||
|
# What sections do we support in the changelog: |
||||
|
sections = [ |
||||
|
'added', |
||||
|
'changed', |
||||
|
'deprecated', |
||||
|
'fixed', |
||||
|
'removed', |
||||
|
'experimental', |
||||
|
] |
||||
|
|
||||
|
repo = 'damus-io/damus' |
||||
|
|
||||
|
Entry = namedtuple("Entry", ["commit", "pullreq", "content", "section"]) |
||||
|
Link = namedtuple("Link", ["ref", "content", "url"]) |
||||
|
|
||||
|
|
||||
|
def git(cmd): |
||||
|
cmd = shlex.split(cmd) |
||||
|
out = subprocess.check_output(['git'] + cmd) |
||||
|
return out.decode('UTF-8') |
||||
|
|
||||
|
|
||||
|
def get_commit_range(): |
||||
|
"""Find a commit range that we should collect the CHANGELOG for. |
||||
|
""" |
||||
|
description = git("describe") |
||||
|
version = description.split('-')[0] |
||||
|
return "{version}..master".format(version=version) |
||||
|
|
||||
|
|
||||
|
def get_log_entries(commitrange): |
||||
|
commit = None |
||||
|
logs = git("log {commitrange}".format(commitrange=commitrange)) |
||||
|
entries = [] |
||||
|
|
||||
|
for l in logs.split('\n'): |
||||
|
m = re.match(r'^commit ([A-Fa-f0-9]{40})$', l) |
||||
|
if m: |
||||
|
commit = m.group(1) |
||||
|
|
||||
|
m = re.match( |
||||
|
r'^\s+Changelog-({}): (.*)$'.format("|".join(sections)), l, re.IGNORECASE) |
||||
|
if not m: |
||||
|
continue |
||||
|
|
||||
|
# Now try to resolve the pull request that originated this commit: |
||||
|
headers = { |
||||
|
'Accept': 'application/vnd.github.groot-preview+json', |
||||
|
} |
||||
|
|
||||
|
if os.environ.get('GH_TOKEN'): |
||||
|
headers['Authorization'] = 'token ' + os.environ.get('GH_TOKEN') |
||||
|
|
||||
|
url = 'https://api.github.com/repos/{repo}/commits/{commit}/pulls'.format(repo=repo, commit=commit) |
||||
|
content = requests.get(url, headers=headers).json() |
||||
|
if content.get(0) is not None: |
||||
|
pullreq = content[0]['number'] |
||||
|
else: |
||||
|
pullreq = None |
||||
|
|
||||
|
e = Entry(commit, pullreq, m.group(2), m.group(1).lower()) |
||||
|
entries.append(e) |
||||
|
|
||||
|
return entries |
||||
|
|
||||
|
|
||||
|
def linkify(entries): |
||||
|
links = [] |
||||
|
for e in entries: |
||||
|
links.append(Link( |
||||
|
ref='#{}'.format(e.pullreq), |
||||
|
content=e.content, |
||||
|
url="https://github.com/{repo}/pull/{pullreq}".format(repo=repo, pullreq=e.pullreq) |
||||
|
)) |
||||
|
return list(set(links)) |
||||
|
|
||||
|
|
||||
|
def group(entries): |
||||
|
groups = {s: [] for s in sections} |
||||
|
for e in entries: |
||||
|
groups[e.section].append(e) |
||||
|
for s in sections: |
||||
|
if len(groups[s]) == 0: |
||||
|
del groups[s] |
||||
|
return groups |
||||
|
|
||||
|
|
||||
|
def commit_date(commitsha): |
||||
|
"""Get the date of the specified commit. |
||||
|
""" |
||||
|
line = git("show -s --format=%ci") |
||||
|
dt = datetime.strptime(line.strip(), '%Y-%m-%d %H:%M:%S %z') |
||||
|
return dt |
||||
|
|
||||
|
|
||||
|
template = Template("""<%def name="group(entries)"> |
||||
|
% for e in entries: |
||||
|
% if e.pullreq is not None: |
||||
|
- ${e.content} ([#${e.pullreq}]) |
||||
|
% else: |
||||
|
- ${e.content} |
||||
|
% endif |
||||
|
% endfor |
||||
|
|
||||
|
</%def><%def name="group_links(entries)"> |
||||
|
% for e in entries: |
||||
|
[${e.pullreq}]: https://github.com/{repo}/pull/${e.pullreq} |
||||
|
% endfor |
||||
|
</%def> |
||||
|
<!-- |
||||
|
TODO: Insert version codename, and username of the contributor that named the release. |
||||
|
--> |
||||
|
|
||||
|
${h2} [${version}] - ${date.strftime("%Y-%m-%d")} |
||||
|
|
||||
|
% for section in sections: |
||||
|
${h3} ${section.capitalize()} |
||||
|
${group(groups[section]) | trim} |
||||
|
% endfor |
||||
|
|
||||
|
% for l in links: |
||||
|
[${l.ref}]: ${l.url} |
||||
|
% endfor |
||||
|
[${version}]: https://github.com/{repo}/releases/tag/v${version}""") |
||||
|
|
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
parser = argparse.ArgumentParser( |
||||
|
description='Generate a changelog summary for a given commit range' |
||||
|
) |
||||
|
parser.add_argument('commitrange', type=str, nargs='?', |
||||
|
help='Range of commits to consider (format: <from_commit>..<to_commit>', |
||||
|
default=get_commit_range()) |
||||
|
|
||||
|
args = parser.parse_args() |
||||
|
|
||||
|
if '..' not in args.commitrange: |
||||
|
print("Commit range must include '..' to separate 'from_commit' and 'to_commit'") |
||||
|
sys.exit(1) |
||||
|
|
||||
|
fromcommit, tocommit = args.commitrange.split('..') |
||||
|
entries = get_log_entries(args.commitrange) |
||||
|
groups = group(entries) |
||||
|
date = commit_date(tocommit) |
||||
|
|
||||
|
print(template.render( |
||||
|
groups=groups, |
||||
|
repo=repo, |
||||
|
sections=groups.keys(), |
||||
|
h2='##', |
||||
|
h3='###', |
||||
|
version=tocommit[1:], |
||||
|
date=date, |
||||
|
links=linkify(entries), |
||||
|
)) |
||||
|
|
||||
|
|
Loading…
Reference in new issue