"""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"}