Skip to content

Commit

Permalink
feat(reana-dev): add git-aggregate-changelog (#789)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonadoni committed Mar 7, 2024
1 parent a4cb84c commit 67485c2
Showing 1 changed file with 201 additions and 0 deletions.
201 changes: 201 additions & 0 deletions reana/reana_dev/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@

import datetime
import os
import re
import subprocess
import sys
from typing import Optional

import click
import yaml

from reana.config import (
COMPONENTS_USING_SHARED_MODULE_COMMONS,
Expand All @@ -28,6 +30,8 @@
PYTHON_VERSION_FILE,
RELEASE_COMMIT_REGEX,
REPO_LIST_ALL,
REPO_LIST_CLUSTER_INFRASTRUCTURE,
REPO_LIST_CLUSTER_RUNTIME_BATCH,
REPO_LIST_PYTHON_REQUIREMENTS,
REPO_LIST_SHARED,
)
Expand Down Expand Up @@ -1586,4 +1590,201 @@ def git_tag(component, exclude_components): # noqa: D301
run_command(f"git tag {current_version}", component=component)


def get_previous_versions(components, override={}):
"""Get the version of each component at the time of the previous REANA release."""
helm_values = yaml.safe_load(

Check warning on line 1595 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1595

Added line #L1595 was not covered by tests
run_command(
"git show HEAD~1:helm/reana/values.yaml",
component="reana",
return_output=True,
)
)

prev_versions = dict(override)
prev_server = helm_values["components"]["reana_server"]["image"].split(":")[1]
for component in components:
if component in override:
continue

Check warning on line 1607 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1603-L1607

Added lines #L1603 - L1607 were not covered by tests

if (

Check warning on line 1609 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1609

Added line #L1609 was not covered by tests
component
in REPO_LIST_CLUSTER_INFRASTRUCTURE + REPO_LIST_CLUSTER_RUNTIME_BATCH
):
# cluster components: get version from docker image in
# Helm values of previous REANA release
image = helm_values["components"][component.replace("-", "_")]["image"]
prev_version = image.split(":")[1]
elif component in REPO_LIST_SHARED:

Check warning on line 1617 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1615-L1617

Added lines #L1615 - L1617 were not covered by tests
# shared components: read version from requirements.txt of reana-server
# of previous REANA release
requirement = run_command(

Check warning on line 1620 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1620

Added line #L1620 was not covered by tests
f"git show {prev_server}:requirements.txt | grep '^{component}'",
component="reana-server",
return_output=True,
)
prev_version = re.search("==([a-zA-Z0-9.-_]+)", requirement).group(1)

Check warning on line 1625 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1625

Added line #L1625 was not covered by tests
else:
raise ValueError(f"Not able to find previous version of {component}")
prev_versions[component] = prev_version

Check warning on line 1628 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1627-L1628

Added lines #L1627 - L1628 were not covered by tests

return prev_versions

Check warning on line 1630 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1630

Added line #L1630 was not covered by tests


def get_formatted_changelog_lines(component, versions):
"""Read and format the changelog lines of given component and versions.
The changelog will be reformatted so that:
- commit types do not create subsections (e.g. `### Build`)
- the commit type is prepended to each commit message
- all sections are moved one level down in the hierarchy
Example:
```
## [0.9.8](https://github.com/reanahub/reana-commons/compare/0.9.7...0.9.8) (2024-03-01)
### Build
* **python:** change extra names to comply with PEP 685 [...]
```
becomes
```
### reana-commons [0.9.8](https://github.com/reanahub/reana-commons/compare/0.9.7...0.9.8) (2024-03-01)
* [Build] **python:** change extra names to comply with PEP 685 [...]
```
"""
changelog_path = os.path.join(get_srcdir(component), "CHANGELOG.md")
with open(changelog_path) as f:
changelog_lines = f.readlines()

Check warning on line 1661 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1659-L1661

Added lines #L1659 - L1661 were not covered by tests

formatted_lines = []
is_version_to_add = False
current_section = ""
for line in changelog_lines:
if matches := re.match(r"##\s+\[?([\d.]+)", line):

Check warning on line 1667 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1663-L1667

Added lines #L1663 - L1667 were not covered by tests
# check if release in header is part of releases we are
# interested in
is_version_to_add = matches.group(1) in versions
if not is_version_to_add:
continue

Check warning on line 1672 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1670-L1672

Added lines #L1670 - L1672 were not covered by tests

if line.startswith("### "):

Check warning on line 1674 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1674

Added line #L1674 was not covered by tests
# commit type (e.g. fix, feat, ...)
current_section = line[len("### ") :].strip()
elif line.startswith("## "):

Check warning on line 1677 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1676-L1677

Added lines #L1676 - L1677 were not covered by tests
# release header
line = f"### {component}" + line[len("##") :]
if formatted_lines:

Check warning on line 1680 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1679-L1680

Added lines #L1679 - L1680 were not covered by tests
# add empty line before previous release changelog
formatted_lines.append("\n")
formatted_lines.append(line)
formatted_lines.append("\n")
elif line.startswith("*"):

Check warning on line 1685 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1682-L1685

Added lines #L1682 - L1685 were not covered by tests
# release please format, bullet points with '*'
formatted_lines.append(f"* [{current_section}]" + line[1:])
elif line.startswith("-"):

Check warning on line 1688 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1687-L1688

Added lines #L1687 - L1688 were not covered by tests
# old changelog format, bullet points with '-'
formatted_lines.append("*" + line[1:])

Check warning on line 1690 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1690

Added line #L1690 was not covered by tests

return formatted_lines

Check warning on line 1692 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1692

Added line #L1692 was not covered by tests


def append_after_version_changelog(component, version, new_lines):
"""Append the given lines after the changelog of the provided version."""
changelog_path = os.path.join(get_srcdir(component), "CHANGELOG.md")
with open(changelog_path) as changelog_file:
changelog_lines = changelog_file.readlines()

Check warning on line 1699 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1697-L1699

Added lines #L1697 - L1699 were not covered by tests

# find the idx of the release that follows the given one
idx_insert = None
found_given_version = False
for i, line in enumerate(changelog_lines):
if line.startswith("## "):
if version in line:
found_given_version = True
elif found_given_version:
idx_insert = i
break

Check warning on line 1710 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1702-L1710

Added lines #L1702 - L1710 were not covered by tests

if idx_insert is None:
raise ValueError(f"Could not find changelog of {component} {version}")

Check warning on line 1713 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1712-L1713

Added lines #L1712 - L1713 were not covered by tests

new_changelog = (

Check warning on line 1715 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1715

Added line #L1715 was not covered by tests
changelog_lines[:idx_insert] + new_lines + changelog_lines[idx_insert:]
)

with open(changelog_path, "w") as changelog_file:
changelog_file.writelines(new_changelog)

Check warning on line 1720 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1719-L1720

Added lines #L1719 - L1720 were not covered by tests


@git_commands.command(name="git-aggregate-changelog")
@click.option(
"--previous-reana-client",
help="Which is the version of reana-client that was released "
"for the last REANA release?",
required=True,
)
def get_aggregate_changelog(previous_reana_client): # noqa: D301
"""Aggregate the changelog of all REANA components.
Aggregate the changelog of all REANA components and append it to the main changelog of REANA.
This is useful for creating the changelog of a new REANA release.
All the repositories of the cluster components, shared components, `reana-client` and
`reana` must be checked out at the respective release commits.
:param previous_reana_client: The version of reana-client that was part of the previous REANA release.
:type previous_reana_client: str
"""
# all the components whose changelogs will be aggregated
changelog_components = (

Check warning on line 1743 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1743

Added line #L1743 was not covered by tests
["reana-client"]
+ REPO_LIST_SHARED
+ REPO_LIST_CLUSTER_INFRASTRUCTURE
+ REPO_LIST_CLUSTER_RUNTIME_BATCH
)
for component in ["reana"] + changelog_components:
if not is_last_commit_release_commit(component):
click.secho(

Check warning on line 1751 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1749-L1751

Added lines #L1749 - L1751 were not covered by tests
f"The last commit of {component} is not a release commit. "
"Please make sure you have the release commit checked out.",
fg="red",
)
sys.exit(1)

Check warning on line 1756 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1756

Added line #L1756 was not covered by tests

# get all the versions of the components as they were when the previous REANA version was released
prev_versions = get_previous_versions(

Check warning on line 1759 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1759

Added line #L1759 was not covered by tests
changelog_components, {"reana-client": previous_reana_client}
)

aggregated_changelog_lines = []
for component in changelog_components:
prev_version = prev_versions[component]

Check warning on line 1765 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1763-L1765

Added lines #L1763 - L1765 were not covered by tests

# get all tags reachable from latest release but not part of previous REANA release
versions_to_add = set(

Check warning on line 1768 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1768

Added line #L1768 was not covered by tests
run_command(
f"git tag --no-merged {prev_version} --merged",
component,
return_output=True,
).splitlines()
)

# also add current version, as it might not be tagged yet
versions_to_add.add(get_current_component_version_from_source_files(component))

Check warning on line 1777 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1777

Added line #L1777 was not covered by tests

aggregated_changelog_lines += get_formatted_changelog_lines(

Check warning on line 1779 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1779

Added line #L1779 was not covered by tests
component, versions_to_add
)
aggregated_changelog_lines += ["\n"]

Check warning on line 1782 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1782

Added line #L1782 was not covered by tests

current_reana_version = get_current_component_version_from_source_files(component)
append_after_version_changelog(

Check warning on line 1785 in reana/reana_dev/git.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/git.py#L1784-L1785

Added lines #L1784 - L1785 were not covered by tests
"reana", current_reana_version, aggregated_changelog_lines
)


git_commands_list = list(git_commands.commands.values())

0 comments on commit 67485c2

Please sign in to comment.