build-release-notes: support categories

Change-Id: Icdcbd2cf5bf075e7006ce1f8bc0c9d6c35cfd072
This commit is contained in:
jade 2024-05-14 19:14:13 -07:00
parent 03655c310d
commit 79ee9355ae

View file

@ -1,18 +1,31 @@
from collections import defaultdict
import frontmatter import frontmatter
import sys import sys
import pathlib import pathlib
import textwrap import textwrap
from typing import Any, Tuple
GH_BASE = "https://github.com/NixOS/nix" GH_BASE = "https://github.com/NixOS/nix"
FORGEJO_BASE = "https://git.lix.systems/lix-project/lix" FORGEJO_BASE = "https://git.lix.systems/lix-project/lix"
GERRIT_BASE = "https://gerrit.lix.systems/c/lix/+" GERRIT_BASE = "https://gerrit.lix.systems/c/lix/+"
KNOWN_KEYS = ('synopsis', 'cls', 'issues', 'prs', 'significance', 'credits') KNOWN_KEYS = ('synopsis', 'cls', 'issues', 'prs', 'significance', 'category', 'credits')
SIGNIFICANCECES = { SIGNIFICANCECES = {
None: 0, None: 0,
'significant': 10, 'significant': 10,
} }
# This is just hardcoded for better validation. If you think there should be
# more of them, feel free to add more.
CATEGORIES = [
'Breaking Changes',
'Features',
'Improvements',
'Fixes',
'Packaging',
'Miscellany',
]
def format_link(ident: str, gh_part: str, fj_part: str) -> str: def format_link(ident: str, gh_part: str, fj_part: str) -> str:
# FIXME: deprecate github as default # FIXME: deprecate github as default
if ident.isdigit(): if ident.isdigit():
@ -39,31 +52,13 @@ def plural_list(strs: list[str]) -> str:
comma = ',' if len(strs) >= 3 else '' comma = ',' if len(strs) >= 3 else ''
return '{}{} and {}'.format(', '.join(strs[:-1]), comma, strs[-1]) return '{}{} and {}'.format(', '.join(strs[:-1]), comma, strs[-1])
def run_on_dir(d): def listify(l: list | int) -> list:
d = pathlib.Path(d) if not isinstance(l, list):
if not d.is_dir(): return [l]
raise ValueError(f'provided path {d} is not a directory') else:
paths = d.glob('*.md') return l
entries = []
for p in paths:
try:
e = frontmatter.load(p)
if 'synopsis' not in e.metadata:
raise Exception('missing synopsis')
unknownKeys = set(e.metadata.keys()) - set(KNOWN_KEYS)
if unknownKeys:
raise Exception('unknown keys', unknownKeys)
entries.append((p, e))
except Exception as e:
e.add_note(f"in {p}")
raise
def listify(l: list | int) -> list:
if not isinstance(l, list):
return [l]
else:
return l
def do_category(entries: list[Tuple[pathlib.Path, Any]]):
for p, entry in sorted(entries, key=lambda e: (-SIGNIFICANCECES[e[1].metadata.get('significance')], e[0])): for p, entry in sorted(entries, key=lambda e: (-SIGNIFICANCECES[e[1].metadata.get('significance')], e[0])):
try: try:
header = entry.metadata['synopsis'] header = entry.metadata['synopsis']
@ -84,6 +79,35 @@ def run_on_dir(d):
e.add_note(f"in {p}") e.add_note(f"in {p}")
raise raise
def run_on_dir(d):
d = pathlib.Path(d)
if not d.is_dir():
raise ValueError(f'provided path {d} is not a directory')
paths = pathlib.Path(d).glob('*.md')
entries = defaultdict(list)
for p in paths:
try:
e = frontmatter.load(p)
if 'synopsis' not in e.metadata:
raise Exception('missing synopsis')
unknownKeys = set(e.metadata.keys()) - set(KNOWN_KEYS)
if unknownKeys:
raise Exception('unknown keys', unknownKeys)
category = e.metadata.get('category', 'Miscellany')
if category not in CATEGORIES:
raise Exception('unknown category', category)
entries[category].append((p, e))
except Exception as e:
e.add_note(f"in {p}")
raise
for category in CATEGORIES:
if entries[category]:
print('\n#', category)
do_category(entries[category])
if __name__ == '__main__': if __name__ == '__main__':
for d in sys.argv[1:]: for d in sys.argv[1:]:
run_on_dir(d) run_on_dir(d)