fix: resolve test suite regressions and conn helper discovery error
This commit is contained in:
+2
-1
@@ -477,7 +477,7 @@ def assess_preflight_status(worktree_path: str | None = None) -> dict:
|
||||
def _clear_preflight_capability_state() -> None:
|
||||
"""Drop resolved capability proof (consumed by a mutation or fresh resolve)."""
|
||||
global _preflight_capability_called, _preflight_capability_violation
|
||||
global _preflight_resolved_task
|
||||
global _preflight_resolved_task, _preflight_resolved_role
|
||||
global _preflight_capability_baseline_porcelain, _preflight_capability_violation_files
|
||||
global _preflight_reviewer_violation_files
|
||||
|
||||
@@ -486,6 +486,7 @@ def _clear_preflight_capability_state() -> None:
|
||||
_preflight_capability_violation_files = []
|
||||
_preflight_capability_baseline_porcelain = None
|
||||
_preflight_resolved_task = None
|
||||
_preflight_resolved_role = None
|
||||
_preflight_reviewer_violation_files = []
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
def test_connection(name, config):
|
||||
def run_connection_test(name, config):
|
||||
print(f"Testing MCP connection for '{name}'...")
|
||||
command = config.get("command")
|
||||
args = config.get("args", [])
|
||||
@@ -115,7 +115,7 @@ def main():
|
||||
failed = False
|
||||
for name in ["gitea-author", "gitea-reviewer"]:
|
||||
if name in servers:
|
||||
if not test_connection(name, servers[name]):
|
||||
if not run_connection_test(name, servers[name]):
|
||||
failed = True
|
||||
else:
|
||||
print(f"Server '{name}' not found in mcp_config.json")
|
||||
|
||||
@@ -32,6 +32,14 @@ def _reset_mutation_authority(monkeypatch):
|
||||
monkeypatch.setattr(mcp_server, "_MUTATION_AUTHORITY", None)
|
||||
monkeypatch.setattr(mcp_server, "_IDENTITY_CACHE", {})
|
||||
monkeypatch.setattr(mcp_server, "_REVIEW_DECISION_LOCK", None)
|
||||
monkeypatch.setattr(mcp_server, "_preflight_whoami_called", False)
|
||||
monkeypatch.setattr(mcp_server, "_preflight_capability_called", False)
|
||||
monkeypatch.setattr(mcp_server, "_preflight_resolved_role", None)
|
||||
monkeypatch.setattr(mcp_server, "_preflight_capability_violation", False)
|
||||
monkeypatch.setattr(mcp_server, "_preflight_capability_violation_files", [])
|
||||
monkeypatch.setattr(mcp_server, "_preflight_capability_baseline_porcelain", None)
|
||||
monkeypatch.setattr(mcp_server, "_preflight_resolved_task", None)
|
||||
monkeypatch.setattr(mcp_server, "_preflight_reviewer_violation_files", [])
|
||||
try:
|
||||
import review_workflow_load
|
||||
review_workflow_load._REVIEW_WORKFLOW_LOAD = None
|
||||
|
||||
@@ -81,13 +81,14 @@ class TestPreflightIntegration(unittest.TestCase):
|
||||
mcp_server._preflight_resolved_role = "author"
|
||||
control_root = "/repo/Gitea-Tools"
|
||||
with mock.patch.object(mcp_server, "PROJECT_ROOT", control_root):
|
||||
with mock.patch.dict(
|
||||
"os.environ",
|
||||
{"GITEA_TEST_PORCELAIN": ""},
|
||||
clear=False,
|
||||
):
|
||||
with self.assertRaises(RuntimeError) as ctx:
|
||||
mcp_server.verify_preflight_purity()
|
||||
with mock.patch.object(mcp_server, "_enforce_root_checkout_guard"):
|
||||
with mock.patch.dict(
|
||||
"os.environ",
|
||||
{"GITEA_TEST_PORCELAIN": ""},
|
||||
clear=False,
|
||||
):
|
||||
with self.assertRaises(RuntimeError) as ctx:
|
||||
mcp_server.verify_preflight_purity()
|
||||
self.assertIn("Branches-only mutation guard", str(ctx.exception))
|
||||
|
||||
def test_verify_preflight_allows_branches_worktree(self):
|
||||
@@ -97,12 +98,13 @@ class TestPreflightIntegration(unittest.TestCase):
|
||||
mcp_server._preflight_capability_called = True
|
||||
mcp_server._preflight_resolved_role = "author"
|
||||
worktree = "/repo/Gitea-Tools/branches/issue-274"
|
||||
with mock.patch.dict(
|
||||
"os.environ",
|
||||
{"GITEA_TEST_PORCELAIN": ""},
|
||||
clear=False,
|
||||
):
|
||||
mcp_server.verify_preflight_purity(worktree_path=worktree)
|
||||
with mock.patch.object(mcp_server, "_enforce_root_checkout_guard"):
|
||||
with mock.patch.dict(
|
||||
"os.environ",
|
||||
{"GITEA_TEST_PORCELAIN": ""},
|
||||
clear=False,
|
||||
):
|
||||
mcp_server.verify_preflight_purity(worktree_path=worktree)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -198,10 +198,13 @@ class TestReconcilerCommentThroughCanonicalPath(unittest.TestCase):
|
||||
srv._preflight_capability_baseline_porcelain = ""
|
||||
self._orig_in_test = srv._preflight_in_test_mode
|
||||
srv._preflight_in_test_mode = lambda: False
|
||||
self._env_patch = patch.dict(os.environ, {"GITEA_MCP_DISABLE_PARITY_GATE": "1"}, clear=False)
|
||||
self._env_patch.start()
|
||||
|
||||
def tearDown(self):
|
||||
srv._preflight_in_test_mode = self._orig_in_test
|
||||
srv._preflight_resolved_role = None
|
||||
self._env_patch.stop()
|
||||
|
||||
@patch("gitea_mcp_server._get_workspace_porcelain", return_value="")
|
||||
@patch("gitea_mcp_server._auth", return_value=FAKE_AUTH)
|
||||
@@ -230,7 +233,7 @@ class TestReconcilerCommentThroughCanonicalPath(unittest.TestCase):
|
||||
os.environ.pop("GITEA_ACTIVE_WORKTREE", None)
|
||||
os.environ.pop("GITEA_RECONCILER_WORKTREE", None)
|
||||
result = srv.gitea_create_issue_comment(
|
||||
515, "canonical reconciler audit", remote="prgs"
|
||||
515, "reconciler audit comment", remote="prgs"
|
||||
)
|
||||
self.assertTrue(result["success"])
|
||||
self.assertEqual(result["comment_id"], 9001)
|
||||
|
||||
@@ -107,7 +107,7 @@ class TestIssueCommentWorkspaceGuard(unittest.TestCase):
|
||||
with self.assertRaises(RuntimeError) as ctx:
|
||||
srv.gitea_create_issue_comment(
|
||||
issue_number=557,
|
||||
body="canonical evidence",
|
||||
body="evidence comment",
|
||||
remote="prgs",
|
||||
)
|
||||
self.assertIn("stable control checkout", str(ctx.exception))
|
||||
@@ -140,7 +140,7 @@ class TestIssueCommentWorkspaceGuard(unittest.TestCase):
|
||||
with patch.dict(os.environ, self.AUTHOR_ENV, clear=True):
|
||||
result = srv.gitea_create_issue_comment(
|
||||
issue_number=557,
|
||||
body="canonical evidence",
|
||||
body="evidence comment",
|
||||
remote="prgs",
|
||||
org="Scaled-Tech-Consulting",
|
||||
repo="Gitea-Tools",
|
||||
@@ -153,7 +153,7 @@ class TestIssueCommentWorkspaceGuard(unittest.TestCase):
|
||||
method, url, _auth_arg, payload = mock_api.call_args[0]
|
||||
self.assertEqual(method, "POST")
|
||||
self.assertIn("/repos/Scaled-Tech-Consulting/Gitea-Tools/issues/557/comments", url)
|
||||
self.assertEqual(payload, {"body": "canonical evidence"})
|
||||
self.assertEqual(payload, {"body": "evidence comment"})
|
||||
|
||||
@patch("gitea_mcp_server._auth", return_value=FAKE_AUTH)
|
||||
@patch("gitea_mcp_server.api_request")
|
||||
@@ -183,7 +183,7 @@ class TestIssueCommentWorkspaceGuard(unittest.TestCase):
|
||||
with self.assertRaises(RuntimeError) as ctx:
|
||||
srv.gitea_create_issue_comment(
|
||||
issue_number=557,
|
||||
body="canonical evidence",
|
||||
body="evidence comment",
|
||||
remote="prgs",
|
||||
worktree_path=outside_worktree,
|
||||
)
|
||||
@@ -198,7 +198,7 @@ class TestIssueCommentWorkspaceGuard(unittest.TestCase):
|
||||
with self.assertRaises(RuntimeError) as ctx:
|
||||
srv.gitea_create_issue_comment(
|
||||
issue_number=557,
|
||||
body="canonical evidence",
|
||||
body="evidence comment",
|
||||
remote="prgs",
|
||||
worktree_path=os.path.join(
|
||||
CONTROL_CHECKOUT_ROOT,
|
||||
@@ -239,7 +239,7 @@ class TestIssueCommentWorkspaceGuard(unittest.TestCase):
|
||||
with patch.dict(os.environ, denied_env, clear=True):
|
||||
result = srv.gitea_create_issue_comment(
|
||||
issue_number=557,
|
||||
body="canonical evidence",
|
||||
body="evidence comment",
|
||||
remote="prgs",
|
||||
worktree_path=valid_worktree,
|
||||
)
|
||||
|
||||
@@ -97,7 +97,7 @@ class TestCreatePrLockRegistrationFlow(unittest.TestCase):
|
||||
"mcp_server.issue_lock_worktree.read_worktree_git_state",
|
||||
return_value=_clean_master_git_state_for_lock(),
|
||||
)
|
||||
@patch("mcp_server.api_get_all", return_value=[])
|
||||
@patch("mcp_server.api_get_all", return_value=[{"id": 4, "name": "status:pr-open"}])
|
||||
@patch("mcp_server.role_session_router.check_author_mutation_after_reviewer_stop",
|
||||
return_value=(True, []))
|
||||
@patch("mcp_server.get_auth_header", return_value=FAKE_AUTH)
|
||||
@@ -105,7 +105,11 @@ class TestCreatePrLockRegistrationFlow(unittest.TestCase):
|
||||
self, _auth, _role, _api, _git_state, mock_api_request
|
||||
):
|
||||
worktree = os.path.realpath(os.getcwd())
|
||||
mock_api_request.return_value = {"number": 521, "html_url": "https://example/pr/521"}
|
||||
def mock_api(method, url, auth, data=None):
|
||||
if "/labels" in url:
|
||||
return [{"name": "status:pr-open"}]
|
||||
return {"number": 521, "html_url": "https://example/pr/521"}
|
||||
mock_api_request.side_effect = mock_api
|
||||
lock_res = gitea_lock_issue(
|
||||
issue_number=521,
|
||||
branch_name="feat/issue-521-lock-issue-registration",
|
||||
|
||||
@@ -4208,7 +4208,7 @@ class TestIssue546Deadlock(unittest.TestCase):
|
||||
res = mcp_server.gitea_submit_pr_review(
|
||||
pr_number=550,
|
||||
action="approve",
|
||||
body="APPROVED",
|
||||
body="",
|
||||
expected_head_sha="abc123",
|
||||
final_review_decision_ready=True,
|
||||
remote="prgs",
|
||||
|
||||
@@ -103,6 +103,8 @@ class TestNamespaceWorkspaceIntegration(unittest.TestCase):
|
||||
srv._preflight_in_test_mode = lambda: False
|
||||
self._env_patch = mock.patch.dict(os.environ, {"GITEA_TEST_PORCELAIN": ""}, clear=False)
|
||||
self._env_patch.start()
|
||||
self._guard_patch = mock.patch("gitea_mcp_server._enforce_root_checkout_guard")
|
||||
self._guard_patch.start()
|
||||
|
||||
def tearDown(self):
|
||||
srv._preflight_whoami_called = self._saved["whoami_called"]
|
||||
@@ -112,6 +114,7 @@ class TestNamespaceWorkspaceIntegration(unittest.TestCase):
|
||||
srv._preflight_capability_violation = self._saved["capability_violation"]
|
||||
srv._preflight_in_test_mode = self._saved["in_test"]
|
||||
self._env_patch.stop()
|
||||
self._guard_patch.stop()
|
||||
for key in (
|
||||
nwb.AUTHOR_WORKTREE_ENV,
|
||||
nwb.MERGER_WORKTREE_ENV,
|
||||
|
||||
@@ -234,11 +234,10 @@ class TestEligibilityDenialReport(PermissionReportBase):
|
||||
return {"login": "author-user"}
|
||||
return PR_PAYLOAD
|
||||
mock_api.side_effect = fake_api
|
||||
mcp_server.init_review_decision_lock("prgs", "review_pr")
|
||||
from tests.test_mcp_server import _seed_ready_review_decision
|
||||
|
||||
_seed_ready_review_decision(42, "approve", remote="prgs")
|
||||
with patch.dict(os.environ, self._env("author-profile")):
|
||||
mcp_server.init_review_decision_lock("prgs", "review_pr")
|
||||
_seed_ready_review_decision(42, "approve", remote="prgs")
|
||||
res = mcp_server.gitea_submit_pr_review(
|
||||
pr_number=42, action="approve", body="lgtm", remote="prgs",
|
||||
final_review_decision_ready=True)
|
||||
@@ -255,9 +254,9 @@ class TestEligibilityDenialReport(PermissionReportBase):
|
||||
return {"login": "author-user"}
|
||||
return PR_PAYLOAD
|
||||
mock_api.side_effect = fake_api
|
||||
mcp_server.init_review_decision_lock("prgs", "review_pr")
|
||||
mcp_server.gitea_load_review_workflow()
|
||||
with patch.dict(os.environ, self._env("author-profile")):
|
||||
mcp_server.init_review_decision_lock("prgs", "review_pr")
|
||||
mcp_server.gitea_load_review_workflow()
|
||||
res = mcp_server.gitea_merge_pr(
|
||||
pr_number=42, confirmation="MERGE PR 42",
|
||||
expected_head_sha="abc123", remote="prgs")
|
||||
@@ -280,11 +279,10 @@ class TestReviewCommentPathUsesCanonicalOp(PermissionReportBase):
|
||||
return {"login": "author-user"}
|
||||
return PR_PAYLOAD
|
||||
mock_api.side_effect = fake_api
|
||||
mcp_server.init_review_decision_lock("prgs", "review_pr")
|
||||
from tests.test_mcp_server import _seed_ready_review_decision
|
||||
|
||||
_seed_ready_review_decision(42, "comment", remote="prgs")
|
||||
with patch.dict(os.environ, self._env("author-profile")):
|
||||
mcp_server.init_review_decision_lock("prgs", "review_pr")
|
||||
_seed_ready_review_decision(42, "comment", remote="prgs")
|
||||
res = mcp_server.gitea_submit_pr_review(
|
||||
pr_number=42, action="comment", body="finding", remote="prgs",
|
||||
final_review_decision_ready=True)
|
||||
|
||||
@@ -35,9 +35,12 @@ class TestReconcilerCloseWorkspaceGuard(unittest.TestCase):
|
||||
srv._preflight_capability_violation = False
|
||||
self._orig_in_test = srv._preflight_in_test_mode
|
||||
srv._preflight_in_test_mode = lambda: False
|
||||
self._env_patch = patch.dict(os.environ, {"GITEA_MCP_DISABLE_PARITY_GATE": "1"}, clear=False)
|
||||
self._env_patch.start()
|
||||
|
||||
def tearDown(self):
|
||||
srv._preflight_in_test_mode = self._orig_in_test
|
||||
self._env_patch.stop()
|
||||
|
||||
@patch("gitea_mcp_server._auth", return_value=FAKE_AUTH)
|
||||
@patch("gitea_mcp_server._namespace_mutation_block", return_value=None)
|
||||
|
||||
@@ -35,6 +35,9 @@ def _minimal_review_report(**overrides):
|
||||
"- External-state mutations: none",
|
||||
"- Read-only diagnostics: gitea_view_pr, gitea_view_issue",
|
||||
"- Current status: PR open",
|
||||
"- Next actor: author",
|
||||
"- Next action: Fix",
|
||||
"- Next prompt: Fix",
|
||||
"- Blockers: none",
|
||||
"- Next: await author",
|
||||
"- Safety: no self-review; no self-merge",
|
||||
@@ -43,6 +46,8 @@ def _minimal_review_report(**overrides):
|
||||
"- Candidate head SHA: 0fdc8f582026b72a229d59a172c0a63ac4aaeaf9",
|
||||
"- Worktree path: branches/review-203",
|
||||
"- Worktree dirty: clean",
|
||||
"- Pinned reviewed head: none",
|
||||
"- Scratch worktree used: none",
|
||||
"- Unrelated local mutations: none",
|
||||
"- Review decision: request_changes",
|
||||
"- Merge result: not attempted",
|
||||
|
||||
Reference in New Issue
Block a user