Skip to content

test(cmd-version): add fixture to reproduce issue with empty changelog #1268

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions tests/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,3 +328,4 @@ def _read_long_description():
""".lstrip() # noqa: E501

RELEASE_NOTES = "# Release Notes"
DEFAULT_MERGE_STRATEGY_OPTION = "theirs"
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
from __future__ import annotations

from typing import TYPE_CHECKING

import pytest
import tomlkit
from flatdict import FlatDict
from freezegun import freeze_time

from tests.const import (
DEFAULT_BRANCH_NAME,
)
from tests.fixtures.repos.trunk_based_dev import (
repo_w_trunk_only_w_feature_branch_and_release_in_default_conventional_commits,
repo_w_trunk_only_w_feature_branch_and_release_in_default_emoji_commits,
repo_w_trunk_only_w_feature_branch_and_release_in_default_scipy_commits,
)
from tests.util import temporary_working_directory

if TYPE_CHECKING:
from pathlib import Path
from unittest.mock import MagicMock

from requests_mock import Mocker

from tests.e2e.cmd_version.bump_version.conftest import (
InitMirrorRepo4RebuildFn,
RunPSReleaseFn,
)
from tests.e2e.conftest import GetSanitizedChangelogContentFn
from tests.fixtures.example_project import ExProjectDir
from tests.fixtures.git_repo import (
BuildRepoFromDefinitionFn,
BuildSpecificRepoFn,
CommitConvention,
GetGitRepo4DirFn,
RepoActionConfigure,
RepoActionRelease,
RepoActions,
SplitRepoActionsByReleaseTagsFn,
)


@pytest.mark.xfail(
reason="Should pass after [#1252](https://github.com/python-semantic-release/python-semantic-release/issues/1252) is fixed",
)
@pytest.mark.parametrize(
"repo_fixture_name",
[
pytest.param(repo_fixture_name, marks=pytest.mark.comprehensive)
for repo_fixture_name in [
repo_w_trunk_only_w_feature_branch_and_release_in_default_conventional_commits.__name__,
repo_w_trunk_only_w_feature_branch_and_release_in_default_emoji_commits.__name__,
repo_w_trunk_only_w_feature_branch_and_release_in_default_scipy_commits.__name__,
]
],
)
def test_trunk_repo_rebuild_w_feature_branch_and_release_in_default(
repo_fixture_name: str,
run_psr_release: RunPSReleaseFn,
build_trunk_only_repo_w_feature_branch_and_release_in_default: BuildSpecificRepoFn,
split_repo_actions_by_release_tags: SplitRepoActionsByReleaseTagsFn,
init_mirror_repo_for_rebuild: InitMirrorRepo4RebuildFn,
example_project_dir: ExProjectDir,
git_repo_for_directory: GetGitRepo4DirFn,
build_repo_from_definition: BuildRepoFromDefinitionFn,
mocked_git_push: MagicMock,
post_mocker: Mocker,
default_tag_format_str: str,
version_py_file: Path,
get_sanitized_md_changelog_content: GetSanitizedChangelogContentFn,
get_sanitized_rst_changelog_content: GetSanitizedChangelogContentFn,
):
# build target repo into a temporary directory
target_repo_dir = example_project_dir / repo_fixture_name
commit_type: CommitConvention = (
repo_fixture_name.split("commits", 1)[0].split("_")[-2] # type: ignore[assignment]
)
target_repo_definition = (
build_trunk_only_repo_w_feature_branch_and_release_in_default(
repo_name=repo_fixture_name,
commit_type=commit_type,
dest_dir=target_repo_dir,
)
)
target_git_repo = git_repo_for_directory(target_repo_dir)
target_repo_pyproject_toml = FlatDict(
tomlkit.loads((target_repo_dir / "pyproject.toml").read_text(encoding="utf-8")),
delimiter=".",
)
tag_format_str: str = target_repo_pyproject_toml.get( # type: ignore[assignment]
"tool.semantic_release.tag_format",
default_tag_format_str,
)

# split repo actions by release actions
releasetags_2_steps: dict[str, list[RepoActions]] = (
split_repo_actions_by_release_tags(target_repo_definition, tag_format_str)
)
configuration_step: RepoActionConfigure = releasetags_2_steps.pop("")[0] # type: ignore[assignment]

# Create the mirror repo directory
mirror_repo_dir = init_mirror_repo_for_rebuild(
mirror_repo_dir=(example_project_dir / "mirror"),
configuration_step=configuration_step,
)
mirror_git_repo = git_repo_for_directory(mirror_repo_dir)

# rebuild repo from scratch stopping before each release tag
for curr_release_tag, steps in releasetags_2_steps.items():
# make sure mocks are clear
mocked_git_push.reset_mock()
post_mocker.reset_mock()

# Extract expected result from target repo
head_reference_name = (
curr_release_tag
if curr_release_tag != "Unreleased"
else DEFAULT_BRANCH_NAME
)
target_git_repo.git.checkout(head_reference_name, detach=True)
expected_md_changelog_content = get_sanitized_md_changelog_content(
repo_dir=target_repo_dir
)
expected_rst_changelog_content = get_sanitized_rst_changelog_content(
repo_dir=target_repo_dir
)
expected_pyproject_toml_content = (
target_repo_dir / "pyproject.toml"
).read_text()
expected_version_file_content = (target_repo_dir / version_py_file).read_text()
expected_release_commit_text = target_git_repo.head.commit.message

# In our repo env, start building the repo from the definition
build_repo_from_definition(
dest_dir=mirror_repo_dir,
repo_construction_steps=steps[:-1], # stop before the release step
)
release_action_step: RepoActionRelease = steps[-1] # type: ignore[assignment]

# Act: run PSR on the repo instead of the RELEASE step
with freeze_time(
release_action_step["details"]["datetime"]
), temporary_working_directory(mirror_repo_dir):
run_psr_release(
next_version_str=release_action_step["details"]["version"],
git_repo=mirror_git_repo,
)

# take measurement after running the version command
actual_release_commit_text = mirror_git_repo.head.commit.message
actual_pyproject_toml_content = (mirror_repo_dir / "pyproject.toml").read_text()
actual_version_file_content = (mirror_repo_dir / version_py_file).read_text()
actual_md_changelog_content = get_sanitized_md_changelog_content(
repo_dir=mirror_repo_dir
)
actual_rst_changelog_content = get_sanitized_rst_changelog_content(
repo_dir=mirror_repo_dir
)

# Evaluate (normal release actions should have occurred as expected)
# ------------------------------------------------------------------
# Make sure version file is updated
assert expected_pyproject_toml_content == actual_pyproject_toml_content
assert expected_version_file_content == actual_version_file_content
# Make sure changelog is updated
assert expected_md_changelog_content == actual_md_changelog_content
assert expected_rst_changelog_content == actual_rst_changelog_content
# Make sure commit is created
assert expected_release_commit_text == actual_release_commit_text
# Make sure tag is created
assert curr_release_tag in [tag.name for tag in mirror_git_repo.tags]
assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag
assert post_mocker.call_count == 1 # vcs release creation occured
13 changes: 10 additions & 3 deletions tests/fixtures/git_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from tests.const import (
COMMIT_MESSAGE,
DEFAULT_BRANCH_NAME,
DEFAULT_MERGE_STRATEGY_OPTION,
EXAMPLE_HVCS_DOMAIN,
EXAMPLE_REPO_NAME,
EXAMPLE_REPO_OWNER,
Expand Down Expand Up @@ -233,6 +234,7 @@ def __call__(
branch_name: str,
commit_def: CommitDef,
fast_forward: bool = True,
strategy_option: str = DEFAULT_MERGE_STRATEGY_OPTION,
) -> CommitDef: ...

class CreateSquashMergeCommitFn(Protocol):
Expand All @@ -241,7 +243,7 @@ def __call__(
git_repo: Repo,
branch_name: str,
commit_def: CommitDef,
strategy_option: str = "theirs",
strategy_option: str = DEFAULT_MERGE_STRATEGY_OPTION,
) -> CommitDef: ...

class CommitSpec(TypedDict):
Expand Down Expand Up @@ -311,7 +313,7 @@ class RepoActionGitMergeDetails(DetailsBase):
branch_name: str
commit_def: CommitDef
fast_forward: Literal[False]
# strategy_option: str
strategy_option: NotRequired[str]

class RepoActionGitFFMergeDetails(DetailsBase):
branch_name: str
Expand Down Expand Up @@ -763,6 +765,7 @@ def _create_merge_commit(
branch_name: str,
commit_def: CommitDef,
fast_forward: bool = True,
strategy_option: str = DEFAULT_MERGE_STRATEGY_OPTION,
) -> CommitDef:
curr_dt = stable_now_date()
commit_dt = (
Expand All @@ -784,6 +787,7 @@ def _create_merge_commit(
ff=fast_forward,
no_ff=bool(not fast_forward),
m=commit_def["msg"],
strategy_option=strategy_option,
)

# return the commit definition with the sha & message updated
Expand All @@ -804,7 +808,7 @@ def _create_squash_merge_commit(
git_repo: Repo,
branch_name: str,
commit_def: CommitDef,
strategy_option: str = "theirs",
strategy_option: str = DEFAULT_MERGE_STRATEGY_OPTION,
) -> CommitDef:
curr_dt = stable_now_date()
commit_dt = (
Expand Down Expand Up @@ -1404,6 +1408,9 @@ def _build_repo_from_definition( # noqa: C901, its required and its just test c
branch_name=merge_def["branch_name"],
commit_def=merge_def["commit_def"],
fast_forward=merge_def["fast_forward"],
strategy_option=merge_def.get(
"strategy_option", DEFAULT_MERGE_STRATEGY_OPTION
),
)
if merge_def["commit_def"]["include_in_changelog"]:
current_commits.append(merge_def["commit_def"])
Expand Down
1 change: 1 addition & 0 deletions tests/fixtures/repos/trunk_based_dev/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from tests.fixtures.repos.trunk_based_dev.repo_w_dual_version_support import *
from tests.fixtures.repos.trunk_based_dev.repo_w_dual_version_support_w_prereleases import *
from tests.fixtures.repos.trunk_based_dev.repo_w_feature_branch_and_release_in_default import *
from tests.fixtures.repos.trunk_based_dev.repo_w_no_tags import *
from tests.fixtures.repos.trunk_based_dev.repo_w_prereleases import *
from tests.fixtures.repos.trunk_based_dev.repo_w_tags import *
Loading