Package sandbox definitions and build a pinned owner runtime
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
parent
bfe0e4c4c8
commit
be42de7caf
9 changed files with 127 additions and 8 deletions
|
|
@ -9,6 +9,7 @@ from __future__ import annotations
|
|||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
|
@ -16,8 +17,8 @@ from pathlib import Path
|
|||
from sandboxer.extensions.runtime import RUNTIME_MOUNT, runtime_digest
|
||||
|
||||
|
||||
def checked(command: list[str]) -> str:
|
||||
result = subprocess.run(command, capture_output=True, text=True, timeout=300)
|
||||
def checked(command: list[str], *, env: dict[str, str] | None = None) -> str:
|
||||
result = subprocess.run(command, capture_output=True, text=True, timeout=300, env=env)
|
||||
if result.returncode:
|
||||
raise RuntimeError(f"runtime build command failed: {Path(command[0]).name}")
|
||||
return result.stdout.strip()
|
||||
|
|
@ -44,7 +45,7 @@ def install_claude(output: Path, source: Path, sha256: str, version: str) -> dic
|
|||
|
||||
def build(output: Path, rein_source: Path, llm_source: Path,
|
||||
claude_binary: Path | None = None, claude_sha256: str | None = None,
|
||||
claude_version: str | None = None) -> dict:
|
||||
claude_version: str | None = None, *, owner_runtime: bool = False) -> dict:
|
||||
supplied = (claude_binary, claude_sha256, claude_version)
|
||||
if any(x is not None for x in supplied) and not all(x is not None for x in supplied):
|
||||
raise ValueError("Claude binary, SHA-256 and expected version must be supplied together")
|
||||
|
|
@ -53,10 +54,26 @@ def build(output: Path, rein_source: Path, llm_source: Path,
|
|||
if checked(["git", "-C", str(source), "status", "--porcelain"]):
|
||||
raise ValueError(f"{name} source must be committed before building")
|
||||
revisions[name] = checked(["git", "-C", str(source), "rev-parse", "HEAD"])
|
||||
lock_report = None
|
||||
if owner_runtime:
|
||||
lock_report = json.loads(checked([
|
||||
"/usr/bin/python3", str(rein_source / "scripts/verify_runtime_lock.py")
|
||||
]))
|
||||
if not lock_report.get("ok"):
|
||||
raise ValueError("owner runtime requires the verified sibling lock")
|
||||
if next(x["commit"] for x in lock_report["dependencies"]
|
||||
if x["distribution"] == "llm-connect") != revisions["llm-connect"]:
|
||||
raise ValueError("owner runtime llm source does not match sibling lock")
|
||||
revisions.update({x["distribution"]: x["commit"] for x in lock_report["dependencies"]})
|
||||
output.mkdir(parents=True, exist_ok=False)
|
||||
checked(["/usr/bin/python3", "-m", "venv", "--copies", "--without-pip", str(output)])
|
||||
checked(["uv", "pip", "install", "--python", str(output / "bin/python3"),
|
||||
str(rein_source), str(llm_source)])
|
||||
if owner_runtime:
|
||||
checked(["uv", "sync", "--project", str(rein_source), "--frozen", "--no-editable",
|
||||
"--no-dev", "--extra", "glas", "--extra", "llm", "--python", "/usr/bin/python3"],
|
||||
env={**os.environ, "UV_PROJECT_ENVIRONMENT": str(output)})
|
||||
else:
|
||||
checked(["uv", "pip", "install", "--python", str(output / "bin/python3"),
|
||||
str(rein_source), str(llm_source)])
|
||||
# Console entrypoints must reference the in-sandbox mount, not the build host.
|
||||
for path in (output / "bin").iterdir():
|
||||
if not path.is_file() or path.is_symlink():
|
||||
|
|
@ -75,6 +92,12 @@ def build(output: Path, rein_source: Path, llm_source: Path,
|
|||
if claude_binary is not None:
|
||||
metadata["claude"] = install_claude(output, claude_binary, claude_sha256, claude_version)
|
||||
metadata["source_revisions"] = revisions
|
||||
if owner_runtime:
|
||||
metadata["owner_runtime"] = True
|
||||
metadata["runtime_contract"] = lock_report
|
||||
metadata["uv_lock_sha256"] = hashlib.sha256(
|
||||
(rein_source / "uv.lock").read_bytes()
|
||||
).hexdigest()
|
||||
(output / "build-info.json").write_text(json.dumps(metadata, indent=2) + "\n")
|
||||
return {"runtime": {"path": str(output), "sha256": runtime_digest(output)},
|
||||
"build": metadata}
|
||||
|
|
@ -88,9 +111,12 @@ def main() -> int:
|
|||
parser.add_argument("--claude-binary", type=Path)
|
||||
parser.add_argument("--claude-sha256")
|
||||
parser.add_argument("--claude-version")
|
||||
parser.add_argument("--owner-runtime", action="store_true",
|
||||
help="Include the pinned owner packages from rein uv.lock")
|
||||
args = parser.parse_args()
|
||||
result = build(args.output.resolve(), args.rein_source.resolve(), args.llm_source.resolve(),
|
||||
args.claude_binary, args.claude_sha256, args.claude_version)
|
||||
args.claude_binary, args.claude_sha256, args.claude_version,
|
||||
owner_runtime=args.owner_runtime)
|
||||
print(json.dumps(result, indent=2))
|
||||
return 0
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue