From 328caf007428aac9f6c28d021e57bf3d6bbf78d3 Mon Sep 17 00:00:00 2001 From: Julian Rother <julian@cccv.de> Date: Tue, 26 Oct 2021 11:14:42 +0200 Subject: [PATCH] Fixes and improvements for changelog auto-generation The script generated a broken changelog if the current commit is tagged as a release. That works now. Additional improvements: * Merge commits are ignored * "^fixup!" commits are ignored * Commit summaries are line-wrapped * Authors can be merged by manually supplied name mapping * The first release also includes a list of commits. They were originally excluded because the first release contains so many commits, including many unclean ones. But excluding those commits also means excluding the attribution, so it is not really an option. * Authors are ordered by the number of their contributions in a release to make occasional contributors more visible. --- debian/create_changelog.py | 40 +++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/debian/create_changelog.py b/debian/create_changelog.py index 4be02a75..b62f211c 100755 --- a/debian/create_changelog.py +++ b/debian/create_changelog.py @@ -9,6 +9,15 @@ import git package_name = 'UNKNOWN' +alias_names = { + 'julian': 'Julian Rother', + 'Julian': 'Julian Rother', +} + +ignore_commit_regexes = [ + '^fixup!', +] + def print_release(tag=None, commits=tuple(), last_tag=None): release_version = '0.0.0' release_author = git.objects.util.Actor('None', 'undefined@example.com') @@ -45,21 +54,29 @@ def print_release(tag=None, commits=tuple(), last_tag=None): commit_author_names = {} # author name -> key commit_author_commits = {} # key -> list of commits for commit in commits: + if any(filter(lambda pattern: re.match(pattern, commit.summary), ignore_commit_regexes)): + continue + if len(commit.parents) > 1: + continue # Ignore merge commits + author_name = alias_names.get(commit.author.name, commit.author.name) key = commit_author_emails.get(commit.author.email) if key is None: - key = commit_author_names.get(commit.author.name) + key = commit_author_names.get(author_name) if key is None: key = commit.author.email - commit_authors.append((key, commit.author)) - commit_author_emails[commit.author.email] = key - commit_author_names[commit.author.name] = key + commit_authors.append((key, author_name)) + commit_author_emails[commit.author.email] = key + commit_author_names[author_name] = key commit_author_commits[key] = commit_author_commits.get(key, []) + [commit] - for key, author in commit_authors: - print(f' [ {author.name} ]') + commit_authors.sort(key=lambda args: len(commit_author_commits[args[0]])) + for key, author_name in commit_authors: + print(f' [ {author_name} ]') for commit in commit_author_commits[key]: - print(f' * {commit.summary}') + lines = '\n'.join(textwrap.wrap(commit.summary, 90)) + lines = ' * ' + textwrap.indent(lines, ' ').strip() + print(lines) print() - print(f' -- {release_author.name} <{release_author.email}> {email.utils.formatdate(release_date)}') + print(f' -- {alias_names.get(release_author.name, release_author.name)} <{release_author.email}> {email.utils.formatdate(release_date)}') if __name__ == '__main__': repo = git.Repo('.') @@ -80,9 +97,10 @@ if __name__ == '__main__': for commit in repo.iter_commits('HEAD'): if commit.hexsha in version_commits: prev_tag = version_commits[commit.hexsha] - print_release(tag, commits, last_tag=prev_tag) - print() + if commits: + print_release(tag, commits, last_tag=prev_tag) + print() tag = prev_tag commits = [] commits.append(commit) - print_release(tag, []) + print_release(tag, commits) -- GitLab