gpt-5.2: fix tests and imports after git queries split
Some checks failed
Mark stable commit / test-unit (push) Has been cancelled
Mark stable commit / test-integration (push) Has been cancelled
Mark stable commit / test-env-virtual (push) Has been cancelled
Mark stable commit / test-env-nix (push) Has been cancelled
Mark stable commit / test-e2e (push) Has been cancelled
Mark stable commit / test-virgin-user (push) Has been cancelled
Mark stable commit / test-virgin-root (push) Has been cancelled
Mark stable commit / lint-shell (push) Has been cancelled
Mark stable commit / lint-python (push) Has been cancelled
Mark stable commit / mark-stable (push) Has been cancelled

https://chatgpt.com/share/694135eb-10a8-800f-8b12-968612f605c7

Gemini
https://ai.studio/apps/drive/1QO9MaEklm2zZMDZ6XPP0LStuAooXs1NO
This commit is contained in:
Kevin Veen-Birkenbach
2025-12-16 11:35:10 +01:00
parent e117115b7f
commit 0119af330f
12 changed files with 206 additions and 137 deletions

View File

@@ -0,0 +1,6 @@
from __future__ import annotations
# expose subpackages for patch() / resolve_name() friendliness
from . import release as release # noqa: F401
__all__ = ["release"]

View File

