Files
ITWorx_MCP_Hub-Public/tests/test_wp220_export.py
T

159 lines
5.9 KiB
Python

"""WP-220B regression tests: deterministic, clean-room release export."""
from __future__ import annotations
import json
import subprocess
import sys
import tarfile
from pathlib import Path
import pytest
from scripts import create_manifest, export_release
def _git(repo: Path, *args: str) -> str:
result = subprocess.run( # noqa: S603
["git", *args], # noqa: S607
cwd=repo,
capture_output=True,
text=True,
check=True,
)
return result.stdout
def _build_repo(tmp_path: Path) -> Path:
repo = tmp_path / "repo"
repo.mkdir()
_git(repo, "init", "-q", "-b", "main")
_git(repo, "config", "user.email", "test@example.invalid")
_git(repo, "config", "user.name", "WP-220 Test")
_git(repo, "config", "core.autocrlf", "false")
(repo / ".gitattributes").write_text("* text=auto eol=lf\n", encoding="utf-8")
(repo / ".gitignore").write_text("secret.local\n", encoding="utf-8")
(repo / "README.md").write_text("hello\n", encoding="utf-8")
(repo / "src").mkdir()
(repo / "src" / "app.py").write_text("print('hi')\n", encoding="utf-8")
(repo / "pyproject.toml").write_text(
'[project]\nname = "x"\nversion = "0.0.0"\ndependencies = []\n\n'
"[dependency-groups]\ndev = []\n",
encoding="utf-8",
)
(repo / "evidence").mkdir()
(repo / "evidence" / "NOTE.md").write_text("evidence\n", encoding="utf-8")
(repo / "secret.local").write_text("not tracked, must never be exported\n", encoding="utf-8")
_git(repo, "add", "-A")
_git(repo, "commit", "-q", "-m", "initial commit")
manifest = create_manifest.build_manifest("HEAD", repo)
(repo / "PACK_MANIFEST.json").write_text(
json.dumps(manifest, indent=2) + "\n", encoding="utf-8"
)
_git(repo, "add", "PACK_MANIFEST.json")
_git(repo, "commit", "-q", "-m", "record manifest")
return repo
@pytest.fixture
def repo(tmp_path: Path) -> Path:
return _build_repo(tmp_path)
def _run_export(repo: Path, output_dir: Path, *extra: str) -> subprocess.CompletedProcess[str]:
script = Path(export_release.__file__)
return subprocess.run( # noqa: S603
[sys.executable, str(script), "--root", str(repo), "--output-dir", str(output_dir), *extra],
cwd=repo,
capture_output=True,
text=True,
check=False,
)
def test_source_archive_contains_only_tracked_content(repo: Path, tmp_path: Path) -> None:
output_dir = tmp_path / "export"
result = _run_export(repo, output_dir)
assert result.returncode == 0, result.stdout + result.stderr
archive_path = output_dir / "itworx-mcp-hub-source.tar.gz"
assert archive_path.is_file()
with tarfile.open(archive_path) as archive:
names = set(archive.getnames())
assert "secret.local" not in names
assert "README.md" in names
assert "src/app.py" in names
def test_export_verifies_clean_against_manifest(repo: Path, tmp_path: Path) -> None:
output_dir = tmp_path / "export"
result = _run_export(repo, output_dir, "--verify")
assert result.returncode == 0, result.stdout + result.stderr
export_manifest = json.loads((output_dir / "EXPORT_MANIFEST.json").read_text(encoding="utf-8"))
assert export_manifest["sourceArchiveVerifiedAgainstManifest"] is True
assert export_manifest["sourceArchiveVerificationErrors"] == []
def test_export_detects_tampering_via_verify(repo: Path, tmp_path: Path) -> None:
(repo / "src" / "app.py").write_text("print('tampered')\n", encoding="utf-8")
_git(repo, "commit", "-am", "tamper without regenerating manifest")
output_dir = tmp_path / "export"
result = _run_export(repo, output_dir, "--verify")
assert result.returncode == 1
export_manifest = json.loads((output_dir / "EXPORT_MANIFEST.json").read_text(encoding="utf-8"))
assert export_manifest["sourceArchiveVerifiedAgainstManifest"] is False
assert export_manifest["sourceArchiveVerificationErrors"]
def test_checksums_file_matches_produced_artifacts(repo: Path, tmp_path: Path) -> None:
output_dir = tmp_path / "export"
_run_export(repo, output_dir, "--include-evidence")
checksums_text = (output_dir / "CHECKSUMS.sha256").read_text(encoding="utf-8")
lines = [line for line in checksums_text.splitlines() if line.strip()]
assert any(line.endswith("itworx-mcp-hub-source.tar.gz") for line in lines)
assert any(line.endswith("sbom.cdx.json") for line in lines)
import hashlib
for line in lines:
digest, name = line.split(" ", 1)
data = (output_dir / name).read_bytes()
assert hashlib.sha256(data).hexdigest() == digest
def test_history_bundle_reproduces_identical_tree(repo: Path, tmp_path: Path) -> None:
output_dir = tmp_path / "export"
_run_export(repo, output_dir, "--include-history")
bundle_path = output_dir / "itworx-mcp-hub-history.bundle"
assert bundle_path.is_file()
clone_dir = tmp_path / "clone-from-bundle"
_git(tmp_path, "clone", "-q", str(bundle_path), str(clone_dir))
original_tree = create_manifest.resolve_tree("HEAD", repo)
cloned_tree = create_manifest.resolve_tree("HEAD", clone_dir)
assert original_tree == cloned_tree
def test_sbom_is_generated_and_records_source_commit(repo: Path, tmp_path: Path) -> None:
output_dir = tmp_path / "export"
_run_export(repo, output_dir)
sbom = json.loads((output_dir / "sbom.cdx.json").read_text(encoding="utf-8"))
head_commit = create_manifest.resolve_commit("HEAD", repo)
assert sbom["metadata"]["sourceCommit"] == head_commit
def test_evidence_archive_contains_only_evidence_subtree(repo: Path, tmp_path: Path) -> None:
output_dir = tmp_path / "export"
_run_export(repo, output_dir, "--include-evidence")
evidence_archive = output_dir / "itworx-mcp-hub-evidence.tar.gz"
assert evidence_archive.is_file()
with tarfile.open(evidence_archive) as archive:
names = set(archive.getnames())
assert names == {"evidence", "evidence/NOTE.md"}