Files
ITWorx_MCP_Hub-Public/tests/test_wp170_release.py
T

88 lines
3.8 KiB
Python

"""WP-170 release-contract regression tests."""
from __future__ import annotations
import json
from pathlib import Path
import yaml
from scripts.promotion_preflight import _RESET, _ComposeMergeLoader
ROOT = Path(__file__).resolve().parents[1]
COMPOSE = ROOT / "infrastructure/compose/docker-compose.yml"
PROD_COMPOSE = ROOT / "infrastructure/compose/docker-compose.prod.yml"
INVENTORY = ROOT / "evidence/WP-170/release-inventory.json"
TRACEABILITY = ROOT / "evidence/WP-170/traceability.json"
def test_release_compose_overlay_requires_immutable_images_and_never_builds() -> None:
# _ComposeMergeLoader subclasses yaml.SafeLoader and only adds the !reset tag.
document = yaml.load(PROD_COMPOSE.read_text(encoding="utf-8"), Loader=_ComposeMergeLoader) # noqa: S506
base = yaml.safe_load(COMPOSE.read_text(encoding="utf-8"))
services = document["services"]
assert services
for name, service in services.items():
if base["services"][name].get("profiles"):
# Optional services are absent from the baseline promotion. Their
# activation overlay pins the image and is tested separately.
assert service.get("build") is _RESET
continue
if "image" not in service:
# Production may override runtime configuration without repeating an
# image only when the inherited base service is third-party,
# build-free, and already immutable by digest.
base_service = base["services"][name]
assert "build" not in base_service
assert "@sha256:" in str(base_service["image"])
continue
assert service.get("build") is _RESET
image = str(service["image"])
if image.startswith("${"):
assert "immutable" in image and ":?" in image
else:
# The recovered ContextForge baseline is one deliberately bounded
# exception until this exact compatibility image is promoted to an
# immutable registry digest. It must stay on the reviewed local tag
# and must never be pulled implicitly.
if name == "contextforge":
assert image == "itworx-mcp-hub/contextforge-schema:12d4a0c7789c"
assert service.get("pull_policy") == "never"
continue
# Other literal production images remain immutable by digest.
assert "@sha256:" in image
def test_base_compose_preserves_socket_and_edge_boundaries() -> None:
document = yaml.safe_load(COMPOSE.read_text(encoding="utf-8"))
assert any(
"/var/run/docker.sock" in str(value)
for value in document["services"]["docker-read-broker"].get("volumes", [])
)
assert not document["services"]["docker-read-broker"].get("ports")
def test_release_inventory_records_all_rc_images_and_external_boundaries() -> None:
inventory = json.loads(INVENTORY.read_text(encoding="utf-8"))
assert inventory["sourceCommit"]
assert inventory["releaseDecision"]["v1Tag"] is None
assert inventory["releaseDecision"]["reason"] == "external-input-required"
assert len(inventory["images"]) == 8
assert all(image["digest"].startswith("sha256:") for image in inventory["images"])
assert inventory["externalInputs"]
def test_traceability_covers_every_acceptance_matrix_capability() -> None:
matrix = (ROOT / "ACCEPTANCE_MATRIX.md").read_text(encoding="utf-8")
traceability = json.loads(TRACEABILITY.read_text(encoding="utf-8"))
capabilities = [
line.split("|", 2)[1].strip()
for line in matrix.splitlines()
if line.startswith("|")
and not line.startswith("| Capability")
and not line.startswith("|---")
]
assert {item["capability"] for item in traceability["requirements"]} == set(capabilities)
assert all(item["evidence"] for item in traceability["requirements"])