82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
"""Fail-closed preflight for the pinned Rayforge Windows GUI checkpoint."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
def inspect(rayforge: Path, python_env: Path) -> dict[str, object]:
|
|
msys2_shell = Path("C:/msys64/msys2_shell.cmd")
|
|
msys2_env = rayforge / ".msys2_env"
|
|
gi_probe = subprocess.run(
|
|
[str(python_env), "-c", "import gi"],
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
gi_available = gi_probe.returncode == 0
|
|
gi_error = next(
|
|
(
|
|
line.strip()
|
|
for line in reversed(gi_probe.stderr.splitlines())
|
|
if line.strip()
|
|
),
|
|
"unable to import gi",
|
|
)
|
|
app_entry = rayforge / "rayforge" / "__main__.py"
|
|
addon_manifest = (
|
|
Path(__file__).parents[1]
|
|
/ "spikes"
|
|
/ "rayforge-jcz-no-device-addon"
|
|
/ "rayforge-addon.yaml"
|
|
)
|
|
checks = {
|
|
"pinned_source_present": (rayforge / ".git").is_dir(),
|
|
"application_entry_present": app_entry.is_file(),
|
|
"no_device_addon_present": addon_manifest.is_file(),
|
|
"python_environment_present": python_env.is_file(),
|
|
"pygobject_gi_available": gi_available,
|
|
"msys2_ucrt64_shell_present": msys2_shell.is_file(),
|
|
"rayforge_msys2_environment_present": msys2_env.is_file(),
|
|
}
|
|
ready = all(checks.values())
|
|
return {
|
|
"transport": None,
|
|
"controller_backend_reachable": False,
|
|
"checks": checks,
|
|
"ready_for_manual_gui_test": ready,
|
|
"status": "ready" if ready else "blocked",
|
|
"missing_requirements": [key for key, passed in checks.items() if not passed],
|
|
"observed_launch_error": (
|
|
None
|
|
if gi_available
|
|
else gi_error
|
|
),
|
|
"installation_performed": False,
|
|
"next_action": (
|
|
"launch isolated no-device GUI test"
|
|
if ready
|
|
else "provide a reviewed Rayforge Windows GTK runtime or approve its installation"
|
|
),
|
|
}
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("rayforge", type=Path)
|
|
parser.add_argument("python", type=Path)
|
|
parser.add_argument("--output", type=Path)
|
|
args = parser.parse_args()
|
|
result = inspect(args.rayforge.resolve(), args.python.resolve())
|
|
rendered = json.dumps(result, indent=2, sort_keys=True) + "\n"
|
|
if args.output:
|
|
args.output.write_text(rendered, encoding="utf-8", newline="\n")
|
|
else:
|
|
print(rendered, end="")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|