photoncloud-monorepo/scripts/check_workspace_source_roots.py
centra 4ab47b1726
Implement declarative tenant networking and local VM dataplane
Add tenant-scoped PrismNET routing, security-group, port, and service-IP APIs plus a deployer reconciler and Nix module that apply declarative tenant network state.

Teach PlasmaVMC to realize PrismNET NICs as a concrete local worker dataplane with Linux bridges, dnsmasq-backed DHCP, tap devices, richer network metadata, stable managed-volume IDs, and file:// image imports.

Expand the VM cluster validation around the new path, including the guest webapp demo, restart and cross-node migration checks, IAM listener reservation hardening, and a flake workspace-source-root audit so Nix builds keep path dependencies complete.
2026-04-04 00:07:43 +09:00

119 lines
4 KiB
Python

#!/usr/bin/env python3
from __future__ import annotations
import re
import sys
import tomllib
from pathlib import Path
from typing import Any
def extract_workspace_source_roots(flake_path: Path) -> dict[str, list[str]]:
source = flake_path.read_text()
match = re.search(r"workspaceSourceRoots\s*=\s*\{(.*?)\n\s*\};", source, re.S)
if match is None:
raise ValueError(f"Could not find workspaceSourceRoots in {flake_path}")
roots: dict[str, list[str]] = {}
for name, body in re.findall(r"\n\s*(\w+)\s*=\s*\[(.*?)\];", match.group(1), re.S):
roots[name] = re.findall(r'"([^"]+)"', body)
return roots
def collect_path_dependencies(value: Any) -> list[str]:
found: list[str] = []
if isinstance(value, dict):
path = value.get("path")
if isinstance(path, str):
found.append(path)
for nested in value.values():
found.extend(collect_path_dependencies(nested))
elif isinstance(value, list):
for nested in value:
found.extend(collect_path_dependencies(nested))
return found
def workspace_manifests(repo_root: Path, workspace_name: str) -> list[Path]:
workspace_manifest = repo_root / workspace_name / "Cargo.toml"
manifests = [workspace_manifest]
workspace_data = tomllib.loads(workspace_manifest.read_text())
members = workspace_data.get("workspace", {}).get("members", [])
for member in members:
for candidate in (workspace_manifest.parent).glob(member):
manifest = candidate if candidate.name == "Cargo.toml" else candidate / "Cargo.toml"
if manifest.is_file():
manifests.append(manifest)
unique_manifests: list[Path] = []
seen: set[Path] = set()
for manifest in manifests:
resolved = manifest.resolve()
if resolved in seen:
continue
seen.add(resolved)
unique_manifests.append(manifest)
return unique_manifests
def required_root(dep_rel: Path) -> str:
parts = dep_rel.parts
if not parts:
return ""
if parts[0] == "crates" and len(parts) >= 2:
return "/".join(parts[:2])
return parts[0]
def is_covered(dep_rel: str, configured_roots: list[str]) -> bool:
return any(dep_rel == root or dep_rel.startswith(f"{root}/") for root in configured_roots)
def main() -> int:
repo_root = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else Path.cwd().resolve()
flake_path = repo_root / "flake.nix"
workspace_roots = extract_workspace_source_roots(flake_path)
failures: list[str] = []
for workspace_name, configured_roots in sorted(workspace_roots.items()):
workspace_manifest = repo_root / workspace_name / "Cargo.toml"
if not workspace_manifest.is_file():
continue
for manifest in workspace_manifests(repo_root, workspace_name):
manifest_data = tomllib.loads(manifest.read_text())
for dep_path in collect_path_dependencies(manifest_data):
dependency_dir = (manifest.parent / dep_path).resolve()
try:
dep_rel = dependency_dir.relative_to(repo_root)
except ValueError:
continue
dep_rel_str = dep_rel.as_posix()
if is_covered(dep_rel_str, configured_roots):
continue
needed = required_root(dep_rel)
manifest_rel = manifest.relative_to(repo_root).as_posix()
failures.append(
f"{workspace_name}: missing source root '{needed}' for dependency "
f"'{dep_rel_str}' referenced by {manifest_rel}"
)
if failures:
print("workspaceSourceRoots is missing path dependencies:", file=sys.stderr)
for failure in failures:
print(f" - {failure}", file=sys.stderr)
return 1
print("workspaceSourceRoots covers all workspace path dependencies.")
return 0
if __name__ == "__main__":
raise SystemExit(main())