161 lines
6.5 KiB
Python
161 lines
6.5 KiB
Python
"""Regression tests for Issue #973: validated cross-repository canonical roots."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import shutil
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
import subprocess
|
|
|
|
import gitea_config
|
|
import namespace_workspace_binding as nwb
|
|
import canonical_repository_root as crr
|
|
|
|
|
|
class TestIssue973RecognizedEnvKeys(unittest.TestCase):
|
|
"""Test recognized environment variable keys under #973."""
|
|
|
|
def test_recognized_gitea_env_keys(self):
|
|
for key in (
|
|
"GITEA_CANONICAL_REPOSITORY_ROOT",
|
|
"GITEA_REVIEWER_WORKTREE",
|
|
"GITEA_MERGER_WORKTREE",
|
|
"GITEA_MCP_SESSION_STATE_TTL_HOURS",
|
|
):
|
|
self.assertIn(key, gitea_config.RECOGNIZED_GITEA_ENV_KEYS)
|
|
|
|
def test_get_unconsumed_gitea_env_overrides_ignores_recognized(self):
|
|
env = {
|
|
"GITEA_CANONICAL_REPOSITORY_ROOT": "/some/path",
|
|
"GITEA_REVIEWER_WORKTREE": "/some/reviewer/path",
|
|
"GITEA_MERGER_WORKTREE": "/some/merger/path",
|
|
"GITEA_MCP_SESSION_STATE_TTL_HOURS": "24",
|
|
"GITEA_UNRECOGNIZED_FOO_VAR": "bar",
|
|
}
|
|
unconsumed = gitea_config.get_unconsumed_gitea_env_overrides(env)
|
|
self.assertNotIn("GITEA_CANONICAL_REPOSITORY_ROOT", unconsumed)
|
|
self.assertNotIn("GITEA_REVIEWER_WORKTREE", unconsumed)
|
|
self.assertNotIn("GITEA_MERGER_WORKTREE", unconsumed)
|
|
self.assertNotIn("GITEA_MCP_SESSION_STATE_TTL_HOURS", unconsumed)
|
|
self.assertIn("GITEA_UNRECOGNIZED_FOO_VAR", unconsumed)
|
|
|
|
|
|
class TestIssue973CrossRepoCanonicalRoots(unittest.TestCase):
|
|
"""Test workspace binding and canonical root validation for cross-repo namespaces."""
|
|
|
|
def setUp(self):
|
|
self._tmp = tempfile.TemporaryDirectory()
|
|
self.tmp_dir = os.path.realpath(self._tmp.name)
|
|
|
|
# Create simulated installation root
|
|
self.install_root = os.path.join(self.tmp_dir, "Gitea-Tools")
|
|
os.makedirs(self.install_root)
|
|
subprocess.run(["git", "init", "-b", "master"], cwd=self.install_root, check=True)
|
|
|
|
# Create simulated target repository root
|
|
self.target_root = os.path.join(self.tmp_dir, "mcp-control-plane")
|
|
os.makedirs(self.target_root)
|
|
subprocess.run(["git", "init", "-b", "master"], cwd=self.target_root, check=True)
|
|
|
|
# Create branches/ directory and a valid worktree in target repository
|
|
self.target_branches = os.path.join(self.target_root, "branches")
|
|
os.makedirs(self.target_branches)
|
|
self.target_worktree = os.path.join(self.target_branches, "rev-pr-99")
|
|
os.makedirs(self.target_worktree)
|
|
# Create git common dir linking target_worktree to target_root
|
|
dot_git_file = os.path.join(self.target_worktree, ".git")
|
|
git_dir_target = os.path.join(self.target_root, ".git", "worktrees", "rev-pr-99")
|
|
os.makedirs(git_dir_target, exist_ok=True)
|
|
with open(dot_git_file, "w") as f:
|
|
f.write(f"gitdir: {git_dir_target}\n")
|
|
with open(os.path.join(git_dir_target, "commondir"), "w") as f:
|
|
f.write("../../..\n")
|
|
|
|
def tearDown(self):
|
|
self._tmp.cleanup()
|
|
|
|
def test_valid_cross_repo_canonical_root(self):
|
|
ctx = nwb.resolve_namespace_mutation_context(
|
|
role_kind="reviewer",
|
|
worktree_path=self.target_worktree,
|
|
process_project_root=self.install_root,
|
|
env={},
|
|
configured_canonical_root=self.target_root,
|
|
)
|
|
self.assertEqual(ctx["canonical_repo_root"], self.target_root)
|
|
self.assertTrue(ctx["roots_aligned"])
|
|
self.assertTrue(ctx["canonical_root_assessment"]["proven"])
|
|
|
|
def test_nonexistent_configured_canonical_root(self):
|
|
nonexistent = os.path.join(self.tmp_dir, "nonexistent-repo")
|
|
ctx = nwb.resolve_namespace_mutation_context(
|
|
role_kind="reviewer",
|
|
worktree_path=self.target_worktree,
|
|
process_project_root=self.install_root,
|
|
env={},
|
|
configured_canonical_root=nonexistent,
|
|
)
|
|
self.assertFalse(ctx["roots_aligned"])
|
|
self.assertFalse(ctx["canonical_root_assessment"]["proven"])
|
|
self.assertTrue(any("does not exist" in r for r in ctx["canonical_root_assessment"]["reasons"]))
|
|
|
|
def test_non_git_configured_canonical_root(self):
|
|
non_git = os.path.join(self.tmp_dir, "non-git-dir")
|
|
os.makedirs(non_git)
|
|
ctx = nwb.resolve_namespace_mutation_context(
|
|
role_kind="reviewer",
|
|
worktree_path=self.target_worktree,
|
|
process_project_root=self.install_root,
|
|
env={},
|
|
configured_canonical_root=non_git,
|
|
)
|
|
self.assertFalse(ctx["roots_aligned"])
|
|
self.assertFalse(ctx["canonical_root_assessment"]["proven"])
|
|
self.assertTrue(any("not a git repository" in r for r in ctx["canonical_root_assessment"]["reasons"]))
|
|
|
|
def test_git_common_directory_membership_matching(self):
|
|
valid, err = nwb.verify_git_common_directory_membership(
|
|
self.target_worktree, self.target_root
|
|
)
|
|
self.assertTrue(valid, err)
|
|
self.assertIsNone(err)
|
|
|
|
def test_git_common_directory_membership_foreign_repo_blocks(self):
|
|
# Foreign worktree created under install_root
|
|
foreign_wt = os.path.join(self.install_root, "branches", "foreign-wt")
|
|
os.makedirs(foreign_wt)
|
|
dot_git_file = os.path.join(foreign_wt, ".git")
|
|
git_dir_install = os.path.join(self.install_root, ".git", "worktrees", "foreign-wt")
|
|
os.makedirs(git_dir_install, exist_ok=True)
|
|
with open(dot_git_file, "w") as f:
|
|
f.write(f"gitdir: {git_dir_install}\n")
|
|
with open(os.path.join(git_dir_install, "commondir"), "w") as f:
|
|
f.write("../../..\n")
|
|
|
|
valid, err = nwb.verify_git_common_directory_membership(
|
|
foreign_wt, self.target_root
|
|
)
|
|
self.assertFalse(valid)
|
|
self.assertIn("does not belong", err)
|
|
|
|
def test_reviewer_worktree_outside_branches_blocks(self):
|
|
outside_wt = os.path.join(self.target_root, "outside_branches_wt")
|
|
os.makedirs(outside_wt)
|
|
|
|
assessment = nwb.assess_namespace_mutation_workspace(
|
|
role_kind="reviewer",
|
|
worktree_path=outside_wt,
|
|
worktree=None,
|
|
process_project_root=self.install_root,
|
|
env={},
|
|
configured_canonical_root=self.target_root,
|
|
)
|
|
self.assertTrue(assessment["block"])
|
|
self.assertTrue(any("is not under" in r for r in assessment["reasons"]))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|