@@ -7,7 +7,7 @@ Version discovery and bumping helpers for the release workflow.
from __future__ import annotations
from pkgmgr.core.git import get_tags
from pkgmgr.core.git.queries import get_tags
from pkgmgr.core.version.semver import (
SemVer,
find_latest_version,

View File

@@ -1,4 +1,3 @@
# src/pkgmgr/actions/release/workflow.py
from __future__ import annotations
import os
@@ -6,7 +5,8 @@ import sys
from typing import Optional
from pkgmgr.actions.branch import close_branch
from pkgmgr.core.git import get_current_branch, GitError
from pkgmgr.core.git import GitError
from pkgmgr.core.git.queries import get_current_branch
from pkgmgr.core.repository.paths import resolve_repo_paths
from .files import (

View File

@@ -7,7 +7,7 @@ from typing import Any, Dict, List, Optional, Tuple
from pkgmgr.cli.context import CLIContext
from pkgmgr.core.repository.dir import get_repo_dir
from pkgmgr.core.repository.identifier import get_repo_identifier
from pkgmgr.core.git import get_tags
from pkgmgr.core.git.queries import get_tags
from pkgmgr.core.version.semver import extract_semver_from_tags
from pkgmgr.actions.changelog import generate_changelog

View File

@@ -7,7 +7,7 @@ from typing import Any, Dict, List, Optional, Tuple
from pkgmgr.cli.context import CLIContext
from pkgmgr.core.repository.dir import get_repo_dir
from pkgmgr.core.repository.identifier import get_repo_identifier
from pkgmgr.core.git import get_tags
from pkgmgr.core.git.queries import get_tags
from pkgmgr.core.version.semver import SemVer, find_latest_version
from pkgmgr.core.version.installed import (
get_installed_python_version,

View File

@@ -7,7 +7,7 @@ from pkgmgr.core.git.commands import GitDeleteRemoteBranchError
class TestCloseBranch(unittest.TestCase):
@patch("pkgmgr.actions.branch.close_branch.input", return_value="y")
@patch("builtins.input", return_value="y")
@patch("pkgmgr.actions.branch.close_branch.get_current_branch", return_value="feature-x")
@patch("pkgmgr.actions.branch.close_branch.resolve_base_branch", return_value="main")
@patch("pkgmgr.actions.branch.close_branch.fetch")
@@ -26,10 +26,10 @@ class TestCloseBranch(unittest.TestCase):
pull,
checkout,
fetch,
resolve,
current,
input_mock,
):
_resolve,
_current,
_input_mock,
) -> None:
close_branch(None, cwd=".")
fetch.assert_called_once_with("origin", cwd=".")
checkout.assert_called_once_with("main", cwd=".")
@@ -41,31 +41,61 @@ class TestCloseBranch(unittest.TestCase):
@patch("pkgmgr.actions.branch.close_branch.get_current_branch", return_value="main")
@patch("pkgmgr.actions.branch.close_branch.resolve_base_branch", return_value="main")
def test_refuses_to_close_base_branch(self, resolve, current):
def test_refuses_to_close_base_branch(self, _resolve, _current) -> None:
with self.assertRaises(RuntimeError):
close_branch(None)
@patch("pkgmgr.actions.branch.close_branch.input", return_value="n")
@patch("builtins.input", return_value="n")
@patch("pkgmgr.actions.branch.close_branch.get_current_branch", return_value="feature-x")
@patch("pkgmgr.actions.branch.close_branch.resolve_base_branch", return_value="main")
@patch("pkgmgr.actions.branch.close_branch.fetch")
def test_close_branch_aborts_on_no(self, fetch, resolve, current, input_mock):
def test_close_branch_aborts_on_no(self, fetch, _resolve, _current, _input_mock) -> None:
close_branch(None, cwd=".")
fetch.assert_not_called()
@patch("builtins.input")
@patch("pkgmgr.actions.branch.close_branch.get_current_branch", return_value="feature-x")
@patch("pkgmgr.actions.branch.close_branch.resolve_base_branch", return_value="main")
@patch("pkgmgr.actions.branch.close_branch.fetch")
def test_close_branch_force_skips_prompt(self, fetch, resolve, current):
@patch("pkgmgr.actions.branch.close_branch.checkout")
@patch("pkgmgr.actions.branch.close_branch.pull")
@patch("pkgmgr.actions.branch.close_branch.merge_no_ff")
@patch("pkgmgr.actions.branch.close_branch.push")
@patch("pkgmgr.actions.branch.close_branch.delete_local_branch")
@patch("pkgmgr.actions.branch.close_branch.delete_remote_branch")
def test_close_branch_force_skips_prompt(
self,
delete_remote_branch,
delete_local_branch,
push,
merge_no_ff,
pull,
checkout,
fetch,
_resolve,
_current,
input_mock,
) -> None:
close_branch(None, cwd=".", force=True)
fetch.assert_called_once()
# no interactive prompt when forced
input_mock.assert_not_called()
# workflow still runs (but is mocked)
fetch.assert_called_once_with("origin", cwd=".")
checkout.assert_called_once_with("main", cwd=".")
pull.assert_called_once_with("origin", "main", cwd=".")
merge_no_ff.assert_called_once_with("feature-x", cwd=".")
push.assert_called_once_with("origin", "main", cwd=".")
delete_local_branch.assert_called_once_with("feature-x", cwd=".", force=False)
delete_remote_branch.assert_called_once_with("origin", "feature-x", cwd=".")
@patch("pkgmgr.actions.branch.close_branch.get_current_branch", side_effect=GitError("fail"))
def test_close_branch_errors_if_cannot_detect_branch(self, current):
def test_close_branch_errors_if_cannot_detect_branch(self, _current) -> None:
with self.assertRaises(RuntimeError):
close_branch(None)
@patch("pkgmgr.actions.branch.close_branch.input", return_value="y")
@patch("builtins.input", return_value="y")
@patch("pkgmgr.actions.branch.close_branch.get_current_branch", return_value="feature-x")
@patch("pkgmgr.actions.branch.close_branch.resolve_base_branch", return_value="main")
@patch("pkgmgr.actions.branch.close_branch.fetch")
@@ -80,17 +110,17 @@ class TestCloseBranch(unittest.TestCase):
)
def test_close_branch_remote_delete_failure_is_wrapped(
self,
delete_remote_branch,
delete_local_branch,
push,
merge_no_ff,
pull,
checkout,
fetch,
resolve,
current,
input_mock,
):
_delete_remote_branch,
_delete_local_branch,
_push,
_merge_no_ff,
_pull,
_checkout,
_fetch,
_resolve,
_current,
_input_mock,
) -> None:
with self.assertRaises(RuntimeError) as ctx:
close_branch(None, cwd=".")
self.assertIn("remote deletion failed", str(ctx.exception))

View File

