feat: new settings, CLI skeleton and interface skeletons

Adds the pydantic-settings Settings with validated GITEA_URL, OAuth scopes
and toolsets, the argparse CLI skeleton, catalog.model, identity and
GiteaAPIError. Test fixtures now isolate env, cwd and state paths in tmp.
This commit is contained in:
Latte committed 2026-10-14 15:40:37 +02:00
1 parent 4ac9626eb5
commit b82e2866cb
24 files changed
+1512 -605

No files matched your search

+1 -51
View File
@@ -1,4 +1,4 @@
"""Tests for structured logging helpers and get_issue instrumentation (#14)."""
"""Tests for structured logging helpers."""
from __future__ import annotations
@@ -7,26 +7,12 @@ import logging
import pytest
from aegis_gitea_mcp.config import reset_settings
from aegis_gitea_mcp.logging_utils import (
JsonLogFormatter,
log_event,
log_nullable_field,
sanitize_context,
)
from aegis_gitea_mcp.tools.read_tools import get_issue_tool
READ_TOOLS_LOGGER = "aegis_gitea_mcp.tools.read_tools"
@pytest.fixture(autouse=True)
def tool_env(monkeypatch: pytest.MonkeyPatch) -> None:
"""Provide minimal settings environment for response limit helpers."""
reset_settings()
monkeypatch.setenv("GITEA_URL", "https://gitea.example.com")
monkeypatch.setenv("GITEA_TOKEN", "test-token")
monkeypatch.setenv("MCP_API_KEYS", "a" * 64)
monkeypatch.setenv("ENVIRONMENT", "test")
def test_sanitize_context_masks_sensitive_keys() -> None:
@@ -82,39 +68,3 @@ def test_log_nullable_field_characterizes_value(caplog: pytest.LogCaptureFixture
"is_none": False,
"value_type": "list",
}
class _NullIssueGitea:
"""Minimal stub returning an issue with null collection fields."""
async def get_issue(self, owner: str, repo: str, index: int) -> dict[str, object]:
return {
"number": index,
"title": "Issue",
"body": "Body",
"state": "open",
"labels": None,
"assignees": None,
"user": None,
}
@pytest.mark.asyncio
async def test_get_issue_tool_emits_debug_events(caplog: pytest.LogCaptureFixture) -> None:
"""get_issue_tool emits start/shape/field-check debug events and still parses."""
with caplog.at_level(logging.DEBUG, logger=READ_TOOLS_LOGGER):
result = await get_issue_tool(
_NullIssueGitea(), {"owner": "acme", "repo": "app", "issue_number": 7}
)
events = [r.getMessage() for r in caplog.records]
assert "get_issue.start" in events
assert "get_issue.payload_shape" in events
field_checks = [r.context for r in caplog.records if r.getMessage() == "get_issue.field_check"]
assert {"field": "labels", "is_none": True, "value_type": None} in field_checks
assert {"field": "user", "is_none": True, "value_type": None} in field_checks
# Logging must not change behaviour: null collections still parse to empties.
assert result["labels"] == []
assert result["assignees"] == []