Skip to content

Commit

Permalink
feat: allow more granular control of changelog sorting
Browse files Browse the repository at this point in the history
Signed-off-by: gardar <gardar@users.noreply.github.com>
  • Loading branch information
gardar committed Jun 15, 2024
1 parent f2b83a7 commit c4bd39a
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 24 deletions.
2 changes: 1 addition & 1 deletion changelogs/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ output_formats:
- md
add_plugin_period: false
changelog_nice_yaml: false
changelog_semantic_versioning_sort: false
changelog_sort: alphanumerical
9 changes: 9 additions & 0 deletions changelogs/fragments/165-changelog-sort-option.yml
Original file line number Diff line number Diff line change
@@ -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.
12 changes: 8 additions & 4 deletions docs/changelog-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
23 changes: 12 additions & 11 deletions src/antsibull_changelog/changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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"])
Expand Down Expand Up @@ -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(
Expand Down
17 changes: 11 additions & 6 deletions src/antsibull_changelog/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"
)
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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.
Expand All @@ -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:
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/antsibull_changelog/yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -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``.
"""
Expand All @@ -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
)

0 comments on commit c4bd39a

Please sign in to comment.