from __future__ import annotations from pathlib import Path import shlex import subprocess import sys import unittest from unittest.mock import patch META_ROOT = Path(__file__).resolve().parents[1] RELEASE_TOOLS_ROOT = META_ROOT / "tools" / "release" if str(RELEASE_TOOLS_ROOT) not in sys.path: sys.path.insert(0, str(RELEASE_TOOLS_ROOT)) from govoplan_release import git_state # noqa: E402 class ReleaseGitStateTests(unittest.TestCase): def test_unset_ssh_address_family_preserves_original_command_and_operator_config(self) -> None: environment = git_state.sanitized_git_environment({}) self.assertEqual( [ "/usr/bin/ssh", "-o", "BatchMode=yes", "-o", "ConnectTimeout=8", ], shlex.split(environment["GIT_SSH_COMMAND"]), ) self.assertNotIn("GOVOPLAN_RELEASE_SSH_ADDRESS_FAMILY", environment) self.assertEqual(environment, git_state.sanitized_git_environment(environment)) def test_ssh_address_family_accepts_only_fixed_choices_and_survives_resanitizing(self) -> None: for family in ("any", "inet", "inet6"): with self.subTest(family=family): environment = git_state.sanitized_git_environment({ "GOVOPLAN_RELEASE_SSH_ADDRESS_FAMILY": family, "GIT_SSH_COMMAND": "/attacker/ssh -o StrictHostKeyChecking=no", "GIT_SSH": "/attacker/ssh", "PATH": "/attacker/bin", }) self.assertEqual( [ "/usr/bin/ssh", "-o", "BatchMode=yes", "-o", "ConnectTimeout=8", "-o", f"AddressFamily={family}", ], shlex.split(environment["GIT_SSH_COMMAND"]), ) self.assertNotIn("GIT_SSH", environment) self.assertEqual("/usr/bin:/bin", environment["PATH"]) self.assertEqual(environment, git_state.sanitized_git_environment(environment)) def test_invalid_ssh_address_family_is_rejected_before_git_runs(self) -> None: for invalid in ( "", "INET", "ipv4", " inet", "inet ", "inet\n", "inet; touch /not-executed", "inet -o StrictHostKeyChecking=no", "$(not-executed)", ): with ( self.subTest(value=invalid), patch.dict("os.environ", {"GOVOPLAN_RELEASE_SSH_ADDRESS_FAMILY": invalid}), patch.object(git_state.subprocess, "run") as run, ): with self.assertRaisesRegex( ValueError, "GOVOPLAN_RELEASE_SSH_ADDRESS_FAMILY must be any, inet, or inet6", ): git_state.git(Path("/workspace/govoplan-core"), "status", "--porcelain") run.assert_not_called() def test_source_provenance_readback_keeps_family_but_discards_ssh_command_override(self) -> None: from govoplan_release.source_provenance import inspect_remote_tag completed = subprocess.CompletedProcess( [], 0, f"{'a' * 40}\trefs/tags/v1.2.3\n{'b' * 40}\trefs/tags/v1.2.3^{{}}\n", "", ) with ( patch.dict("os.environ", { "GOVOPLAN_RELEASE_SSH_ADDRESS_FAMILY": "inet", "GIT_SSH_COMMAND": "/attacker/ssh -o StrictHostKeyChecking=no", }), patch("govoplan_release.repository_tag.subprocess.run", return_value=completed) as run, ): result = inspect_remote_tag( path=Path("/workspace/govoplan-core"), remote="origin", remote_url="git@git.add-ideas.de:GovOPlaN/govoplan-core.git", tag="v1.2.3", ) self.assertEqual("b" * 40, result.commit) self.assertEqual( "/usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=8 -o AddressFamily=inet", run.call_args.kwargs["env"]["GIT_SSH_COMMAND"], ) def test_manifest_version_does_not_confuse_interface_versions(self) -> None: from tempfile import TemporaryDirectory with TemporaryDirectory() as directory: root = Path(directory) / "govoplan-example" manifest = root / "src" / "govoplan_example" / "backend" / "manifest.py" manifest.parent.mkdir(parents=True) manifest.write_text( "\n".join( ( 'MODULE_VERSION = "1.2.3"', "manifest = ModuleManifest(", ' id="example",', " version=MODULE_VERSION,", " provides_interfaces=(", ' ModuleInterfaceProvider(name="example.items", version="9.8.7"),', " ),", ")", "", ) ), encoding="utf-8", ) versions = git_state.read_manifest_versions(root) self.assertEqual(("1.2.3",), versions) def test_git_trusts_only_the_resolved_repository_for_each_command(self) -> None: repository = Path("/workspace/../workspace/govoplan-core") completed = subprocess.CompletedProcess([], 0, "", "") with patch.object(git_state.subprocess, "run", return_value=completed) as run: result = git_state.git(repository, "status", "--porcelain") self.assertEqual(result.returncode, 0) command = run.call_args.args[0] self.assertIn(f"safe.directory={repository.resolve()}", command) self.assertNotIn("safe.directory=*", command) self.assertEqual(run.call_args.kwargs["cwd"], repository) self.assertEqual( run.call_args.kwargs["env"]["GIT_CONFIG_GLOBAL"], "/dev/null", ) if __name__ == "__main__": unittest.main()