@@ -7,43 +7,55 @@ from pkgmgr.core.git.commands import GitDeleteRemoteBranchError
class TestDropBranch(unittest.TestCase):
@patch("pkgmgr.actions.branch.drop_branch.input", return_value="y")
@patch("builtins.input", return_value="y")
@patch("pkgmgr.actions.branch.drop_branch.get_current_branch", return_value="feature-x")
@patch("pkgmgr.actions.branch.drop_branch.resolve_base_branch", return_value="main")
@patch("pkgmgr.actions.branch.drop_branch.delete_local_branch")
@patch("pkgmgr.actions.branch.drop_branch.delete_remote_branch")
def test_drop_branch_happy_path(self, delete_remote, delete_local, resolve, current, input_mock):
def test_drop_branch_happy_path(self, delete_remote, delete_local, _resolve, _current, _input_mock) -> None:
drop_branch(None, cwd=".")
delete_local.assert_called_once_with("feature-x", cwd=".", force=False)
delete_remote.assert_called_once_with("origin", "feature-x", cwd=".")
@patch("pkgmgr.actions.branch.drop_branch.get_current_branch", return_value="main")
@patch("pkgmgr.actions.branch.drop_branch.resolve_base_branch", return_value="main")
def test_refuses_to_drop_base_branch(self, resolve, current):
def test_refuses_to_drop_base_branch(self, _resolve, _current) -> None:
with self.assertRaises(RuntimeError):
drop_branch(None)
@patch("pkgmgr.actions.branch.drop_branch.input", return_value="n")
@patch("builtins.input", return_value="n")
@patch("pkgmgr.actions.branch.drop_branch.get_current_branch", return_value="feature-x")
@patch("pkgmgr.actions.branch.drop_branch.resolve_base_branch", return_value="main")
@patch("pkgmgr.actions.branch.drop_branch.delete_local_branch")
def test_drop_branch_aborts_on_no(self, delete_local, resolve, current, input_mock):
def test_drop_branch_aborts_on_no(self, delete_local, _resolve, _current, _input_mock) -> None:
drop_branch(None, cwd=".")
delete_local.assert_not_called()
@patch("builtins.input")
@patch("pkgmgr.actions.branch.drop_branch.get_current_branch", return_value="feature-x")
@patch("pkgmgr.actions.branch.drop_branch.resolve_base_branch", return_value="main")
@patch("pkgmgr.actions.branch.drop_branch.delete_local_branch")
def test_drop_branch_force_skips_prompt(self, delete_local, resolve, current):
@patch("pkgmgr.actions.branch.drop_branch.delete_remote_branch")
def test_drop_branch_force_skips_prompt(
self,
delete_remote,
delete_local,
_resolve,
_current,
input_mock,
) -> None:
drop_branch(None, cwd=".", force=True)
delete_local.assert_called_once()
input_mock.assert_not_called()
delete_local.assert_called_once_with("feature-x", cwd=".", force=False)
delete_remote.assert_called_once_with("origin", "feature-x", cwd=".")
@patch("pkgmgr.actions.branch.drop_branch.get_current_branch", side_effect=GitError("fail"))
def test_drop_branch_errors_if_no_branch_detected(self, current):
def test_drop_branch_errors_if_no_branch_detected(self, _current) -> None:
with self.assertRaises(RuntimeError):
drop_branch(None)
@patch("pkgmgr.actions.branch.drop_branch.input", return_value="y")
@patch("builtins.input", return_value="y")
@patch("pkgmgr.actions.branch.drop_branch.get_current_branch", return_value="feature-x")
@patch("pkgmgr.actions.branch.drop_branch.resolve_base_branch", return_value="main")
@patch("pkgmgr.actions.branch.drop_branch.delete_local_branch")
@@ -51,7 +63,14 @@ class TestDropBranch(unittest.TestCase):
"pkgmgr.actions.branch.drop_branch.delete_remote_branch",
side_effect=GitDeleteRemoteBranchError("boom", cwd="."),
)
def test_drop_branch_remote_delete_failure_is_wrapped(self, delete_remote, delete_local, resolve, current, input_mock):
def test_drop_branch_remote_delete_failure_is_wrapped(
self,
_delete_remote,
_delete_local,
_resolve,
_current,
_input_mock,
) -> None:
with self.assertRaises(RuntimeError) as ctx:
drop_branch(None, cwd=".")
self.assertIn("remote deletion failed", str(ctx.exception))

View File

