From c4bd39af899902a2a42f298e05007ad5d2b69994 Mon Sep 17 00:00:00 2001 From: gardar Date: Sat, 15 Jun 2024 03:51:13 +0000 Subject: [PATCH] feat: allow more granular control of changelog sorting Signed-off-by: gardar --- changelogs/config.yaml | 2 +- .../fragments/165-changelog-sort-option.yml | 9 ++++++++ docs/changelog-configuration.md | 12 ++++++---- src/antsibull_changelog/changes.py | 23 ++++++++++--------- src/antsibull_changelog/config.py | 17 +++++++++----- src/antsibull_changelog/yaml.py | 4 ++-- 6 files changed, 43 insertions(+), 24 deletions(-) create mode 100644 changelogs/fragments/165-changelog-sort-option.yml diff --git a/changelogs/config.yaml b/changelogs/config.yaml index 6f5a0c07..2399dc17 100644 --- a/changelogs/config.yaml +++ b/changelogs/config.yaml @@ -38,4 +38,4 @@ output_formats: - md add_plugin_period: false changelog_nice_yaml: false -changelog_semantic_versioning_sort: false +changelog_sort: alphanumerical diff --git a/changelogs/fragments/165-changelog-sort-option.yml b/changelogs/fragments/165-changelog-sort-option.yml new file mode 100644 index 00000000..a7c317cc --- /dev/null +++ b/changelogs/fragments/165-changelog-sort-option.yml @@ -0,0 +1,9 @@ +--- +minor_changes: + - | + Adds a new configuration option `changelog_sort`. + This option allows sorting of changelog entries in `changelogs/changelog.yaml` with four modes: + - `unsorted`: No sorting is performed. + - `version`: Sorts entries by version in ascending order. + - `version_reverse`: Sorts entries by version in descending order. + - `alphanumerical`: Sorts entries in alphanumerical order. diff --git a/docs/changelog-configuration.md b/docs/changelog-configuration.md index bc3e5e70..8ef9d032 100644 --- a/docs/changelog-configuration.md +++ b/docs/changelog-configuration.md @@ -103,12 +103,16 @@ YAML encoding that is compatible with ansible-lint's default rules. The exact format used might be adjusted in the future if new releases of ansible-lint adjust their yamllint configuration. -### `changelog_semantic_versioning_sort` (boolean) +### `changelog_sort` (string) -The default is `false`. +The default is `alphanumerical`. + +This option controls the sorting of changelog entries in `changelogs/changelog.yaml`. It accepts the following values: -When set to `true` the changelog entries in `changelogs/changelog.yaml` entries will -be sorted by semantic version. +- `unsorted`: No sorting is performed on the changelog entries. The entries are stored in the order they were added. +- `version`: Sorts the changelog entries by semantic version in ascending order. +- `version_reverse`: Sorts the changelog entries by semantic version in descending order. +- `alphanumerical`: Sorts the changelog entries in alphanumerical order. ### `flatmap` (optional boolean) diff --git a/src/antsibull_changelog/changes.py b/src/antsibull_changelog/changes.py index ea5c05f1..f26b759b 100644 --- a/src/antsibull_changelog/changes.py +++ b/src/antsibull_changelog/changes.py @@ -156,11 +156,12 @@ def save(self) -> None: """ self.sort() self.data["ancestor"] = self.ancestor + sort_keys = self.config.changelog_sort == "alphanumerical" store_yaml( self.path, self.data, self.config.changelog_nice_yaml, - self.config.changelog_semantic_versioning_sort, + sort_keys, ) def add_release( @@ -421,17 +422,7 @@ def update_fragments( def sort(self) -> None: """ Sort change metadata in place. - Optionally sorts by semantic version. """ - if self.config.changelog_semantic_versioning_sort: - self.data["releases"] = dict( - sorted( - self.data["releases"].items(), - key=lambda t: [int(v) for v in t[0].split(".")], - reverse=True, - ), - ) - for _, config in self.data["releases"].items(): if "modules" in config: config["modules"] = sorted(config["modules"]) @@ -714,6 +705,16 @@ def sort(self) -> None: """ Sort change metadata in place. """ + if self.config.changelog_sort in ["version", "version_reverse"]: + reverse_order = self.config.changelog_sort == "version_reverse" + self.data["releases"] = dict( + sorted( + self.data["releases"].items(), + key=lambda t: self.version_constructor(t[0]), + reverse=reverse_order, + ) + ) + for _, config in self.data["releases"].items(): if "modules" in config: config["modules"] = sorted( diff --git a/src/antsibull_changelog/config.py b/src/antsibull_changelog/config.py index 7277ceba..5a75b720 100644 --- a/src/antsibull_changelog/config.py +++ b/src/antsibull_changelog/config.py @@ -380,7 +380,7 @@ class ChangelogConfig: output_formats: set[TextFormat] add_plugin_period: bool changelog_nice_yaml: bool - changelog_semantic_versioning_sort: bool + changelog_sort: str def __init__( self, @@ -427,6 +427,7 @@ def __init__( "trivial" if has_trivial_section_by_default else None, ) self.sanitize_changelog = self.config.get("sanitize_changelog", False) + always_refresh = self.config.get( "always_refresh", self.changes_format == "classic" ) @@ -472,9 +473,8 @@ def __init__( self.changelog_nice_yaml = self.config.get("changelog_nice_yaml", False) - self.changelog_semantic_versioning_sort = self.config.get( - "changelog_semantic_versioning_sort", False - ) + self.changelog_sort = self.config.get("changelog_sort", "alphanumerical") + self._validate_config(ignore_is_other_project) @@ -506,6 +506,11 @@ def _validate_config(self, ignore_is_other_project: bool) -> None: "combined with prevent_known_fragments == False" ) + valid_sort_options = ["unsorted", "version", "version_reverse", "alphanumerical"] + if self.changelog_sort not in valid_sort_options: + raise ChangelogError(f"Invalid changelog_sort option: {self.changelog_sort}") + + def store(self) -> None: # noqa: C901 """ Store changelog configuration file to disk. @@ -527,7 +532,7 @@ def store(self) -> None: # noqa: C901 "sanitize_changelog": self.sanitize_changelog, "add_plugin_period": self.add_plugin_period, "changelog_nice_yaml": self.changelog_nice_yaml, - "changelog_semantic_versioning_sort": self.changelog_semantic_versioning_sort, + "changelog_sort": self.changelog_sort, } if not self.is_collection: if self.use_semantic_versioning: @@ -608,7 +613,7 @@ def default( "sanitize_changelog": True, "add_plugin_period": True, "changelog_nice_yaml": False, - "changelog_semantic_versioning_sort": False, + "changelog_sort": "alphanumerical", } if title is not None: config["title"] = title diff --git a/src/antsibull_changelog/yaml.py b/src/antsibull_changelog/yaml.py index ba3b2da9..a369a1bf 100644 --- a/src/antsibull_changelog/yaml.py +++ b/src/antsibull_changelog/yaml.py @@ -42,7 +42,7 @@ def load_yaml(path: str) -> Any: return yaml.load(stream, Loader=_SafeLoader) -def store_yaml(path: str, content: Any, nice: bool = False, sort: bool = False) -> None: +def store_yaml(path: str, content: Any, nice: bool, sort_keys: bool = False) -> None: """ Store ``content`` as YAML file under ``path``. """ @@ -53,5 +53,5 @@ def store_yaml(path: str, content: Any, nice: bool = False, sort: bool = False) default_flow_style=False, Dumper=_IndentedDumper if nice else _SafeDumper, explicit_start=nice, - sort_keys=not sort, + sort_keys=sort_keys )