Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

fix(commands/changelog): use topological order for commit ordering #677

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions commitizen/commands/changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,7 @@ def __call__(self):
tag_format=self.tag_format,
)

commits = git.get_commits(
start=start_rev, end=end_rev, args="--author-date-order"
)
commits = git.get_commits(start=start_rev, end=end_rev, args="--topo-order")
if not commits:
raise NoCommitsFoundError("No commits found")

Expand Down
78 changes: 77 additions & 1 deletion tests/commands/test_changelog_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@
NotAGitProjectError,
NotAllowed,
)
from tests.utils import create_file_and_commit, wait_for_tag
from tests.utils import (
create_branch,
create_file_and_commit,
get_current_branch,
merge_branch,
switch_branch,
wait_for_tag,
)


@pytest.mark.usefixtures("tmp_commitizen_project")
Expand Down Expand Up @@ -268,6 +275,75 @@ def test_changelog_hook_customize(mocker: MockFixture, config_customize):
changelog_hook_mock.assert_called_with(full_changelog, full_changelog)


@pytest.mark.usefixtures("tmp_commitizen_project")
def test_changelog_with_non_linear_merges_commit_order(
mocker: MockFixture, config_customize
):
"""Test that commits merged non-linearly are correctly ordered in the changelog

A typical scenario is having two branches from main like so:
* feat: I will be merged first - (2023-03-01 11:35:51 +0100) | (branchB)
| * feat: I will be merged second - (2023-03-01 11:35:22 +0100) | (branchA)
|/
* feat: initial commit - (2023-03-01 11:34:54 +0100) | (HEAD -> main)

And merging them, for example in the reverse order they were created on would give the following:
* Merge branch 'branchA' - (2023-03-01 11:42:59 +0100) | (HEAD -> main)
|\
| * feat: I will be merged second - (2023-03-01 11:35:22 +0100) | (branchA)
* | feat: I will be merged first - (2023-03-01 11:35:51 +0100) | (branchB)
|/
* feat: initial commit - (2023-03-01 11:34:54 +0100) |

In this case we want the changelog to reflect the topological order of commits,
i.e. the order in which they were merged into the main branch

So the above example should result in the following:
## Unreleased

### Feat
- I will be merged second
- I will be merged first
- initial commit
"""
changelog_hook_mock = mocker.Mock()
changelog_hook_mock.return_value = "cool changelog hook"

create_file_and_commit("feat: initial commit")

main_branch = get_current_branch()

create_branch("branchA")
create_branch("branchB")

switch_branch("branchA")
create_file_and_commit("feat: I will be merged second")

switch_branch("branchB")
create_file_and_commit("feat: I will be merged first")

# Note we merge branches opposite order than author_date
switch_branch(main_branch)
merge_branch("branchB")
merge_branch("branchA")

changelog = Changelog(
config_customize,
{"unreleased_version": None, "incremental": True, "dry_run": False},
)
mocker.patch.object(changelog.cz, "changelog_hook", changelog_hook_mock)
changelog()
full_changelog = "\
## Unreleased\n\n\
\
### Feat\n\n\
- I will be merged second\n\
- I will be merged first\n\
- initial commit\n"

changelog_hook_mock.assert_called_with(full_changelog, full_changelog)


@pytest.mark.usefixtures("tmp_commitizen_project")
def test_changelog_multiple_incremental_do_not_add_new_lines(
mocker: MockFixture, capsys, changelog_path, file_regression
Expand Down
25 changes: 25 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,31 @@ def create_file_and_commit(message: str, filename: Optional[str] = None):
raise exceptions.CommitError(c.err)


def create_branch(name: str):
c = cmd.run(f"git branch {name}")
if c.return_code != 0:
raise exceptions.GitCommandError(c.err)


def switch_branch(branch: str):
c = cmd.run(f"git switch {branch}")
if c.return_code != 0:
raise exceptions.GitCommandError(c.err)


def merge_branch(branch: str):
c = cmd.run(f"git merge {branch}")
if c.return_code != 0:
raise exceptions.GitCommandError(c.err)


def get_current_branch() -> str:
c = cmd.run("git rev-parse --abbrev-ref HEAD")
if c.return_code != 0:
raise exceptions.GitCommandError(c.err)
return c.out


def create_tag(tag: str):
c = git.tag(tag)
if c.return_code != 0:
Expand Down