From a4115cfe98b98598adc1b44e04565ec0254b604d Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Fri, 3 Jul 2026 20:16:40 -0600 Subject: [PATCH 01/26] docs(CHANGELOG): add `v9.21.2` changelog details for website --- CHANGELOG.rst | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5decef8f5..651e00b44 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -778,6 +778,39 @@ v10.0.0 (2025-05-25) .. _PR#1245: https://github.com/python-semantic-release/python-semantic-release/pull/1245 +.. _changelog-v9.21.2: + +v9.21.2 (2026-07-04) +==================== + +🪲 Bug Fixes +------------ + +* **hvcs**: Mask credentials in git URL debug logs, closes `#1426`_ (`PR#1450`_, `da0cb2b`_) + +📖 Documentation +---------------- + +* **github-actions**: Fix recommended upstream detection script's upstream name parsing (`911f62a`_) + +⚙️ Build System +---------------- + +* Mark for Python 3.14 compatibility (`86c0439`_) + +* **deps**: Bump ``tomlkit`` dependency from ``~=0.11.0`` to ``~=0.13.0`` (`5395d06`_) + +* **deps**: Prevent update to ``click@8.2.0`` (`128f06a`_) + +.. _#1426: https://github.com/python-semantic-release/python-semantic-release/issues/1426 +.. _128f06a: https://github.com/python-semantic-release/python-semantic-release/commit/128f06a512ff782b773df2989d3445f894672ace +.. _5395d06: https://github.com/python-semantic-release/python-semantic-release/commit/5395d065fc890813b1ef0df1c024a714668cb102 +.. _86c0439: https://github.com/python-semantic-release/python-semantic-release/commit/86c04399fc66fa9584c6c875698a43e91104186b +.. _911f62a: https://github.com/python-semantic-release/python-semantic-release/commit/911f62aa6ab0a169a4126bea44fbc8dfb4f967b6 +.. _da0cb2b: https://github.com/python-semantic-release/python-semantic-release/commit/da0cb2bb40ffdd898117b72e3309e2281fdf682c +.. _PR#1450: https://github.com/python-semantic-release/python-semantic-release/pull/1450 + + .. _changelog-v9.21.1: v9.21.1 (2025-05-05) From 15f3281bc4607476784f6cb5128f985d17a1356c Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Fri, 3 Jul 2026 22:26:44 -0600 Subject: [PATCH 02/26] ci(deps): bump `python-semantic-release@v10.5.3` action to `v10.6.0` --- .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 ee476daf7..d6fc8de73 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@350c48fcb3ffcdfd2e0a235206bc2ecea6b69df0 # v10.5.3 + uses: python-semantic-release/python-semantic-release@37a30a7987cfebb6d49240bf1c4e9cd9817d0673 # v10.6.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} verbosity: 1 diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 2623eccdf..198fd2c3a 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@350c48fcb3ffcdfd2e0a235206bc2ecea6b69df0 # v10.5.3 + uses: python-semantic-release/python-semantic-release@37a30a7987cfebb6d49240bf1c4e9cd9817d0673 # v10.6.0 with: github_token: "" verbosity: 1 From 09ac93e285a182873f312b3dffe46e8484bd7915 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Jul 2026 04:21:54 +0000 Subject: [PATCH 03/26] ci(deps): bump `python-semantic-release/publish-action@v10.5.3` to `v10.6.0` --- .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 d6fc8de73..4c9565b29 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@310a9983a0ae878b29f3aac778d7c77c1db27378 # v10.5.3 + uses: python-semantic-release/publish-action@4f3c5d7f5caddf6535050c4bcb55f033f000a7dd # v10.6.0 if: steps.release.outputs.released == 'true' with: github_token: ${{ secrets.GITHUB_TOKEN }} From d95e46e7603b559c6de6160092c0b9af9a428f02 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sat, 4 Jul 2026 00:51:11 -0600 Subject: [PATCH 04/26] fix(changelog): fix handling of whitespace commit bodies in changelog template filter (#1457) Co-authored-by: Amigo --- src/semantic_release/changelog/context.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/semantic_release/changelog/context.py b/src/semantic_release/changelog/context.py index 563f6a3f4..202b2c373 100644 --- a/src/semantic_release/changelog/context.py +++ b/src/semantic_release/changelog/context.py @@ -169,6 +169,11 @@ def autofit_text_width(text: str, maxwidth: int = 100, indent_size: int = 0) -> ) ) + # Guard against empty paragraphs (e.g. from whitespace-only lines in commit bodies), + # which would cause words[0] to raise an IndexError. + if not words: + continue + # Initialize the line for each paragraph line = words[0] next_line = "" From 2b95cf76bfb6faa5bdc3e5100589d6b48c10935c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Jul 2026 00:27:49 -0700 Subject: [PATCH 05/26] build(deps-dev): expand setuptools dependency range to include `v82.0.0` (#1428) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8b3034531..35c7468b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ # Ref: https://packaging.python.org/en/latest/specifications/declaring-project-metadata/ # and https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html [build-system] -requires = ["setuptools >= 75.3.0, < 81.0.0", "wheel ~= 0.42"] +requires = ["setuptools >= 75.3.0, < 83.0.0", "wheel ~= 0.42"] build-backend = "setuptools.build_meta" [project] From a4b9a438846c9f795b8bbaf2b145077fb6c3f7a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Jul 2026 00:41:59 -0700 Subject: [PATCH 06/26] build(deps): expand `python-gitlab` dependency range to include `v8.0.0+` (#1451) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 35c7468b0..7dd7607aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ dependencies = [ "gitpython ~= 3.0", "requests ~= 2.25", "jinja2 ~= 3.1", - "python-gitlab >= 4.0.0, < 7.0.0", + "python-gitlab >= 4.0.0, < 9.0.0", "tomlkit ~= 0.13.0", "dotty-dict ~= 1.3", "importlib-resources ~= 6.0", From e96cfd6161491928df33b546b21f549fe96a6125 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Jul 2026 10:00:41 -0700 Subject: [PATCH 07/26] build(deps-dev): bump `responses@~0.25.0` to `~0.26.2` (#1455) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: dependabot[bot] Signed-off-by: codejedi365 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7dd7607aa..3185d6e64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -80,7 +80,7 @@ test = [ "pytest-order ~= 1.3", "pytest-pretty ~= 1.2", "pytest-xdist ~= 3.0", - "responses ~= 0.25.0", + "responses ~= 0.26.2", "requests-mock ~= 1.10", ] dev = [ From b3f5f0006b15bf97ead26b356e98541dd253ec74 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sat, 4 Jul 2026 12:18:53 -0600 Subject: [PATCH 08/26] test(config): fix pytest configure hook to handle comprehensive `-k` test filter --- tests/conftest.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index df4e2f82d..4e78b59b5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -125,9 +125,9 @@ def pytest_configure(config: pytest.Config): See `pytest_collection_modifyitems` for more information on test selection modifications. """ - user_desired_comprehensive_evaluation = config.getoption("--comprehensive") - user_provided_filter = str(config.getoption("-k")) - user_provided_markers = str(config.getoption("-m")) + user_desired_comprehensive_evaluation = bool(config.getoption("--comprehensive")) + user_provided_filter = str(config.getoption("-k")).strip() + user_provided_markers = str(config.getoption("-m")).strip() root_test_dir = Path(__file__).parent.relative_to(config.rootpath) user_provided_test_path = bool(config.args != [str(root_test_dir)]) @@ -183,7 +183,7 @@ def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item comprehensive_test_skip_marker = pytest.mark.skip( reason="comprehensive tests are disabled by default" ) - user_provided_filter = str(config.getoption("-k")) + user_provided_filter = str(config.getoption("-k")).strip() if any((disable_comprehensive_tests,)): for item in items: From ba3aee257c92c1c597f5c750f09a575ad4a4e907 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sat, 4 Jul 2026 12:29:46 -0600 Subject: [PATCH 09/26] test(unit): adjust test fixture usage style for cleaner tests --- .../declarations/test_toml_declaration.py | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tests/unit/semantic_release/version/declarations/test_toml_declaration.py b/tests/unit/semantic_release/version/declarations/test_toml_declaration.py index a768b6cd3..f90e6dec3 100644 --- a/tests/unit/semantic_release/version/declarations/test_toml_declaration.py +++ b/tests/unit/semantic_release/version/declarations/test_toml_declaration.py @@ -13,6 +13,7 @@ from semantic_release.version.declarations.toml import TomlVersionDeclaration from semantic_release.version.version import Version +from tests.fixtures.example_project import change_to_ex_proj_dir from tests.fixtures.git_repo import default_tag_format_str if TYPE_CHECKING: @@ -115,6 +116,7 @@ def test_toml_declaration_is_version_replacer(): ] ], ) +@pytest.mark.usefixtures(change_to_ex_proj_dir.__name__) def test_toml_declaration_from_definition( replacement_def: str, tag_format: str, @@ -122,7 +124,6 @@ def test_toml_declaration_from_definition( resulting_contents: str, next_version: str, test_file: str, - change_to_ex_proj_dir: None, ): """ Given a file with a formatted version string, @@ -152,9 +153,8 @@ def test_toml_declaration_from_definition( assert expected_filepath == actual_file_modified -def test_toml_declaration_no_file_change( - change_to_ex_proj_dir: None, -): +@pytest.mark.usefixtures(change_to_ex_proj_dir.__name__) +def test_toml_declaration_no_file_change(): """ Given a configured stamp file is already up-to-date, When update_file_w_version() is called with the same version, @@ -202,9 +202,8 @@ def test_toml_declaration_error_on_missing_file(): ) -def test_toml_declaration_no_version_in_file( - change_to_ex_proj_dir: None, -): +@pytest.mark.usefixtures(change_to_ex_proj_dir.__name__) +def test_toml_declaration_no_version_in_file(): test_file = "test_file" expected_filepath = Path(test_file).resolve() starting_contents = dedent( @@ -233,9 +232,8 @@ def test_toml_declaration_no_version_in_file( assert starting_contents == actual_contents -def test_toml_declaration_noop_is_noop( - change_to_ex_proj_dir: None, -): +@pytest.mark.usefixtures(change_to_ex_proj_dir.__name__) +def test_toml_declaration_noop_is_noop(): test_file = "test_file" expected_filepath = Path(test_file).resolve() starting_contents = dedent( @@ -285,9 +283,9 @@ def test_toml_declaration_noop_warning_on_missing_file( ) +@pytest.mark.usefixtures(change_to_ex_proj_dir.__name__) def test_toml_declaration_noop_warning_on_no_version_in_file( capsys: pytest.CaptureFixture[str], - change_to_ex_proj_dir: None, ): test_file = "test_file" starting_contents = dedent( From 028d53909276270ce969d246ed739afd7808eacd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Jul 2026 07:44:11 +0000 Subject: [PATCH 10/26] build(deps): expand `tomlkit` dependency range to include `v0.14.0+` & `v0.15.0+` Signed-off-by: dependabot[bot] Signed-off-by: codejedi365 --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3185d6e64..8f1071d59 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,7 @@ dependencies = [ "requests ~= 2.25", "jinja2 ~= 3.1", "python-gitlab >= 4.0.0, < 9.0.0", - "tomlkit ~= 0.13.0", + "tomlkit >= 0.13.0, < 0.16.0", "dotty-dict ~= 1.3", "importlib-resources ~= 6.0", "pydantic ~= 2.0", @@ -57,7 +57,7 @@ repository = "http://github.com/python-semantic-release/python-semantic-release. [project.optional-dependencies] build = [ "build ~= 1.2", - "tomlkit ~= 0.13.0", + "tomlkit >= 0.13.0, < 0.16.0", ] docs = [ "Sphinx ~= 7.4", From 31dd27e03cec0b4c9488dafc77473cfb1b82028c Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sat, 4 Jul 2026 12:17:53 -0600 Subject: [PATCH 11/26] refactor(stamp-version): adjust toml version stamper to prevent re-ordering keyed output --- src/semantic_release/cli/cli_context.py | 2 +- .../version/declarations/toml.py | 56 ++++++++++++------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/semantic_release/cli/cli_context.py b/src/semantic_release/cli/cli_context.py index a5c07a85e..502411f2b 100644 --- a/src/semantic_release/cli/cli_context.py +++ b/src/semantic_release/cli/cli_context.py @@ -67,7 +67,7 @@ def _init_raw_config(self) -> RawConfig: ) ) - # TODO: Evaluate Exeception catches + # TODO: Evaluate Exception catches try: if was_conf_file_user_provided and not conf_file_exists: raise FileNotFoundError( # noqa: TRY301 diff --git a/src/semantic_release/version/declarations/toml.py b/src/semantic_release/version/declarations/toml.py index 59e6996ac..bcf0fc180 100644 --- a/src/semantic_release/version/declarations/toml.py +++ b/src/semantic_release/version/declarations/toml.py @@ -1,7 +1,7 @@ from __future__ import annotations from pathlib import Path -from typing import Any, Dict, cast +from typing import TYPE_CHECKING import tomlkit from deprecated.sphinx import deprecated @@ -13,6 +13,9 @@ from semantic_release.version.declarations.i_version_replacer import IVersionReplacer from semantic_release.version.version import Version +if TYPE_CHECKING: + from tomlkit.toml_document import TOMLDocument + class TomlVersionDeclaration(IVersionReplacer): def __init__( @@ -47,8 +50,8 @@ def content(self) -> None: def parse(self) -> set[Version]: # pragma: no cover """Look for the version in the source content""" content = self._load() - maybe_version: str = content.get(self._search_text) # type: ignore[return-value] - if maybe_version is not None: + maybe_version = content.get(self._search_text) + if isinstance(maybe_version, str) and (maybe_version := maybe_version.strip()): logger.debug( "Found a key %r that looks like a version (%r)", self._search_text, @@ -65,23 +68,34 @@ def replace(self, new_version: Version) -> str: updated content. """ content = self._load() - if self._search_text in content: - logger.info( - "found %r in source file contents, replacing with %s", - self._search_text, - new_version, - ) - content[self._search_text] = ( - new_version.as_tag() - if self._stamp_format == VersionStampType.TAG_FORMAT - else str(new_version) - ) - - return tomlkit.dumps(cast(Dict[str, Any], content)) - - def _load(self) -> Dotty: - """Load the content of the source file into a Dotty for easier searching""" - return Dotty(tomlkit.loads(self.content)) + if self._search_text not in Dotty(content): + # TODO: v11 + # raise KeyError( + # f"key {self._search_text!r} not found in source file {self._path!r}" + # ) + return tomlkit.dumps(content) + + logger.info( + "found %r in source file contents, replacing with %s", + self._search_text, + new_version, + ) + + sub_content = content + parts = self._search_text.split(".") + for part in parts[:-1]: + sub_content = sub_content.get(part, {}) + + sub_content[parts[-1]] = ( + new_version.as_tag() + if self._stamp_format == VersionStampType.TAG_FORMAT + else str(new_version) + ) + + return tomlkit.dumps(content) + + def _load(self) -> TOMLDocument: + return tomlkit.loads(self.content) def update_file_w_version( self, new_version: Version, noop: bool = False @@ -93,7 +107,7 @@ def update_file_w_version( ) return None - if self._search_text not in self._load(): + if self._search_text not in Dotty(self._load()): noop_report( f"VERSION PATTERN NOT FOUND: no version to stamp in file {self._path!r}", ) From 1c5834c097b623bf789a722b82e75df7db34c06f Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sat, 4 Jul 2026 13:18:08 -0600 Subject: [PATCH 12/26] chore(tox): adjust ruff command in tox config --- pyproject.toml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8f1071d59..18f5237cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,7 @@ dependencies = [ "requests ~= 2.25", "jinja2 ~= 3.1", "python-gitlab >= 4.0.0, < 9.0.0", - "tomlkit >= 0.13.0, < 0.16.0", + "tomlkit ~= 0.13.0", "dotty-dict ~= 1.3", "importlib-resources ~= 6.0", "pydantic ~= 2.0", @@ -57,7 +57,7 @@ repository = "http://github.com/python-semantic-release/python-semantic-release. [project.optional-dependencies] build = [ "build ~= 1.2", - "tomlkit >= 0.13.0, < 0.16.0", + "tomlkit ~= 0.13.0", ] docs = [ "Sphinx ~= 7.4", @@ -173,9 +173,10 @@ commands = [testenv:ruff] deps = .[dev] commands = - ruff check . --statistics --output-format=text + ruff check . --statistics """ + [tool.mypy] python_version = "3.8" show_column_numbers = true @@ -213,6 +214,7 @@ ignore_missing_imports = true module = "dotty_dict" ignore_missing_imports = true + [tool.ruff] line-length = 88 target-version = "py38" From 01707ead53e093fe217a82c9ff9898c5e4daf9dc Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sat, 4 Jul 2026 13:19:22 -0600 Subject: [PATCH 13/26] build(deps): extend `click` dependency range to include `v8.2+` --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 18f5237cf..2faba0697 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ authors = [ { name = "codejedi365", email = "codejedi365@gmail.com" }, ] dependencies = [ - "click ~= 8.1.0", + "click >= 8.1.0, < 9.0.0", "click-option-group ~= 0.5", "gitpython ~= 3.0", "requests ~= 2.25", From 85408e1742f4df005fed70971096d80f30f145d0 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sat, 4 Jul 2026 13:20:24 -0600 Subject: [PATCH 14/26] test(config): refactor test fixtures to handle click library variance --- tests/conftest.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 4e78b59b5..90f21339d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,6 +13,7 @@ from unittest import mock import pytest +from click import __version__ as click_version from click.testing import CliRunner from filelock import FileLock from git import Commit, Repo @@ -193,9 +194,17 @@ def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item item.add_marker(comprehensive_test_skip_marker) +def get_cli_runner() -> CliRunner: + return ( + CliRunner() + if tuple(map(int, click_version.split("."))) >= (8, 2, 0) + else CliRunner(mix_stderr=False) # type: ignore[call-arg] + ) + + @pytest.fixture def cli_runner() -> CliRunner: - return CliRunner(mix_stderr=False) + return get_cli_runner() @pytest.fixture(scope="session") @@ -211,7 +220,7 @@ def _run_cli( # Prevent logs from being propagated to the root logger (pytest) logger.propagate = False - cli_runner = CliRunner(mix_stderr=False) + cli_runner = get_cli_runner() env_vars = {**clean_os_environment, **(env or {})} args = ["-vv", *(argv or [])] From ef97ac9f0f7eb3346f5a0bf2fe57b71de4894513 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sat, 4 Jul 2026 13:23:38 -0600 Subject: [PATCH 15/26] refactor(cli): refactor for future click library implementation In click 8.2.0, they deprecated the `MultiCommand` object in support of `Group`. Adjusting accordingly to prevent future breaking change as `Group` currently exists in `click@v8.1.0`. --- src/semantic_release/cli/commands/main.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/semantic_release/cli/commands/main.py b/src/semantic_release/cli/commands/main.py index c10d3f647..387893974 100644 --- a/src/semantic_release/cli/commands/main.py +++ b/src/semantic_release/cli/commands/main.py @@ -30,8 +30,8 @@ ] -class Cli(click.MultiCommand): - """Root MultiCommand for the semantic-release CLI""" +class Cli(click.Group): + """Root Group for the semantic-release CLI""" class SubCmds(Enum): """Subcommand import definitions""" @@ -42,12 +42,12 @@ class SubCmds(Enum): VERSION = f"{__package__}.version" PUBLISH = f"{__package__}.publish" - def list_commands(self, _ctx: click.Context) -> list[str]: + def list_commands(self, ctx: click.Context) -> list[str]: # noqa: ARG002 # Used for shell-completion return [subcmd.lower().replace("_", "-") for subcmd in Cli.SubCmds.__members__] - def get_command(self, _ctx: click.Context, name: str) -> click.Command | None: - subcmd_name = name.lower().replace("-", "_") + def get_command(self, ctx: click.Context, cmd_name: str) -> click.Command | None: # noqa: ARG002 + subcmd_name = cmd_name.lower().replace("-", "_") try: subcmd_def: Cli.SubCmds = Cli.SubCmds.__dict__[subcmd_name.upper()] module_path = subcmd_def.value From e5ff73102c0153f9cc857b93d3eacd8576a7dd99 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sat, 4 Jul 2026 13:25:30 -0600 Subject: [PATCH 16/26] test: refactor e2e tests to work across `click@v8.1.0` to `v8.2.0` --- tests/e2e/cmd_config/test_generate_config.py | 12 ++++++------ tests/e2e/test_main.py | 8 +++++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/e2e/cmd_config/test_generate_config.py b/tests/e2e/cmd_config/test_generate_config.py index a9db934ea..fe3174d43 100644 --- a/tests/e2e/cmd_config/test_generate_config.py +++ b/tests/e2e/cmd_config/test_generate_config.py @@ -51,11 +51,11 @@ def test_generate_config_toml( # Evaluate: Check that the command ran successfully and that the output matches the expected configuration assert_successful_exit_code(result, cli_cmd) - assert expected_config_as_str == result.output.strip() + assert expected_config_as_str == result.stdout.strip() # Setup: Write the generated configuration to a file config_file = "releaserc.toml" - example_project_dir.joinpath(config_file).write_text(result.output) + example_project_dir.joinpath(config_file).write_text(result.stdout) # Act: Validate that the generated config is a valid configuration for PSR cli_cmd = [ @@ -93,11 +93,11 @@ def test_generate_config_json( # Evaluate: Check that the command ran successfully and that the output matches the expected configuration assert_successful_exit_code(result, cli_cmd) - assert expected_config_as_str == result.output.strip() + assert expected_config_as_str == result.stdout.strip() # Setup: Write the generated configuration to a file config_file = "releaserc.json" - example_project_dir.joinpath(config_file).write_text(result.output) + example_project_dir.joinpath(config_file).write_text(result.stdout) # Act: Validate that the generated config is a valid configuration for PSR cli_cmd = [ @@ -144,7 +144,7 @@ def test_generate_config_pyproject_toml( # Evaluate: Check that the command ran successfully and that the output matches the expected configuration assert_successful_exit_code(result, cli_cmd) - assert expected_config_as_str == result.output.strip() + assert expected_config_as_str == result.stdout.strip() # Setup: Write the generated configuration to a file example_pyproject_toml.write_text( @@ -152,7 +152,7 @@ def test_generate_config_pyproject_toml( "\n\n", [ example_pyproject_toml.read_text(encoding="utf-8").strip(), - result.output, + result.stdout, ], ) ) diff --git a/tests/e2e/test_main.py b/tests/e2e/test_main.py index 4e1df87e0..86d60b57b 100644 --- a/tests/e2e/test_main.py +++ b/tests/e2e/test_main.py @@ -9,6 +9,7 @@ import git import pytest +from click import __version__ as click_version from click.testing import CliRunner from pytest_lazy_fixtures.lazy_fixture import lf as lazy_fixture @@ -65,7 +66,12 @@ def test_main_no_args_passes_w_help_text(): cli_cmd = [MAIN_PROG_NAME] result = CliRunner().invoke(main, prog_name=cli_cmd[0]) - assert_successful_exit_code(result, cli_cmd) + + if tuple(map(int, click_version.split("."))) >= (8, 2, 0): + assert_exit_code(2, result, cli_cmd) + else: + assert_successful_exit_code(result, cli_cmd) + assert "Usage: " in result.output From 725e16b3be0f4a537cfbfac6dc5d5219fc2010d6 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sat, 4 Jul 2026 23:06:22 -0600 Subject: [PATCH 17/26] ci(validate): adjust lint job to use Python 3.8 instead --- .github/workflows/validate.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 198fd2c3a..b0e966d16 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -451,10 +451,10 @@ jobs: ref: ${{ github.sha }} fetch-depth: 1 - - name: Setup | Install Python ${{ env.COMMON_PYTHON_VERSION }} + - name: Setup | Install Python ${{ env.LOWEST_PYTHON_VERSION }} uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: - python-version: ${{ env.COMMON_PYTHON_VERSION }} + python-version: ${{ env.LOWEST_PYTHON_VERSION }} cache: 'pip' - name: Setup | Install dependencies From ceb4e976c3c75c7b23d8788a3f56d201480e6664 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sat, 4 Jul 2026 23:19:44 -0600 Subject: [PATCH 18/26] style(mypy-config): remove specified 3.8 compiler from config - defaults to autodetect --- pyproject.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2faba0697..e20798ff5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,12 +84,12 @@ test = [ "requests-mock ~= 1.10", ] dev = [ - "pre-commit ~= 4.3", + "pre-commit >= 3.5.0, < 5.0.0", "tox ~= 4.11", "ruff == 0.6.1" ] mypy = [ - "mypy == 1.16.1", + "mypy >= 1.14.1, < 2.0.0", "types-Deprecated ~= 1.2", "types-requests ~= 2.32.0", "types-pyyaml ~= 6.0", @@ -178,7 +178,6 @@ commands = [tool.mypy] -python_version = "3.8" show_column_numbers = true show_error_context = true pretty = true From 0ef2d0c36a056386284ac02b4c82d44033a57b47 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Jul 2026 17:02:58 +0000 Subject: [PATCH 19/26] build(deps-dev): expand `pytest` dependency range to include `v9.0.0` Signed-off-by: dependabot[bot] Signed-off-by: codejedi365 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e20798ff5..d688ee0e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ test = [ "flatdict ~= 4.0", "freezegun ~= 1.5", "pyyaml ~= 6.0", - "pytest ~= 8.3", + "pytest >= 8.3, < 10.0", "pytest-clarity ~= 1.0", "pytest-cov >= 5.0.0, < 8.0.0", "pytest-env ~= 1.0", From 45f0f27545e4a0a0627f4677040a05d16f214f0e Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sun, 5 Jul 2026 00:00:04 -0600 Subject: [PATCH 20/26] test: adjust style to match expected pytest environment & type-checker --- tests/e2e/cmd_version/test_version_build.py | 40 +++++++++++---------- tests/util.py | 4 +-- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/tests/e2e/cmd_version/test_version_build.py b/tests/e2e/cmd_version/test_version_build.py index 51022da87..40ac74388 100644 --- a/tests/e2e/cmd_version/test_version_build.py +++ b/tests/e2e/cmd_version/test_version_build.py @@ -26,27 +26,29 @@ @pytest.mark.skipif(sys.platform == "win32", reason="Unix only") @pytest.mark.parametrize( "shell", - filter( - None, - [ - # because we will actually run the build command in this shell, we must ensure it exists - "bash" - if list( - filter( - lambda sh_exe: Path(sh_exe).exists(), - ("/bin/bash", "/usr/bin/bash", "/usr/local/bin/bash"), + list( + filter( + None, + [ + # because we will actually run the build command in this shell, we must ensure it exists + "bash" + if list( + filter( + lambda sh_exe: Path(sh_exe).exists(), + ("/bin/bash", "/usr/bin/bash", "/usr/local/bin/bash"), + ) ) - ) - else "", - "zsh" - if list( - filter( - lambda sh_exe: Path(sh_exe).exists(), - ("/bin/zsh", "/usr/bin/zsh", "/usr/local/bin/zsh"), + else "", + "zsh" + if list( + filter( + lambda sh_exe: Path(sh_exe).exists(), + ("/bin/zsh", "/usr/bin/zsh", "/usr/local/bin/zsh"), + ) ) - ) - else "", - ], + else "", + ], + ) ) or ["sh"], ) diff --git a/tests/util.py b/tests/util.py index d97e04845..8ddff0a83 100644 --- a/tests/util.py +++ b/tests/util.py @@ -51,7 +51,7 @@ GitCommandWrapperType: TypeAlias = Git -def get_func_qual_name(func: Callable) -> str: +def get_func_qual_name(func: Callable[[Any], Any]) -> str: return str.join(".", filter(None, [func.__module__, func.__qualname__])) @@ -79,7 +79,7 @@ def assert_successful_exit_code(result: ClickInvokeResult, cli_cmd: list[str]) - return assert_exit_code(SUCCESS_EXIT_CODE, result, cli_cmd) -def get_full_qualname(callable_obj: Callable) -> str: +def get_full_qualname(callable_obj: Callable[[Any], Any]) -> str: parts = filter( None, [ From 81527c6731033237828f2eecf5fc1b5854c63b63 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sun, 5 Jul 2026 11:26:19 -0600 Subject: [PATCH 21/26] style: adjust implementation & tests to suppress warnings & type errors --- src/semantic_release/helpers.py | 2 +- tests/conftest.py | 4 ++-- tests/e2e/test_main.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/semantic_release/helpers.py b/src/semantic_release/helpers.py index 8ec505a16..5df443955 100644 --- a/src/semantic_release/helpers.py +++ b/src/semantic_release/helpers.py @@ -94,7 +94,7 @@ def text_reducer(text: str, filter_pair: tuple[Pattern[str], str]) -> str: def validate_types_in_sequence( - sequence: Sequence, types: type | tuple[type, ...] + sequence: Sequence[Any], types: type | tuple[type, ...] ) -> bool: """Validate that all elements in a sequence are of a specific type""" return all(isinstance(item, types) for item in sequence) diff --git a/tests/conftest.py b/tests/conftest.py index 90f21339d..1cdea68a0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,13 +7,13 @@ import sys from datetime import datetime, timedelta, timezone from hashlib import md5 +from importlib.metadata import version as get_package_version from pathlib import Path from tempfile import NamedTemporaryFile from typing import TYPE_CHECKING, cast from unittest import mock import pytest -from click import __version__ as click_version from click.testing import CliRunner from filelock import FileLock from git import Commit, Repo @@ -197,7 +197,7 @@ def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item def get_cli_runner() -> CliRunner: return ( CliRunner() - if tuple(map(int, click_version.split("."))) >= (8, 2, 0) + if tuple(map(int, get_package_version("click").split("."))) >= (8, 2, 0) else CliRunner(mix_stderr=False) # type: ignore[call-arg] ) diff --git a/tests/e2e/test_main.py b/tests/e2e/test_main.py index 86d60b57b..cb9d2e05d 100644 --- a/tests/e2e/test_main.py +++ b/tests/e2e/test_main.py @@ -2,6 +2,7 @@ import json import subprocess +from importlib.metadata import version as get_package_version from pathlib import Path from shutil import rmtree from textwrap import dedent @@ -9,7 +10,6 @@ import git import pytest -from click import __version__ as click_version from click.testing import CliRunner from pytest_lazy_fixtures.lazy_fixture import lf as lazy_fixture @@ -67,7 +67,7 @@ def test_main_no_args_passes_w_help_text(): cli_cmd = [MAIN_PROG_NAME] result = CliRunner().invoke(main, prog_name=cli_cmd[0]) - if tuple(map(int, click_version.split("."))) >= (8, 2, 0): + if tuple(map(int, get_package_version("click").split("."))) >= (8, 2, 0): assert_exit_code(2, result, cli_cmd) else: assert_successful_exit_code(result, cli_cmd) From 5e8f94c3d81ccf17598af8a77659dd31df2ea403 Mon Sep 17 00:00:00 2001 From: Frank Goldfish Date: Sun, 5 Jul 2026 11:41:43 -0700 Subject: [PATCH 22/26] fix(cmd-version): fix non-styled error msg when strict & no new version (#1437) When `semantic-release version` is run with `--strict` and no new commits have been found, the error message containing Rich markup ([bold orange1]...) was passed to `click.echo()`, causing the markup tags to be printed literally rather than rendered as formatted text. Resolves: #1423 * test(cmd-version): modify strict test to not include rich color modifier --------- Co-authored-by: frankgoldfish Co-authored-by: codejedi365 Signed-off-by: codejedi365 --- src/semantic_release/cli/commands/version.py | 13 ++++--------- tests/e2e/cmd_version/test_version_strict.py | 4 +++- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/semantic_release/cli/commands/version.py b/src/semantic_release/cli/commands/version.py index 7a6fa26ef..d83be9894 100644 --- a/src/semantic_release/cli/commands/version.py +++ b/src/semantic_release/cli/commands/version.py @@ -591,19 +591,14 @@ def version( # noqa: C901 # If the new version has already been released, we fail and abort if strict; # otherwise we exit with 0. if new_version in previously_released_versions: - err_msg = str.join( - " ", - [ - "[bold orange1]No release will be made,", - f"{new_version!s} has already been released!", - ], - ) + err_msg = f"No release will be made, {new_version!s} has already been released!" + orange1_code = 214 # https://rich.readthedocs.io/en/stable/appendix/colors.html if opts.strict: - click.echo(err_msg, err=True) + click.secho(err_msg, err=True, fg=orange1_code, bold=True) ctx.exit(2) - rprint(err_msg) + click.secho(err_msg, err=True, fg=orange1_code, bold=True) return if print_only or print_only_tag: diff --git a/tests/e2e/cmd_version/test_version_strict.py b/tests/e2e/cmd_version/test_version_strict.py index e90970bd3..dcdfb099b 100644 --- a/tests/e2e/cmd_version/test_version_strict.py +++ b/tests/e2e/cmd_version/test_version_strict.py @@ -44,7 +44,9 @@ def test_version_already_released_when_strict( latest_release_version = get_versions_from_repo_build_def( repo_result["definition"] )[-1] - expected_error_msg = f"[bold orange1]No release will be made, {latest_release_version} has already been released!" + expected_error_msg = ( + f"No release will be made, {latest_release_version} has already been released!" + ) # Setup: take measurement before running the version command repo_status_before = repo.git.status(short=True) From be11d3ff790dd85e1b84ef9d8030b3200c74e7c5 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sun, 5 Jul 2026 12:07:17 -0600 Subject: [PATCH 23/26] style: adjust formatting for clearer test implementations --- .../bump_version/git_flow/test_repo_1_channel.py | 5 ++--- .../bump_version/git_flow/test_repo_2_channels.py | 5 ++--- .../bump_version/git_flow/test_repo_3_channels.py | 5 ++--- .../bump_version/git_flow/test_repo_4_channels.py | 5 ++--- .../bump_version/github_flow/test_repo_1_channel.py | 5 ++--- .../test_repo_1_channel_branch_update_merge.py | 5 ++--- .../bump_version/github_flow/test_repo_2_channels.py | 5 ++--- .../github_flow_monorepo/test_monorepo_1_channel.py | 5 ++--- .../github_flow_monorepo/test_monorepo_2_channels.py | 5 ++--- .../bump_version/trunk_based_dev/test_repo_trunk.py | 5 ++--- .../test_repo_trunk_dual_version_support.py | 5 ++--- ...st_repo_trunk_dual_version_support_w_prereleases.py | 5 ++--- .../trunk_based_dev/test_repo_trunk_w_prereleases.py | 5 ++--- .../trunk_based_dev_monorepo/test_monorepo_trunk.py | 5 ++--- tests/e2e/cmd_version/test_version_build.py | 10 ++++------ 15 files changed, 32 insertions(+), 48 deletions(-) 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 79d94b37b..ee17c5214 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 @@ -163,8 +163,7 @@ def test_gitflow_repo_rebuild_1_channel( 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_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 2b8c046e1..27ff5f339 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 @@ -163,8 +163,7 @@ def test_gitflow_repo_rebuild_2_channels( 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_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 a26988646..5b32befd1 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 @@ -164,8 +164,7 @@ def test_gitflow_repo_rebuild_3_channels( 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_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 0adde1fa3..2a135b116 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 @@ -163,8 +163,7 @@ def test_gitflow_repo_rebuild_4_channels( 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_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 edeb485ce..fedd861dd 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 @@ -163,8 +163,7 @@ def test_githubflow_repo_rebuild_1_channel( 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_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 1d54aa459..a3018d346 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 @@ -176,8 +176,7 @@ def test_github_flow_repo_w_default_release_n_branch_update_merge( 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_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 ab6906eea..e86858b55 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 @@ -163,8 +163,7 @@ def test_githubflow_repo_rebuild_2_channels( 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_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 1d82138f2..c0dafbf7c 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 @@ -249,8 +249,7 @@ def test_githubflow_monorepo_rebuild_1_channel( assert curr_release_str in [tag.name for tag in mirror_git_repo.tags] # Make sure publishing actions occurred - assert ( - mocked_git_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 1352995b9..7c3e36390 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 @@ -248,8 +248,7 @@ def test_githubflow_monorepo_rebuild_2_channels( assert curr_release_str in [tag.name for tag in mirror_git_repo.tags] # Make sure publishing actions occurred - assert ( - mocked_git_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 c57c6d58c..b0f05c41b 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 @@ -165,8 +165,7 @@ def test_trunk_repo_rebuild_only_official_releases( 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_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 6ea7e1f54..223e7a1f6 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 @@ -171,8 +171,7 @@ def test_trunk_repo_rebuild_dual_version_spt_official_releases_only( 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_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 89819abe9..2ef42b490 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 @@ -172,8 +172,7 @@ def test_trunk_repo_rebuild_dual_version_spt_w_official_n_prereleases( 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_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 78eca0bd6..5d3f1684f 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 @@ -163,8 +163,7 @@ def test_trunk_repo_rebuild_w_prereleases( 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_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred 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 c68a35f5d..60aae38cb 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 @@ -249,8 +249,7 @@ def test_trunk_monorepo_rebuild_1_channel( assert curr_release_str in [tag.name for tag in mirror_git_repo.tags] # Make sure publishing actions occurred - assert ( - mocked_git_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 # 1 for commit, 1 for tag assert post_mocker.call_count == 1 # vcs release creation occurred diff --git a/tests/e2e/cmd_version/test_version_build.py b/tests/e2e/cmd_version/test_version_build.py index 40ac74388..068377543 100644 --- a/tests/e2e/cmd_version/test_version_build.py +++ b/tests/e2e/cmd_version/test_version_build.py @@ -128,9 +128,8 @@ def test_version_runs_build_command( ) assert built_wheel_file.exists() - assert ( - mocked_git_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 assert post_mocker.call_count == 1 @@ -230,9 +229,8 @@ def test_version_runs_build_command_windows( dist_file_exists = built_wheel_file.exists() assert dist_file_exists, f"\n Expected wheel file to be created at {built_wheel_file}, but it does not exist." - assert ( - mocked_git_fetch.call_count == 1 - ) # fetch called to check for remote changes + # fetch called to check for remote changes + assert mocked_git_fetch.call_count == 1 assert mocked_git_push.call_count == 2 assert post_mocker.call_count == 1 From 5fa2df5f802a0107872f9f0487f34292ad6e0bc4 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Sun, 5 Jul 2026 15:24:49 -0600 Subject: [PATCH 24/26] 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 25/26] 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 26/26] 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