blob: ad9cad65e5021673d70d4a891ef6f811b8b0ec5a [file] [log] [blame] [edit]
from changelog.git import stage_file
from changelog.util import load_all_released_changes, load_unreleased_changes, version_cmp
from functools import cmp_to_key
from operator import attrgetter
class ChangelogWriter(object):
"""
Writes ReleaseChanges objects to a file using the following format:
# __VERSION__ __YYYY-MM-DD__
## __Category__
- ### __Features__
- ...
- ### __Bugfixes__
- ...
- ### __Deprecations__
- ...
"""
def __init__(self, output_file):
self.output_file = output_file
def write_changes(self, changes):
self.process_changes(changes)
self.write_header()
for s in self.get_sorted_categories():
self.write_category_header(s)
self.write_items_for_category(s, self.features, "Features")
self.write_items_for_category(s, self.bugfixes, "Bugfixes")
self.write_items_for_category(s, self.deprecations, "Deprecations")
self.write_items_for_category(s, self.removals, "Removals")
self.write_items_for_category(s, self.documentations, "Documentations")
self.write_contributors()
def write_contributors(self):
contributors = set()
for e in self.current_changes.entries:
if e.contributor:
contributors.add(self.contributor_with_link(e.contributor))
if contributors:
self.output_file.write("## __Contributors__\n")
contributors_string = ', '.join(contributors)
self.output_file.write("Special thanks to the following contributors to this release: \n")
self.output_file.write("\n" + contributors_string + "\n")
def contributor_with_link(self, contributor):
return "[@" + contributor + "]" + "(" + \
"https://github.com/" + contributor + ")"
def process_changes(self, changes):
self.current_changes = changes
self.reset_maps()
self.group_entries()
def reset_maps(self):
self.features = {}
self.bugfixes = {}
self.deprecations = {}
self.removals = {}
self.documentations = {}
self.categories = set()
def group_entries(self):
for e in self.current_changes.entries:
m = self.get_map_for_type(e.type)
m.setdefault(e.category, []).append(e)
self.categories.add(e.category)
def get_sorted_categories(self):
return sorted(list(self.categories))
def is_service_category(self,s):
return s.lower() not in NON_SERVICE_CATEGORIES
def write_header(self):
version_string = self.current_changes.version
if version_string is None:
version_string = "@AWS_JAVA_SDK_VERSION@"
self.write("# __%s__ __%s__\n" % (version_string, self.current_changes.date))
def write_category_header(self, c):
self.output_file.write("## __%s__\n" % c)
def write_items_for_category(self, category, map, header):
entries = map.get(category, [])
items = sorted(entries, key=attrgetter('description'))
self.write_entries_with_header(header, items)
def write_entries_with_header(self, header, entries):
if not len(entries) > 0:
return
self.write(" - ### %s\n" % header)
for e in entries:
self.write_entry(e)
self.write('\n')
def write_entry(self,e):
description = e.description
entry_lines = description.splitlines(True)
self.write(" - %s" % entry_lines[0])
for l in entry_lines[1:]:
if len(l.strip()) == 0:
self.write("\n")
else:
self.write(" %s" % l)
self.write('\n')
if e.contributor:
self.write(" - ")
self.write("Contributed by: " + self.contributor_with_link(e.contributor))
self.write('\n')
def get_map_for_type(self, t):
if t == 'feature':
return self.features
elif t == 'bugfix':
return self.bugfixes
elif t == 'deprecation':
return self.deprecations
elif t == 'removal':
return self.removals
elif t == 'documentation':
return self.documentations
else:
raise Exception("Unknown entry type %s!" % t)
def write(self, s):
self.output_file.write(s)
def write_archived_changelogs_message(changelog_file):
message = " #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._\n"
changelog_file.write(message)
def write_changelog():
unreleased = load_unreleased_changes(".changes/next-release")
released = load_all_released_changes(".changes")
released = sorted(released, key=lambda c: [c.version.major, c.version.minor, c.version.patch, c.version.prerelease_version_number()], reverse=True)
if unreleased is not None:
all_changes = [unreleased] + released
else:
all_changes = released
if len(all_changes) == 0:
return
with open('CHANGELOG.md', 'w') as cl:
write_archived_changelogs_message(cl)
writer = ChangelogWriter(cl)
for changes in all_changes:
writer.write_changes(changes)
stage_file('CHANGELOG.md')