@@ -11,8 +11,17 @@ class TestOpenBranch(unittest.TestCase):
@patch("pkgmgr.actions.branch.open_branch.pull")
@patch("pkgmgr.actions.branch.open_branch.create_branch")
@patch("pkgmgr.actions.branch.open_branch.push_upstream")
def test_open_branch_executes_git_commands(self, push_upstream, create_branch, pull, checkout, fetch, resolve):
def test_open_branch_executes_git_commands(
self,
push_upstream,
create_branch,
pull,
checkout,
fetch,
_resolve,
) -> None:
open_branch("feature-x", base_branch="main", cwd=".")
fetch.assert_called_once_with("origin", cwd=".")
checkout.assert_called_once_with("main", cwd=".")
pull.assert_called_once_with("origin", "main", cwd=".")
@@ -26,11 +35,25 @@ class TestOpenBranch(unittest.TestCase):
@patch("pkgmgr.actions.branch.open_branch.pull")
@patch("pkgmgr.actions.branch.open_branch.create_branch")
@patch("pkgmgr.actions.branch.open_branch.push_upstream")
def test_open_branch_prompts_for_name(self, fetch, resolve, input_mock):
def test_open_branch_prompts_for_name(
self,
push_upstream,
create_branch,
pull,
checkout,
fetch,
_resolve,
_input_mock,
) -> None:
open_branch(None)
fetch.assert_called_once()
def test_open_branch_rejects_empty_name(self):
fetch.assert_called_once_with("origin", cwd=".")
checkout.assert_called_once_with("main", cwd=".")
pull.assert_called_once_with("origin", "main", cwd=".")
create_branch.assert_called_once_with("auto-branch", "main", cwd=".")
push_upstream.assert_called_once_with("origin", "auto-branch", cwd=".")
def test_open_branch_rejects_empty_name(self) -> None:
with patch("builtins.input", return_value=""):
with self.assertRaises(RuntimeError):
open_branch(None)

View File

@@ -21,46 +21,34 @@ class TestMirrorGitRemote(unittest.TestCase):
)
def test_build_default_ssh_url(self) -> None:
repo = {
"provider": "github.com",
"account": "alice",
"repository": "repo",
}
self.assertEqual(
build_default_ssh_url(repo),
"git@github.com:alice/repo.git",
)
def test_determine_primary_prefers_origin(self) -> None:
repo = {"provider": "github.com", "account": "alice", "repository": "repo"}
ctx = self._ctx(config={"origin": "git@github.com:alice/repo.git"})
self.assertEqual(
determine_primary_remote_url(repo, ctx),
"git@github.com:alice/repo.git",
)
self.assertEqual(build_default_ssh_url(repo), "git@github.com:alice/repo.git")
def test_determine_primary_uses_file_order(self) -> None:
def test_determine_primary_prefers_origin_in_resolved(self) -> None:
# resolved_mirrors = config + file (file wins), so put origin in file.
repo = {"provider": "github.com", "account": "alice", "repository": "repo"}
ctx = self._ctx(
file={
"first": "git@a/first.git",
"second": "git@a/second.git",
}
)
self.assertEqual(
determine_primary_remote_url(repo, ctx),
"git@a/first.git",
)
ctx = self._ctx(file={"origin": "git@github.com:alice/repo.git"})
self.assertEqual(determine_primary_remote_url(repo, ctx), "git@github.com:alice/repo.git")
def test_determine_primary_falls_back_to_file_order(self) -> None:
repo = {"provider": "github.com", "account": "alice", "repository": "repo"}
ctx = self._ctx(file={"first": "git@a/first.git", "second": "git@a/second.git"})
self.assertEqual(determine_primary_remote_url(repo, ctx), "git@a/first.git")
def test_determine_primary_falls_back_to_config_order(self) -> None:
repo = {"provider": "github.com", "account": "alice", "repository": "repo"}
ctx = self._ctx(config={"cfg1": "git@c/one.git", "cfg2": "git@c/two.git"})
self.assertEqual(determine_primary_remote_url(repo, ctx), "git@c/one.git")
def test_determine_primary_fallback_default(self) -> None:
repo = {"provider": "github.com", "account": "alice", "repository": "repo"}
ctx = self._ctx()
self.assertEqual(
determine_primary_remote_url(repo, ctx),
"git@github.com:alice/repo.git",
)
self.assertEqual(determine_primary_remote_url(repo, ctx), "git@github.com:alice/repo.git")
@patch("pkgmgr.actions.mirror.git_remote._safe_git_output")
def test_has_origin_remote(self, m_out) -> None:
m_out.return_value = "origin\nupstream\n"
@patch("pkgmgr.actions.mirror.git_remote.list_remotes", return_value=["origin", "backup"])
def test_has_origin_remote_true(self, _m_list) -> None:
self.assertTrue(has_origin_remote("/tmp/repo"))
@patch("pkgmgr.actions.mirror.git_remote.list_remotes", return_value=["backup"])
def test_has_origin_remote_false(self, _m_list) -> None:
self.assertFalse(has_origin_remote("/tmp/repo"))

View File

