From 5fa2df5f802a0107872f9f0487f34292ad6e0bc4 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sun, 5 Jul 2026 15:24:49 -0600 Subject: [PATCH 1/5] style: fix configuration docs with alphabetical options --- docs/configuration/configuration.rst | 92 ++++++++++++++-------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/docs/configuration/configuration.rst b/docs/configuration/configuration.rst index d81369fbc..b39e6a30b 100644 --- a/docs/configuration/configuration.rst +++ b/docs/configuration/configuration.rst @@ -120,6 +120,52 @@ sure to use the correct root key depending on the configuration format you are u ---- +.. _config-add_partial_tags: + +``add_partial_tags`` +"""""""""""""""""""" + +**Type:** ``bool`` + +Specify if partial version tags should be handled when creating a new version. If set to +``true``, a ``major`` and a ``major.minor`` tag will be created or updated, using the format +specified in :ref:`tag_format`. If version has build metadata, a ``major.minor.patch`` tag +will also be created or updated. + +Partial version tags are **disabled** for pre-release versions. + +**Example** + +.. code-block:: toml + + [semantic_release] + tag_format = "v{version}" + add_partial_tags = true + +This configuration with the next version of ``1.2.3`` will result in: + +.. code-block:: bash + + git log --decorate --oneline --graph --all + # * 4d4cb0a (tag: v1.2.3, tag: v1.2, tag: v1, origin/main, main) 1.2.3 + # * 3a2b1c0 fix: some bug + # * 2b1c0a9 (tag: v1.2.2) 1.2.2 + # ... + +If build-metadata is used, the next version of ``1.2.3+20251109`` will result in: + +.. code-block:: bash + + git log --decorate --oneline --graph --all + # * 4d4cb0a (tag: v1.2.3+20251109, tag: v1.2.3, tag: v1.2, tag: v1, origin/main, main) 1.2.3+20251109 + # * 3a2b1c0 chore: add partial tags to PSR configuration + # * 2b1c0a9 (tag: v1.2.3+20251031) 1.2.3+20251031 + # ... + +**Default:** ``false`` + +---- + .. _config-allow_zero_version: ``allow_zero_version`` @@ -1162,52 +1208,6 @@ from the :ref:`remote.name ` location of your git repository ---- -.. _config-add_partial_tags: - -``add_partial_tags`` -"""""""""""""""""""" - -**Type:** ``bool`` - -Specify if partial version tags should be handled when creating a new version. If set to -``true``, a ``major`` and a ``major.minor`` tag will be created or updated, using the format -specified in :ref:`tag_format`. If version has build metadata, a ``major.minor.patch`` tag -will also be created or updated. - -Partial version tags are **disabled** for pre-release versions. - -**Example** - -.. code-block:: toml - - [semantic_release] - tag_format = "v{version}" - add_partial_tags = true - -This configuration with the next version of ``1.2.3`` will result in: - -.. code-block:: bash - - git log --decorate --oneline --graph --all - # * 4d4cb0a (tag: v1.2.3, tag: v1.2, tag: v1, origin/main, main) 1.2.3 - # * 3a2b1c0 fix: some bug - # * 2b1c0a9 (tag: v1.2.2) 1.2.2 - # ... - -If build-metadata is used, the next version of ``1.2.3+20251109`` will result in: - -.. code-block:: bash - - git log --decorate --oneline --graph --all - # * 4d4cb0a (tag: v1.2.3+20251109, tag: v1.2.3, tag: v1.2, tag: v1, origin/main, main) 1.2.3+20251109 - # * 3a2b1c0 chore: add partial tags to PSR configuration - # * 2b1c0a9 (tag: v1.2.3+20251031) 1.2.3+20251031 - # ... - -**Default:** ``false`` - ----- - .. _config-tag_format: ``tag_format`` From 7a1f822c06f5258f8b82ea9563b56979d3bc1cd9 Mon Sep 17 00:00:00 2001 From: aconal-com Date: Mon, 6 Jul 2026 05:33:09 +0200 Subject: [PATCH 2/5] fix(config): eliminate `.git/` in parent dir warnings for monorepos configured with `..` (#1444) In monorepo setups where `repo_dir = '..'` is configured for a subpackage, `Path('..').absolute()` returns `/path/to/package/..` rather than the resolved `/path/to/repo`. This change resolves symlinks and normalizes paths, preventing additional `'Found .git/ in higher parent directory'` warnings. Resolves: #1418 * docs(configuration): document `repo_dir` config option * test(fixtures): update example monorepo to configure `repo_dir` as parent dir * test(cmd-version): update rebuild repo tests to check for `.git/` in parent dir warning * test(cmd-version): add e2e test to check for warning of `.git/` in parent dir * test(fixtures): adjust change directory for windows compatibility --------- Co-authored-by: Aniket Karne Co-authored-by: codejedi365 Signed-off-by: codejedi365 --- docs/configuration/configuration.rst | 19 +++++++++ src/semantic_release/cli/config.py | 28 +++++++++---- .../git_flow/test_repo_1_channel.py | 5 ++- .../git_flow/test_repo_2_channels.py | 5 ++- .../git_flow/test_repo_3_channels.py | 5 ++- .../git_flow/test_repo_4_channels.py | 5 ++- .../github_flow/test_repo_1_channel.py | 5 ++- ...test_repo_1_channel_branch_update_merge.py | 5 ++- .../github_flow/test_repo_2_channels.py | 5 ++- .../test_monorepo_1_channel.py | 7 +++- .../test_monorepo_2_channels.py | 7 +++- .../trunk_based_dev/test_repo_trunk.py | 5 ++- .../test_repo_trunk_dual_version_support.py | 5 ++- ...runk_dual_version_support_w_prereleases.py | 5 ++- .../test_repo_trunk_w_prereleases.py | 5 ++- .../test_monorepo_trunk.py | 7 +++- tests/e2e/cmd_version/test_version.py | 42 ++++++++++++++++++- tests/fixtures/example_project.py | 11 +++-- tests/fixtures/git_repo.py | 4 +- tests/fixtures/monorepos/example_monorepo.py | 28 +++++++++++++ tests/util.py | 23 ++++++++++ 21 files changed, 204 insertions(+), 27 deletions(-) diff --git a/docs/configuration/configuration.rst b/docs/configuration/configuration.rst index b39e6a30b..0a11ce8a0 100644 --- a/docs/configuration/configuration.rst +++ b/docs/configuration/configuration.rst @@ -1208,6 +1208,25 @@ from the :ref:`remote.name ` location of your git repository ---- +.. _config-repo_dir: + +``repo_dir`` +"""""""""""" + +**Type:** ``str`` + +Specify the directory of the Git repository. This is used to determine the location of +the repository for various operations, such as creating tags and commits. PSR will attempt +to automatically determine the location of the repository in parent directories of the +current working directory but will emit a warning if it is higher than this defined value. + +If a git repository is not found from this location or any parent directories, PSR will +raise an error and exit. + +**Default:** ``"."`` + +---- + .. _config-tag_format: ``tag_format`` diff --git a/src/semantic_release/cli/config.py b/src/semantic_release/cli/config.py index 76ccd1e68..8284e23c7 100644 --- a/src/semantic_release/cli/config.py +++ b/src/semantic_release/cli/config.py @@ -13,7 +13,18 @@ error as RegExpError, # noqa: N812 escape as regex_escape, ) -from typing import Any, ClassVar, Dict, List, Literal, Optional, Tuple, Type, Union +from typing import ( + Any, + ClassVar, + Dict, + List, + Literal, + Optional, + Tuple, + Type, + Union, + cast, +) # typing_extensions is for Python 3.8, 3.9, 3.10 compatibility import tomlkit @@ -363,7 +374,7 @@ class RawConfig(BaseModel): logging_use_named_masks: bool = False major_on_zero: bool = True allow_zero_version: bool = False - repo_dir: Annotated[Path, Field(validate_default=True)] = Path(".") + repo_dir: Path = Field(default=cast("Path", "."), validate_default=True) remote: RemoteConfig = RemoteConfig() no_git_verify: bool = False tag_format: str = "v{version}" @@ -388,18 +399,19 @@ def verify_git_repo_dir(cls, dir_path: Path) -> Path: found_path = ( Path(git_repo.working_tree_dir or git_repo.working_dir) .expanduser() + .resolve() .absolute() ) except InvalidGitRepositoryError as err: - raise InvalidGitRepositoryError("No valid git repository found!") from err + msg = "No valid git repository found!" + raise InvalidGitRepositoryError(msg) from err - if dir_path.absolute() != found_path: - logging.warning( - "Found .git/ in higher parent directory rather than provided in configuration." - ) + if dir_path.resolve().absolute() != found_path: + msg = "Found .git/ in higher parent directory rather than provided in configuration." + logger.warning(msg) - return found_path.resolve() + return found_path @field_validator("commit_parser", mode="after") @classmethod diff --git a/tests/e2e/cmd_version/bump_version/git_flow/test_repo_1_channel.py b/tests/e2e/cmd_version/bump_version/git_flow/test_repo_1_channel.py index ee17c5214..33665dcc4 100644 --- a/tests/e2e/cmd_version/bump_version/git_flow/test_repo_1_channel.py +++ b/tests/e2e/cmd_version/bump_version/git_flow/test_repo_1_channel.py @@ -10,7 +10,7 @@ repo_w_git_flow_emoji_commits, repo_w_git_flow_scipy_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from pathlib import Path @@ -66,6 +66,7 @@ def test_gitflow_repo_rebuild_1_channel( pyproject_toml_file: Path, changelog_md_file: Path, changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -153,6 +154,8 @@ def test_gitflow_repo_rebuild_1_channel( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we are running in the same directory as the .git repo + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert expected_pyproject_toml_content == actual_pyproject_toml_content assert expected_version_file_content == actual_version_file_content diff --git a/tests/e2e/cmd_version/bump_version/git_flow/test_repo_2_channels.py b/tests/e2e/cmd_version/bump_version/git_flow/test_repo_2_channels.py index 27ff5f339..abfea6f40 100644 --- a/tests/e2e/cmd_version/bump_version/git_flow/test_repo_2_channels.py +++ b/tests/e2e/cmd_version/bump_version/git_flow/test_repo_2_channels.py @@ -10,7 +10,7 @@ repo_w_git_flow_w_alpha_prereleases_n_emoji_commits, repo_w_git_flow_w_alpha_prereleases_n_scipy_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from pathlib import Path @@ -66,6 +66,7 @@ def test_gitflow_repo_rebuild_2_channels( pyproject_toml_file: Path, changelog_md_file: Path, changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -153,6 +154,8 @@ def test_gitflow_repo_rebuild_2_channels( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we are running in the same directory as the .git repo + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert expected_pyproject_toml_content == actual_pyproject_toml_content assert expected_version_file_content == actual_version_file_content diff --git a/tests/e2e/cmd_version/bump_version/git_flow/test_repo_3_channels.py b/tests/e2e/cmd_version/bump_version/git_flow/test_repo_3_channels.py index 5b32befd1..517f3e39b 100644 --- a/tests/e2e/cmd_version/bump_version/git_flow/test_repo_3_channels.py +++ b/tests/e2e/cmd_version/bump_version/git_flow/test_repo_3_channels.py @@ -11,7 +11,7 @@ repo_w_git_flow_w_rc_n_alpha_prereleases_n_emoji_commits, repo_w_git_flow_w_rc_n_alpha_prereleases_n_scipy_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from pathlib import Path @@ -68,6 +68,7 @@ def test_gitflow_repo_rebuild_3_channels( pyproject_toml_file: Path, changelog_md_file: Path, changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -154,6 +155,8 @@ def test_gitflow_repo_rebuild_3_channels( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we are running in the same directory as the .git repo + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert expected_pyproject_toml_content == actual_pyproject_toml_content assert expected_version_file_content == actual_version_file_content diff --git a/tests/e2e/cmd_version/bump_version/git_flow/test_repo_4_channels.py b/tests/e2e/cmd_version/bump_version/git_flow/test_repo_4_channels.py index 2a135b116..d536e7283 100644 --- a/tests/e2e/cmd_version/bump_version/git_flow/test_repo_4_channels.py +++ b/tests/e2e/cmd_version/bump_version/git_flow/test_repo_4_channels.py @@ -10,7 +10,7 @@ repo_w_git_flow_w_beta_alpha_rev_prereleases_n_emoji_commits, repo_w_git_flow_w_beta_alpha_rev_prereleases_n_scipy_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from pathlib import Path @@ -66,6 +66,7 @@ def test_gitflow_repo_rebuild_4_channels( pyproject_toml_file: Path, changelog_md_file: Path, changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -153,6 +154,8 @@ def test_gitflow_repo_rebuild_4_channels( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we are running in the same directory as the .git repo + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert expected_pyproject_toml_content == actual_pyproject_toml_content assert expected_version_file_content == actual_version_file_content diff --git a/tests/e2e/cmd_version/bump_version/github_flow/test_repo_1_channel.py b/tests/e2e/cmd_version/bump_version/github_flow/test_repo_1_channel.py index fedd861dd..6473d81c8 100644 --- a/tests/e2e/cmd_version/bump_version/github_flow/test_repo_1_channel.py +++ b/tests/e2e/cmd_version/bump_version/github_flow/test_repo_1_channel.py @@ -10,7 +10,7 @@ repo_w_github_flow_w_default_release_channel_emoji_commits, repo_w_github_flow_w_default_release_channel_scipy_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from pathlib import Path @@ -66,6 +66,7 @@ def test_githubflow_repo_rebuild_1_channel( pyproject_toml_file: Path, changelog_md_file: Path, changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -153,6 +154,8 @@ def test_githubflow_repo_rebuild_1_channel( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we are running in the same directory as the .git repo + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert expected_pyproject_toml_content == actual_pyproject_toml_content assert expected_version_file_content == actual_version_file_content diff --git a/tests/e2e/cmd_version/bump_version/github_flow/test_repo_1_channel_branch_update_merge.py b/tests/e2e/cmd_version/bump_version/github_flow/test_repo_1_channel_branch_update_merge.py index a3018d346..3fa862413 100644 --- a/tests/e2e/cmd_version/bump_version/github_flow/test_repo_1_channel_branch_update_merge.py +++ b/tests/e2e/cmd_version/bump_version/github_flow/test_repo_1_channel_branch_update_merge.py @@ -13,7 +13,7 @@ repo_w_github_flow_w_default_release_n_branch_update_merge_emoji_commits, repo_w_github_flow_w_default_release_n_branch_update_merge_scipy_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from pathlib import Path @@ -72,6 +72,7 @@ def test_github_flow_repo_w_default_release_n_branch_update_merge( pyproject_toml_file: Path, changelog_md_file: Path, changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -166,6 +167,8 @@ def test_github_flow_repo_w_default_release_n_branch_update_merge( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we are running in the same directory as the .git repo + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert expected_pyproject_toml_content == actual_pyproject_toml_content assert expected_version_file_content == actual_version_file_content diff --git a/tests/e2e/cmd_version/bump_version/github_flow/test_repo_2_channels.py b/tests/e2e/cmd_version/bump_version/github_flow/test_repo_2_channels.py index e86858b55..0ed421e66 100644 --- a/tests/e2e/cmd_version/bump_version/github_flow/test_repo_2_channels.py +++ b/tests/e2e/cmd_version/bump_version/github_flow/test_repo_2_channels.py @@ -10,7 +10,7 @@ repo_w_github_flow_w_feature_release_channel_emoji_commits, repo_w_github_flow_w_feature_release_channel_scipy_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from pathlib import Path @@ -66,6 +66,7 @@ def test_githubflow_repo_rebuild_2_channels( pyproject_toml_file: Path, changelog_md_file: Path, changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -153,6 +154,8 @@ def test_githubflow_repo_rebuild_2_channels( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we are running in the same directory as the .git repo + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert expected_pyproject_toml_content == actual_pyproject_toml_content assert expected_version_file_content == actual_version_file_content diff --git a/tests/e2e/cmd_version/bump_version/github_flow_monorepo/test_monorepo_1_channel.py b/tests/e2e/cmd_version/bump_version/github_flow_monorepo/test_monorepo_1_channel.py index c0dafbf7c..d9554c4ee 100644 --- a/tests/e2e/cmd_version/bump_version/github_flow_monorepo/test_monorepo_1_channel.py +++ b/tests/e2e/cmd_version/bump_version/github_flow_monorepo/test_monorepo_1_channel.py @@ -12,7 +12,7 @@ from tests.fixtures.monorepos.github_flow import ( monorepo_w_github_flow_w_default_release_channel_conventional_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from typing import Literal, Sequence @@ -71,6 +71,7 @@ def test_githubflow_monorepo_rebuild_1_channel( monorepo_pkg2_changelog_md_file: Path, monorepo_pkg1_changelog_rst_file: Path, monorepo_pkg2_changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -225,6 +226,10 @@ def test_githubflow_monorepo_rebuild_1_channel( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we have configured repo_dir + # to be the parent directory from where PSR is being run, so although it is in the + # parent directory, it is known to the user and should not be a warning + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert ( expected_pkg1_pyproject_toml_content == actual_pkg1_pyproject_toml_content diff --git a/tests/e2e/cmd_version/bump_version/github_flow_monorepo/test_monorepo_2_channels.py b/tests/e2e/cmd_version/bump_version/github_flow_monorepo/test_monorepo_2_channels.py index 7c3e36390..a6d75b4fe 100644 --- a/tests/e2e/cmd_version/bump_version/github_flow_monorepo/test_monorepo_2_channels.py +++ b/tests/e2e/cmd_version/bump_version/github_flow_monorepo/test_monorepo_2_channels.py @@ -12,7 +12,7 @@ from tests.fixtures.monorepos.github_flow import ( monorepo_w_github_flow_w_feature_release_channel_conventional_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from typing import Literal, Sequence @@ -71,6 +71,7 @@ def test_githubflow_monorepo_rebuild_2_channels( monorepo_pkg2_changelog_md_file: Path, monorepo_pkg1_changelog_rst_file: Path, monorepo_pkg2_changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -224,6 +225,10 @@ def test_githubflow_monorepo_rebuild_2_channels( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we have configured repo_dir + # to be the parent directory from where PSR is being run, so although it is in the + # parent directory, it is known to the user and should not be a warning + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert ( expected_pkg1_pyproject_toml_content == actual_pkg1_pyproject_toml_content diff --git a/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk.py b/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk.py index b0f05c41b..cfa122d12 100644 --- a/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk.py +++ b/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk.py @@ -10,7 +10,7 @@ repo_w_trunk_only_emoji_commits, repo_w_trunk_only_scipy_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from pathlib import Path @@ -68,6 +68,7 @@ def test_trunk_repo_rebuild_only_official_releases( pyproject_toml_file: Path, changelog_md_file: Path, changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -155,6 +156,8 @@ def test_trunk_repo_rebuild_only_official_releases( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we are running in the same directory as the .git repo + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert expected_pyproject_toml_content == actual_pyproject_toml_content assert expected_version_file_content == actual_version_file_content diff --git a/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk_dual_version_support.py b/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk_dual_version_support.py index 223e7a1f6..0b7b651fa 100644 --- a/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk_dual_version_support.py +++ b/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk_dual_version_support.py @@ -13,7 +13,7 @@ repo_w_trunk_only_dual_version_spt_emoji_commits, repo_w_trunk_only_dual_version_spt_scipy_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from pathlib import Path @@ -69,6 +69,7 @@ def test_trunk_repo_rebuild_dual_version_spt_official_releases_only( pyproject_toml_file: Path, changelog_md_file: Path, changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -161,6 +162,8 @@ def test_trunk_repo_rebuild_dual_version_spt_official_releases_only( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we are running in the same directory as the .git repo + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert expected_pyproject_toml_content == actual_pyproject_toml_content assert expected_version_file_content == actual_version_file_content diff --git a/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk_dual_version_support_w_prereleases.py b/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk_dual_version_support_w_prereleases.py index 2ef42b490..0eff0a430 100644 --- a/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk_dual_version_support_w_prereleases.py +++ b/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk_dual_version_support_w_prereleases.py @@ -13,7 +13,7 @@ repo_w_trunk_only_dual_version_spt_w_prereleases_emoji_commits, repo_w_trunk_only_dual_version_spt_w_prereleases_scipy_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from pathlib import Path @@ -70,6 +70,7 @@ def test_trunk_repo_rebuild_dual_version_spt_w_official_n_prereleases( pyproject_toml_file: Path, changelog_md_file: Path, changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -162,6 +163,8 @@ def test_trunk_repo_rebuild_dual_version_spt_w_official_n_prereleases( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we are running in the same directory as the .git repo + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert expected_pyproject_toml_content == actual_pyproject_toml_content assert expected_version_file_content == actual_version_file_content diff --git a/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk_w_prereleases.py b/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk_w_prereleases.py index 5d3f1684f..e41a7ae48 100644 --- a/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk_w_prereleases.py +++ b/tests/e2e/cmd_version/bump_version/trunk_based_dev/test_repo_trunk_w_prereleases.py @@ -10,7 +10,7 @@ repo_w_trunk_only_n_prereleases_emoji_commits, repo_w_trunk_only_n_prereleases_scipy_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from pathlib import Path @@ -66,6 +66,7 @@ def test_trunk_repo_rebuild_w_prereleases( pyproject_toml_file: Path, changelog_md_file: Path, changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -153,6 +154,8 @@ def test_trunk_repo_rebuild_w_prereleases( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we are running in the same directory as the .git repo + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert expected_pyproject_toml_content == actual_pyproject_toml_content assert expected_version_file_content == actual_version_file_content diff --git a/tests/e2e/cmd_version/bump_version/trunk_based_dev_monorepo/test_monorepo_trunk.py b/tests/e2e/cmd_version/bump_version/trunk_based_dev_monorepo/test_monorepo_trunk.py index 60aae38cb..56661023f 100644 --- a/tests/e2e/cmd_version/bump_version/trunk_based_dev_monorepo/test_monorepo_trunk.py +++ b/tests/e2e/cmd_version/bump_version/trunk_based_dev_monorepo/test_monorepo_trunk.py @@ -12,7 +12,7 @@ from tests.fixtures.monorepos.trunk_based_dev import ( monorepo_w_trunk_only_releases_conventional_commits, ) -from tests.util import temporary_working_directory +from tests.util import assert_str_not_in_output, temporary_working_directory if TYPE_CHECKING: from typing import Literal, Sequence @@ -71,6 +71,7 @@ def test_trunk_monorepo_rebuild_1_channel( monorepo_pkg2_changelog_md_file: Path, monorepo_pkg1_changelog_rst_file: Path, monorepo_pkg2_changelog_rst_file: Path, + caplog: pytest.LogCaptureFixture, ): # build target repo into a temporary directory target_repo_dir = example_project_dir / repo_fixture_name @@ -225,6 +226,10 @@ def test_trunk_monorepo_rebuild_1_channel( # Evaluate (normal release actions should have occurred as expected) # ------------------------------------------------------------------ + # The warning should not be present in the logs since we have configured repo_dir + # to be the parent directory from where PSR is being run, so although it is in the + # parent directory, it is known to the user and should not be a warning + assert_str_not_in_output("Found .git/ in higher parent directory", caplog.text) # Make sure version file is updated assert ( expected_pkg1_pyproject_toml_content == actual_pkg1_pyproject_toml_content diff --git a/tests/e2e/cmd_version/test_version.py b/tests/e2e/cmd_version/test_version.py index 2bf952647..e5d5bf2da 100644 --- a/tests/e2e/cmd_version/test_version.py +++ b/tests/e2e/cmd_version/test_version.py @@ -13,11 +13,14 @@ MAIN_PROG_NAME, VERSION_SUBCMD, ) +from tests.fixtures.monorepos import ( + monorepo_w_trunk_only_releases_conventional_commits, +) from tests.fixtures.repos import ( repo_w_no_tags_conventional_commits, repo_w_trunk_only_conventional_commits, ) -from tests.util import assert_successful_exit_code +from tests.util import assert_successful_exit_code, temporary_working_directory if TYPE_CHECKING: from unittest.mock import MagicMock @@ -291,3 +294,40 @@ def test_version_only_tag_push( assert head_before == head_after assert mocked_git_push.call_count == 1 # 0 for commit, 1 for tag assert post_mocker.call_count == 1 + + +@pytest.mark.usefixtures(monorepo_w_trunk_only_releases_conventional_commits.__name__) +def test_version_warning_on_not_configured_repo_dir( + run_cli: RunCliFn, + update_pyproject_toml: UpdatePyprojectTomlFn, + monorepo_pkg1_pyproject_toml_file: Path, + monorepo_pkg1_dir: Path, +): + """ + Given a repo with a subdirectory that is not configured in the pyproject.toml, + When running the version command from that subdirectory, + Then a warning should be printed to stderr indicating that the .git directory + was found in a higher parent directory. + + Note: we are using a monorepo for testing since it will automatically set up a + subdirectory with a pyproject.toml file and the .git/ directory in a parent + directory by default, making it easy to test. The successful measure of no + warning is tested throughout the e2e tests for cmd-version. + """ + # Setup: set the repo_dir to None in the pyproject.toml of a subdirectory of the repo + update_pyproject_toml( + "tool.semantic_release.repo_dir", + None, + monorepo_pkg1_pyproject_toml_file, + ) + + # Act + cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--print"] + + # Act: Run release on a subdirectory of the repo that is not configured in the pyproject.toml + with temporary_working_directory(monorepo_pkg1_dir): + result = run_cli(cli_cmd[1:], env={Github.DEFAULT_ENV_TOKEN_NAME: "1234"}) + + # Evaluate + assert_successful_exit_code(result, cli_cmd) + assert "Found .git/ in higher parent directory" in result.stderr diff --git a/tests/fixtures/example_project.py b/tests/fixtures/example_project.py index 41664f75a..bf1bf6307 100644 --- a/tests/fixtures/example_project.py +++ b/tests/fixtures/example_project.py @@ -367,9 +367,14 @@ def get_parser_from_config_file( def _get_parser_from_config( file: Path | str = pyproject_toml_file, ) -> CommitParser[ParseResult, ParserOptions]: - return load_runtime_context( - cli_opts=GlobalCommandLineOptions(config_file=str(Path(file))) - ).commit_parser + file_path = Path(file).resolve() + + # Use a temporary working directory to ensure that the current working directory + # does not affect the loading of the runtime context and commit parser. + with temporary_working_directory(file_path.parent): + return load_runtime_context( + cli_opts=GlobalCommandLineOptions(config_file=str(file_path)) + ).commit_parser return _get_parser_from_config diff --git a/tests/fixtures/git_repo.py b/tests/fixtures/git_repo.py index 613955290..5840f7608 100644 --- a/tests/fixtures/git_repo.py +++ b/tests/fixtures/git_repo.py @@ -1574,7 +1574,9 @@ def _build_repo_from_definition( # noqa: C901, its required and its just test c # Helpful Transform to find the project root repo without needing to pass it around (ie '/' => repo_dir) new_cwd = ( - repo_dir if str(new_cwd) == str(repo_dir.root) else new_cwd + repo_dir + if str(new_cwd) == str(Path(repo_dir.root).resolve()) + else new_cwd ) if not new_cwd.is_dir(): diff --git a/tests/fixtures/monorepos/example_monorepo.py b/tests/fixtures/monorepos/example_monorepo.py index 1b46bde2b..dd708aaf3 100644 --- a/tests/fixtures/monorepos/example_monorepo.py +++ b/tests/fixtures/monorepos/example_monorepo.py @@ -180,6 +180,34 @@ def hello_world() -> None: ], cached_project_path / monorepo_pkg2_pyproject_toml_file, ), + ( + "tool.semantic_release.repo_dir", + str( + Path( + *( + ".." + for _ in range( + len(monorepo_pkg1_pyproject_toml_file.parent.parts) + ) + ) + ) + ), + cached_project_path / monorepo_pkg1_pyproject_toml_file, + ), + ( + "tool.semantic_release.repo_dir", + str( + Path( + *( + ".." + for _ in range( + len(monorepo_pkg2_pyproject_toml_file.parent.parts) + ) + ) + ) + ), + cached_project_path / monorepo_pkg2_pyproject_toml_file, + ), ] for setting, value, toml_file in config_updates: diff --git a/tests/util.py b/tests/util.py index 8ddff0a83..ef3f5c001 100644 --- a/tests/util.py +++ b/tests/util.py @@ -79,6 +79,29 @@ def assert_successful_exit_code(result: ClickInvokeResult, cli_cmd: list[str]) - return assert_exit_code(SUCCESS_EXIT_CODE, result, cli_cmd) +def assert_str_not_in_output(substring: str, output: str) -> bool: + found_lines: list[str] = list( + filter( + lambda line, substr=substring: substr in line, # type: ignore[arg-type] + output.splitlines(), + ) + ) + num_found_lines = len(found_lines) + + if num_found_lines == 0: + return True + + raise AssertionError( + str.join( + os.linesep, + [ + f"Found {num_found_lines} lines in output containing {substring!r}:", + indent(str.join(os.linesep, found_lines), " " * 2), + ], + ) + ) + + def get_full_qualname(callable_obj: Callable[[Any], Any]) -> str: parts = filter( None, From 39dd2052f2ce8282a5d932c31d58a2ca06d2550e Mon Sep 17 00:00:00 2001 From: semantic-release Date: Mon, 6 Jul 2026 06:14:02 +0000 Subject: [PATCH 3/5] chore: release v10.6.1 Automatically generated by python-semantic-release --- CHANGELOG.rst | 49 +++++++++++++++++++ .../automatic-releases/github-actions.rst | 4 +- pyproject.toml | 2 +- src/gh_action/requirements.txt | 2 +- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 651e00b44..fc6c8fac4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,55 @@ CHANGELOG ========= +.. _changelog-v10.6.1: + +v10.6.1 (2026-07-06) +==================== + +🪲 Bug Fixes +------------ + +* **changelog**: Fix handling of whitespace commit bodies in changelog template filter (`PR#1457`_, + `d95e46e`_) + +* **cmd-version**: Fix non-styled error msg when strict & no new version, closes `#1423`_ + (`PR#1437`_, `5e8f94c`_) + +* **config**: Eliminate ``.git/`` in parent dir warnings for monorepos configured with ``..``, + closes `#1418`_ (`PR#1444`_, `7a1f822`_) + +📖 Documentation +---------------- + +* **CHANGELOG**: Add ``v9.21.2`` changelog details for website (`a4115cf`_) + +* **configuration**: Document ``repo_dir`` config option (`PR#1444`_, `7a1f822`_) + +⚙️ Build System +---------------- + +* **deps**: Expand ``python-gitlab`` dependency range to include ``v8.0.0+`` (`PR#1451`_, + `a4b9a43`_) + +* **deps**: Expand ``tomlkit`` dependency range to include ``v0.14.0+`` & ``v0.15.0+`` (`028d539`_) + +* **deps**: Extend ``click`` dependency range to include ``v8.2+`` (`01707ea`_) + +.. _#1418: https://github.com/python-semantic-release/python-semantic-release/issues/1418 +.. _#1423: https://github.com/python-semantic-release/python-semantic-release/issues/1423 +.. _01707ea: https://github.com/python-semantic-release/python-semantic-release/commit/01707ead53e093fe217a82c9ff9898c5e4daf9dc +.. _028d539: https://github.com/python-semantic-release/python-semantic-release/commit/028d53909276270ce969d246ed739afd7808eacd +.. _5e8f94c: https://github.com/python-semantic-release/python-semantic-release/commit/5e8f94c3d81ccf17598af8a77659dd31df2ea403 +.. _7a1f822: https://github.com/python-semantic-release/python-semantic-release/commit/7a1f822c06f5258f8b82ea9563b56979d3bc1cd9 +.. _a4115cf: https://github.com/python-semantic-release/python-semantic-release/commit/a4115cfe98b98598adc1b44e04565ec0254b604d +.. _a4b9a43: https://github.com/python-semantic-release/python-semantic-release/commit/a4b9a438846c9f795b8bbaf2b145077fb6c3f7a5 +.. _d95e46e: https://github.com/python-semantic-release/python-semantic-release/commit/d95e46e7603b559c6de6160092c0b9af9a428f02 +.. _PR#1437: https://github.com/python-semantic-release/python-semantic-release/pull/1437 +.. _PR#1444: https://github.com/python-semantic-release/python-semantic-release/pull/1444 +.. _PR#1451: https://github.com/python-semantic-release/python-semantic-release/pull/1451 +.. _PR#1457: https://github.com/python-semantic-release/python-semantic-release/pull/1457 + + .. _changelog-v10.6.0: v10.6.0 (2026-07-04) diff --git a/docs/configuration/automatic-releases/github-actions.rst b/docs/configuration/automatic-releases/github-actions.rst index 7a7f7ad7f..763edddd2 100644 --- a/docs/configuration/automatic-releases/github-actions.rst +++ b/docs/configuration/automatic-releases/github-actions.rst @@ -893,14 +893,14 @@ to the GitHub Release Assets as well. - name: Action | Semantic Version Release id: release # Adjust tag with desired version if applicable. - uses: python-semantic-release/python-semantic-release@COMMIT_HASH # v10.6.0 + uses: python-semantic-release/python-semantic-release@COMMIT_HASH # v10.6.1 with: github_token: ${{ secrets.GITHUB_TOKEN }} git_committer_name: "github-actions" git_committer_email: "actions@users.noreply.github.com" - name: Publish | Upload to GitHub Release Assets - uses: python-semantic-release/publish-action@COMMIT_HASH # v10.6.0 + uses: python-semantic-release/publish-action@COMMIT_HASH # v10.6.1 if: steps.release.outputs.released == 'true' with: github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/pyproject.toml b/pyproject.toml index d688ee0e7..63229986f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" [project] name = "python-semantic-release" -version = "10.6.0" +version = "10.6.1" description = "Automatic Semantic Versioning for Python projects" requires-python = "~= 3.8" license = { text = "MIT" } diff --git a/src/gh_action/requirements.txt b/src/gh_action/requirements.txt index 88acf11bb..bd2ef457b 100644 --- a/src/gh_action/requirements.txt +++ b/src/gh_action/requirements.txt @@ -1 +1 @@ -python-semantic-release == 10.6.0 +python-semantic-release == 10.6.1 From 57479b4fda043c6f00f673694a8bb61595f0e0e4 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Mon, 6 Jul 2026 00:28:46 -0600 Subject: [PATCH 4/5] ci(deps): bump `python-semantic-release@v10.6.0` action to `v10.6.1` (#1459) --- .github/workflows/cicd.yml | 2 +- .github/workflows/validate.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 4c9565b29..6142dad5b 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -142,7 +142,7 @@ jobs: - name: Release | Python Semantic Release id: release - uses: python-semantic-release/python-semantic-release@37a30a7987cfebb6d49240bf1c4e9cd9817d0673 # v10.6.0 + uses: python-semantic-release/python-semantic-release@39dd2052f2ce8282a5d932c31d58a2ca06d2550e # v10.6.1 with: github_token: ${{ secrets.GITHUB_TOKEN }} verbosity: 1 diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index b0e966d16..ea3e66cbd 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -112,7 +112,7 @@ jobs: - name: Build | Build next version artifacts id: version - uses: python-semantic-release/python-semantic-release@37a30a7987cfebb6d49240bf1c4e9cd9817d0673 # v10.6.0 + uses: python-semantic-release/python-semantic-release@39dd2052f2ce8282a5d932c31d58a2ca06d2550e # v10.6.1 with: github_token: "" verbosity: 1 From 7816daff16382bc227b73ce53f32acac29a45ca3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 06:27:58 +0000 Subject: [PATCH 5/5] ci(deps): bump `python-semantic-release/publish-action@v10.6.0` to `v10.6.1` (#1459) --- .github/workflows/cicd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 6142dad5b..96a63f8bd 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -149,7 +149,7 @@ jobs: build: false - name: Release | Add distribution artifacts to GitHub Release Assets - uses: python-semantic-release/publish-action@4f3c5d7f5caddf6535050c4bcb55f033f000a7dd # v10.6.0 + uses: python-semantic-release/publish-action@5a5718ce47b892ef699f2972dae122297771d641 # v10.6.1 if: steps.release.outputs.released == 'true' with: github_token: ${{ secrets.GITHUB_TOKEN }}