damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | LICENSE

commit a578e44a547f563edfd58fa94859e051e0749ca7
parent a417da6089b727dd7a9760b98cb3a34ee9b86a93
Author: William Casarin <jb55@jb55.com>
Date:   Sat, 18 Jun 2022 10:36:57 -0700

Add changelog devtool

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Adevtools/changelog.py | 171+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 171 insertions(+), 0 deletions(-)

diff --git a/devtools/changelog.py b/devtools/changelog.py @@ -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), + )) + +