fix: annotate POST render endpoints read-only and irreversible POSTs destructive
This commit is contained in:
1 parent
156e963e21
commit
6b11d29919
4 files changed
+107
-22
No files matched your search
@@ -9,7 +9,13 @@ import pytest
|
||||
from jsonschema import Draft202012Validator
|
||||
|
||||
from aegis_gitea_mcp.catalog import Operation, load_catalog
|
||||
from aegis_gitea_mcp.catalog.build import build_catalog, render_catalog, spec_sha256
|
||||
from aegis_gitea_mcp.catalog.build import (
|
||||
DESTRUCTIVE_POST_OPERATIONS,
|
||||
READ_ONLY_POST_OPERATIONS,
|
||||
build_catalog,
|
||||
render_catalog,
|
||||
spec_sha256,
|
||||
)
|
||||
from aegis_gitea_mcp.catalog.schema import (
|
||||
MAX_DESCRIPTION_CHARS,
|
||||
SUDO_SCHEMA,
|
||||
@@ -536,8 +542,12 @@ def test_real_body_and_file_operations() -> None:
|
||||
def test_real_annotations() -> None:
|
||||
catalog = load_catalog()
|
||||
for operation in catalog.operations:
|
||||
assert operation.read_only == (operation.method == "GET")
|
||||
assert operation.destructive == (operation.method in {"DELETE", "PUT", "PATCH"})
|
||||
post_read_only = operation.operation_id in READ_ONLY_POST_OPERATIONS
|
||||
post_destructive = operation.operation_id in DESTRUCTIVE_POST_OPERATIONS
|
||||
assert operation.read_only == (operation.method == "GET" or post_read_only)
|
||||
assert operation.destructive == (
|
||||
operation.method in {"DELETE", "PUT", "PATCH"} or post_destructive
|
||||
)
|
||||
assert not (operation.read_only and operation.destructive)
|
||||
if operation.paginated:
|
||||
names = {p.name for p in operation.parameters}
|
||||
@@ -574,3 +584,43 @@ def test_unknown_parameter_location_is_rejected() -> None:
|
||||
)
|
||||
with pytest.raises(ValueError, match="unknown parameter location"):
|
||||
build_catalog(json.dumps(spec).encode())
|
||||
|
||||
|
||||
def test_post_annotation_overrides_in_the_real_catalog() -> None:
|
||||
by_id = {op.operation_id: op for op in load_catalog().operations}
|
||||
for operation_id in ("renderMarkdown", "renderMarkdownRaw", "renderMarkup"):
|
||||
operation = by_id[operation_id]
|
||||
assert operation.method == "POST"
|
||||
assert operation.read_only and not operation.destructive and operation.idempotent
|
||||
for operation_id in (
|
||||
"repoMergePullRequest",
|
||||
"repoTransfer",
|
||||
"acceptRepoTransfer",
|
||||
"rejectRepoTransfer",
|
||||
"adminRenameUser",
|
||||
"renameOrg",
|
||||
"adminCronRun",
|
||||
"repoMirrorSync",
|
||||
"adminAdoptRepository",
|
||||
"adminDeleteUnadoptedRepository",
|
||||
"repoRenameBranch",
|
||||
):
|
||||
operation = by_id[operation_id]
|
||||
assert operation.destructive and not operation.read_only, operation_id
|
||||
# Ordinary creating POSTs stay non-destructive.
|
||||
for operation_id in ("issueCreateIssue", "repoCreatePullRequest", "repoCreateBranch"):
|
||||
assert not by_id[operation_id].destructive
|
||||
assert not by_id[operation_id].read_only
|
||||
|
||||
|
||||
def test_every_annotation_override_names_a_real_post_operation() -> None:
|
||||
posts = {op.operation_id for op in load_catalog().operations if op.method == "POST"}
|
||||
assert READ_ONLY_POST_OPERATIONS <= posts
|
||||
assert DESTRUCTIVE_POST_OPERATIONS <= posts
|
||||
assert not READ_ONLY_POST_OPERATIONS & DESTRUCTIVE_POST_OPERATIONS
|
||||
|
||||
|
||||
def test_override_applies_to_a_mini_spec() -> None:
|
||||
spec = mini_spec({"/markdown": {"post": {"operationId": "renderMarkdown"}}})
|
||||
operation = build_ops(spec)["renderMarkdown"]
|
||||
assert operation.read_only and not operation.destructive and operation.idempotent
|
||||
Reference in new issue
Block a user