@@ -10,6 +10,8 @@ from pkgmgr.actions.mirror.types import RepoMirrorContext
class TestGitRemotePrimaryPush(unittest.TestCase):
def test_origin_created_and_extra_push_added(self) -> None:
repo = {"provider": "github.com", "account": "alice", "repository": "repo"}
# Use file_mirrors so ctx.resolved_mirrors contains both, no setattr (frozen dataclass!)
ctx = RepoMirrorContext(
identifier="repo",
repo_dir="/tmp/repo",
@@ -20,31 +22,44 @@ class TestGitRemotePrimaryPush(unittest.TestCase):
},
)
executed: list[str] = []
with patch("os.path.isdir", return_value=True):
with patch("pkgmgr.actions.mirror.git_remote.has_origin_remote", return_value=False), patch(
"pkgmgr.actions.mirror.git_remote.add_remote"
) as m_add_remote, patch(
"pkgmgr.actions.mirror.git_remote.set_remote_url"
) as m_set_remote_url, patch(
"pkgmgr.actions.mirror.git_remote.get_remote_push_urls", return_value=set()
), patch(
"pkgmgr.actions.mirror.git_remote.add_remote_push_url"
) as m_add_push:
ensure_origin_remote(repo, ctx, preview=False)
def fake_run(cmd: str, cwd: str, preview: bool) -> None:
executed.append(cmd)
def fake_git(args, cwd):
if args == ["remote"]:
return ""
if args == ["remote", "get-url", "--push", "--all", "origin"]:
return "git@github.com:alice/repo.git\n"
return ""
with patch("os.path.isdir", return_value=True), patch(
"pkgmgr.actions.mirror.git_remote.run_command", side_effect=fake_run
), patch(
"pkgmgr.actions.mirror.git_remote._safe_git_output", side_effect=fake_git
):
ensure_origin_remote(repo, ctx, preview=False)
self.assertEqual(
executed,
[
"git remote add origin git@github.com:alice/repo.git",
"git remote set-url origin git@github.com:alice/repo.git",
"git remote set-url --push origin git@github.com:alice/repo.git",
"git remote set-url --add --push origin git@github.com:alice/repo-backup.git",
],
# determine_primary_remote_url falls back to file order (primary first)
m_add_remote.assert_called_once_with(
"origin",
"git@github.com:alice/repo.git",
cwd="/tmp/repo",
preview=False,
)
m_set_remote_url.assert_any_call(
"origin",
"git@github.com:alice/repo.git",
cwd="/tmp/repo",
push=False,
preview=False,
)
m_set_remote_url.assert_any_call(
"origin",
"git@github.com:alice/repo.git",
cwd="/tmp/repo",
push=True,
preview=False,
)
m_add_push.assert_called_once_with(
"origin",
"git@github.com:alice/repo-backup.git",
cwd="/tmp/repo",
preview=False,
)

View File

@@ -8,16 +8,10 @@ from pkgmgr.actions.mirror.types import RepoMirrorContext
class TestMirrorSetupCmd(unittest.TestCase):
def _ctx(
self,
*,
repo_dir: str = "/tmp/repo",
resolved: dict[str, str] | None = None,
) -> RepoMirrorContext:
# RepoMirrorContext derives resolved via property (config + file)
# We feed mirrors via file_mirrors to keep insertion order realistic.
def _ctx(self, *, repo_dir: str = "/tmp/repo", resolved: dict[str, str] | None = None) -> RepoMirrorContext:
# resolved_mirrors is a @property combining config+file. Put it into file_mirrors.
return RepoMirrorContext(
identifier="repo-id",
identifier="repo",
repo_dir=repo_dir,
config_mirrors={},
file_mirrors=resolved or {},
@@ -26,7 +20,8 @@ class TestMirrorSetupCmd(unittest.TestCase):
@patch("pkgmgr.actions.mirror.setup_cmd.build_context")
@patch("pkgmgr.actions.mirror.setup_cmd.ensure_origin_remote")
def test_setup_mirrors_local_calls_ensure_origin_remote(self, m_ensure, m_ctx) -> None:
m_ctx.return_value = self._ctx(repo_dir="/tmp/repo", resolved={"primary": "git@x/y.git"})
ctx = self._ctx(repo_dir="/tmp/repo", resolved={"primary": "git@x/y.git"})
m_ctx.return_value = ctx
repos = [{"provider": "github.com", "account": "alice", "repository": "repo"}]
setup_mirrors(
@@ -39,24 +34,21 @@ class TestMirrorSetupCmd(unittest.TestCase):
ensure_remote=False,
)
self.assertEqual(m_ensure.call_count, 1)
# ensure_origin_remote(repo, ctx, preview) is called positionally in your code
m_ensure.assert_called_once()
args, kwargs = m_ensure.call_args
# ensure_origin_remote(repo, ctx, preview) may be positional or kw.
# Accept both to avoid coupling tests to call style.
if "preview" in kwargs:
self.assertTrue(kwargs["preview"])
else:
# args: (repo, ctx, preview)
self.assertTrue(args[2])
self.assertEqual(args[0], repos[0])
self.assertIs(args[1], ctx)
self.assertEqual(kwargs.get("preview", args[2] if len(args) >= 3 else None), True)
@patch("pkgmgr.actions.mirror.setup_cmd.build_context")
@patch("pkgmgr.actions.mirror.setup_cmd.probe_mirror")
@patch("pkgmgr.actions.mirror.setup_cmd.determine_primary_remote_url")
def test_setup_mirrors_remote_no_mirrors_probes_primary(self, m_primary, m_probe, m_ctx) -> None:
@patch("pkgmgr.actions.mirror.setup_cmd.probe_remote_reachable")
def test_setup_mirrors_remote_no_mirrors_probes_primary(self, m_probe, m_primary, m_ctx) -> None:
m_ctx.return_value = self._ctx(repo_dir="/tmp/repo", resolved={})
m_primary.return_value = "git@github.com:alice/repo.git"
m_probe.return_value = (True, "")
m_probe.return_value = True
repos = [{"provider": "github.com", "account": "alice", "repository": "repo"}]
setup_mirrors(
@@ -70,10 +62,10 @@ class TestMirrorSetupCmd(unittest.TestCase):
)
m_primary.assert_called()
m_probe.assert_called_with("git@github.com:alice/repo.git", "/tmp/repo")
m_probe.assert_called_once_with("git@github.com:alice/repo.git", cwd="/tmp/repo")
@patch("pkgmgr.actions.mirror.setup_cmd.build_context")
@patch("pkgmgr.actions.mirror.setup_cmd.probe_mirror")
@patch("pkgmgr.actions.mirror.setup_cmd.probe_remote_reachable")
def test_setup_mirrors_remote_with_mirrors_probes_each(self, m_probe, m_ctx) -> None:
m_ctx.return_value = self._ctx(
repo_dir="/tmp/repo",
@@ -82,7 +74,7 @@ class TestMirrorSetupCmd(unittest.TestCase):
"backup": "ssh://git@git.veen.world:2201/alice/repo.git",
},
)
m_probe.return_value = (True, "")
m_probe.return_value = True
repos = [{"provider": "github.com", "account": "alice", "repository": "repo"}]
setup_mirrors(
@@ -96,6 +88,8 @@ class TestMirrorSetupCmd(unittest.TestCase):
)
self.assertEqual(m_probe.call_count, 2)
m_probe.assert_any_call("git@github.com:alice/repo.git", cwd="/tmp/repo")
m_probe.assert_any_call("ssh://git@git.veen.world:2201/alice/repo.git", cwd="/tmp/repo")
if __name__ == "__main__":

View File

@@ -1,4 +1,3 @@
import unittest
from unittest.mock import patch
@@ -6,15 +5,10 @@ from pkgmgr.actions.publish.git_tags import head_semver_tags
class TestHeadSemverTags(unittest.TestCase):
@patch("pkgmgr.actions.publish.git_tags.run_git")
def test_no_tags(self, mock_run_git):
mock_run_git.return_value = ""
@patch("pkgmgr.actions.publish.git_tags.get_tags_at_ref", return_value=[])
def test_no_tags(self, _mock_get_tags_at_ref) -> None:
self.assertEqual(head_semver_tags(), [])
@patch("pkgmgr.actions.publish.git_tags.run_git")
def test_filters_and_sorts_semver(self, mock_run_git):
mock_run_git.return_value = "v1.0.0\nv2.0.0\nfoo\n"
self.assertEqual(
head_semver_tags(),
["v1.0.0", "v2.0.0"],
)
@patch("pkgmgr.actions.publish.git_tags.get_tags_at_ref", return_value=["v2.0.0", "nope", "v1.0.0", "v1.2.0"])
def test_filters_and_sorts_semver(self, _mock_get_tags_at_ref) -> None:
self.assertEqual(head_semver_tags(), ["v1.0.0", "v1.2.0", "v2.0.0"])