Initial public ModelForge release
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
"""Fail-closed integration tests for the parentless public source boundary."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
REPOSITORY_ROOT = Path(__file__).resolve().parents[2]
|
||||
EXPORTER = REPOSITORY_ROOT / "scripts" / "export-public-source.mjs"
|
||||
VALIDATOR = REPOSITORY_ROOT / "scripts" / "validate-public-source.mjs"
|
||||
|
||||
|
||||
class PublicSourceExportTests(unittest.TestCase):
|
||||
def _repository(
|
||||
self,
|
||||
root: Path,
|
||||
*,
|
||||
license_present: bool = True,
|
||||
managed_validation_workflow: str | None = None,
|
||||
) -> Path:
|
||||
repository = root / "private-source"
|
||||
repository.mkdir()
|
||||
files: dict[str, str | bytes] = {
|
||||
"README.md": "# Product\n",
|
||||
"SECURITY.md": "# Security\n",
|
||||
"CONTRIBUTING.md": "# Contributing\n",
|
||||
"docker-compose.yml": "services: {}\n",
|
||||
"VERSION": "1.2.1\n",
|
||||
"backend/pyproject.toml": "[project]\nname = 'fixture-api'\n",
|
||||
"frontend/package.json": '{"name":"fixture-web"}\n',
|
||||
"node-agent/pyproject.toml": "[project]\nname = 'fixture-agent'\n",
|
||||
"runtime-worker/pyproject.toml": "[project]\nname = 'fixture-worker'\n",
|
||||
}
|
||||
if license_present:
|
||||
files["LICENSE"] = (REPOSITORY_ROOT / "LICENSE").read_bytes()
|
||||
if managed_validation_workflow is not None:
|
||||
files[".gitea/workflows/managed-validation.yml"] = managed_validation_workflow
|
||||
for relative_path, contents in files.items():
|
||||
destination = repository / relative_path
|
||||
destination.parent.mkdir(parents=True, exist_ok=True)
|
||||
if isinstance(contents, bytes):
|
||||
destination.write_bytes(contents)
|
||||
else:
|
||||
destination.write_text(contents, encoding="utf-8")
|
||||
(repository / "public-source.allowlist").write_text(
|
||||
"\n".join(sorted(files)) + "\n", encoding="utf-8"
|
||||
)
|
||||
subprocess.run(["git", "init", "-q"], cwd=repository, check=True)
|
||||
subprocess.run(["git", "add", "."], cwd=repository, check=True)
|
||||
subprocess.run(
|
||||
[
|
||||
"git",
|
||||
"-c",
|
||||
"user.name=ModelForge test",
|
||||
"-c",
|
||||
"user.email=test@example.invalid",
|
||||
"commit",
|
||||
"-qm",
|
||||
"fixture",
|
||||
],
|
||||
cwd=repository,
|
||||
check=True,
|
||||
)
|
||||
return repository
|
||||
|
||||
def _export(self, repository: Path, output: Path) -> subprocess.CompletedProcess[str]:
|
||||
return subprocess.run(
|
||||
["node", str(EXPORTER), "--repository", str(repository), "--output", str(output)],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
errors="replace",
|
||||
check=False,
|
||||
)
|
||||
|
||||
def _validate(self, output: Path) -> subprocess.CompletedProcess[str]:
|
||||
return subprocess.run(
|
||||
["node", str(VALIDATOR)],
|
||||
cwd=output,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
errors="replace",
|
||||
check=False,
|
||||
)
|
||||
|
||||
def test_export_requires_an_explicit_tracked_license(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
repository = self._repository(root, license_present=False)
|
||||
result = self._export(repository, root / "public")
|
||||
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("canonical LICENSE is missing", result.stderr)
|
||||
|
||||
def test_manifest_detects_content_tampering_and_unexpected_files(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
output = root / "public"
|
||||
result = self._export(self._repository(root), output)
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
validation = self._validate(output)
|
||||
self.assertEqual(validation.returncode, 0, validation.stdout + validation.stderr)
|
||||
|
||||
original_readme = (output / "README.md").read_bytes()
|
||||
(output / "README.md").write_text("tampered\n", encoding="utf-8")
|
||||
tampered = self._validate(output)
|
||||
self.assertNotEqual(tampered.returncode, 0)
|
||||
self.assertIn("Manifest", tampered.stderr)
|
||||
|
||||
(output / "README.md").write_bytes(original_readme)
|
||||
(output / "not-reviewed.txt").write_text("extra\n", encoding="utf-8")
|
||||
unexpected = self._validate(output)
|
||||
self.assertNotEqual(unexpected.returncode, 0)
|
||||
self.assertIn("Unexpected public source files", unexpected.stderr)
|
||||
|
||||
def test_dirty_source_tree_cannot_claim_the_head_revision(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
repository = self._repository(root)
|
||||
(repository / "README.md").write_text("changed after commit\n", encoding="utf-8")
|
||||
result = self._export(repository, root / "public")
|
||||
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("commit the exact source tree", result.stderr)
|
||||
|
||||
def test_sanitized_destination_collisions_fail_before_writing(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
repository = self._repository(root)
|
||||
private_name = "Tow" + "er.txt"
|
||||
public_name = "GPU " + "Node.txt"
|
||||
(repository / private_name).write_text("one\n", encoding="utf-8")
|
||||
(repository / public_name).write_text("two\n", encoding="utf-8")
|
||||
with (repository / "public-source.allowlist").open("a", encoding="utf-8") as allowlist:
|
||||
allowlist.write(f"{private_name}\n{public_name}\n")
|
||||
subprocess.run(["git", "add", "."], cwd=repository, check=True)
|
||||
subprocess.run(
|
||||
[
|
||||
"git",
|
||||
"-c",
|
||||
"user.name=ModelForge test",
|
||||
"-c",
|
||||
"user.email=test@example.invalid",
|
||||
"commit",
|
||||
"-qm",
|
||||
"collision fixture",
|
||||
],
|
||||
cwd=repository,
|
||||
check=True,
|
||||
)
|
||||
result = self._export(repository, root / "public")
|
||||
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("finding", result.stderr)
|
||||
|
||||
def test_public_managed_validation_requires_explicit_owner_dispatch(self) -> None:
|
||||
workflow = "name: Managed validation\n\non:\n pull_request:\n workflow_dispatch:\n"
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
repository = self._repository(
|
||||
root,
|
||||
managed_validation_workflow=workflow,
|
||||
)
|
||||
output = root / "public"
|
||||
result = self._export(repository, output)
|
||||
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
canonical = (
|
||||
repository / ".gitea/workflows/managed-validation.yml"
|
||||
).read_text(encoding="utf-8")
|
||||
exported = (
|
||||
output / ".gitea/workflows/managed-validation.yml"
|
||||
).read_text(encoding="utf-8")
|
||||
|
||||
self.assertIn(" pull_request:\n", canonical)
|
||||
self.assertNotIn(" pull_request:\n", exported)
|
||||
self.assertIn(" workflow_dispatch:\n", exported)
|
||||
self.assertIn("fork PRs never reach private runners", exported)
|
||||
|
||||
def test_changed_managed_validation_trigger_fails_closed(self) -> None:
|
||||
workflow = "name: Managed validation\n\non:\n workflow_dispatch:\n"
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
repository = self._repository(
|
||||
root,
|
||||
managed_validation_workflow=workflow,
|
||||
)
|
||||
result = self._export(repository, root / "public")
|
||||
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("has no expected pull_request trigger", result.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user