Prepare packaged Hermes for native in-app updates
Track main while pinning the initial release commit. Ship the matching upstream installer and Linux namespace sandbox backport, and launch the native user build prepared by Omarchy. Co-Authored-By: GPT-6 Codex (xhigh) <noreply@openai.com>
This commit is contained in:
1 parent
3356e8c04c
commit
9588b28cf6
4 files changed
+206
-32
No files matched your search
@@ -0,0 +1,71 @@
|
||||
"""Check the release backport against the actual pinned upstream source."""
|
||||
import ast
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from typing import Optional
|
||||
from unittest.mock import patch
|
||||
|
||||
source, patch_file = map(Path, sys.argv[1:])
|
||||
with tempfile.TemporaryDirectory(prefix="hermes-runtime-check-") as temporary:
|
||||
root = Path(temporary)
|
||||
for filename in ("hermes_cli/main.py", "scripts/desktop-update/posix.sh"):
|
||||
destination = root / filename
|
||||
destination.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copyfile(source / filename, destination)
|
||||
subprocess.run(["git", "apply", str(patch_file.resolve())], cwd=root, check=True)
|
||||
text = (root / "hermes_cli/main.py").read_text()
|
||||
functions = {node.name: node for node in ast.parse(text).body if isinstance(node, ast.FunctionDef)}
|
||||
names = [
|
||||
"_desktop_linux_userns_sandbox_available", "_sandbox_helper_lstat",
|
||||
"_sandbox_helper_is_setuid_root", "_desktop_linux_needs_disable_setuid_sandbox",
|
||||
"_desktop_linux_sandbox_fixup",
|
||||
]
|
||||
scope = dict(Path=Path, Optional=Optional, os=os, sys=sys, shutil=shutil,
|
||||
subprocess=subprocess, stat=__import__("stat"))
|
||||
for name in names:
|
||||
exec(compile(ast.Module(body=[functions[name]], type_ignores=[]), str(source), "exec"), scope)
|
||||
|
||||
native = root / "apps/desktop/release/linux-unpacked"
|
||||
native.mkdir(parents=True)
|
||||
executable = native / "Hermes"
|
||||
sandbox = native / "chrome-sandbox"
|
||||
sandbox.write_text("fixture")
|
||||
sandbox.chmod(0o755)
|
||||
gui = ast.get_source_segment(text, functions["cmd_gui"])
|
||||
start = gui.index(" launch_command = [str(packaged_executable)]")
|
||||
end = gui.index(" launch_command.extend(config_electron_flags)", start)
|
||||
exec("def launch(packaged_executable):\n" + gui[start:end] + " return launch_command\n", scope)
|
||||
scope["_desktop_linux_needs_no_sandbox"] = lambda: False
|
||||
with patch.object(shutil, "which", side_effect=lambda name: "/fixture/unshare" if name == "unshare" else None):
|
||||
with patch.object(subprocess, "run", return_value=subprocess.CompletedProcess([], 0)) as run:
|
||||
assert scope["launch"](executable) == [str(executable), "--disable-setuid-sandbox"]
|
||||
assert all(call.args[0][0] == "/fixture/unshare" for call in run.call_args_list)
|
||||
with patch.object(subprocess, "run", return_value=subprocess.CompletedProcess([], 1)):
|
||||
assert not scope["_desktop_linux_sandbox_fixup"](executable)
|
||||
sandbox.unlink()
|
||||
sandbox.symlink_to(root / "unrelated")
|
||||
(root / "unrelated").write_text("keep")
|
||||
with patch.object(subprocess, "run") as run:
|
||||
assert not scope["_desktop_linux_sandbox_fixup"](executable)
|
||||
run.assert_not_called()
|
||||
sandbox.unlink()
|
||||
sandbox.write_text("fixture")
|
||||
|
||||
mock_bin = root / "bin"
|
||||
mock_bin.mkdir()
|
||||
unshare = mock_bin / "unshare"
|
||||
unshare.write_text('#!/bin/bash\nexit "${TEST_NAMESPACE_RESULT:-0}"\n')
|
||||
unshare.chmod(0o755)
|
||||
env = {**os.environ, "PATH": f"{mock_bin}:/usr/bin:/bin"}
|
||||
env.pop("ELECTRON_DISABLE_SANDBOX", None)
|
||||
gate = ["bash", str(root / "scripts/desktop-update/posix.sh"), "--self-test-gate",
|
||||
"--install-root", str(root), "--relaunch-target", str(executable)]
|
||||
assert subprocess.check_output(gate, env=env, text=True).strip() == "relaunch"
|
||||
assert subprocess.check_output(gate, env={**env, "TEST_NAMESPACE_RESULT": "1"}, text=True).startswith("manual:")
|
||||
gate[-1] = "/opt/hermes-desktop/Hermes"
|
||||
assert subprocess.check_output(gate, env=env, text=True).startswith("skew:")
|
||||
print("PASS: native launch and release update handoff retain the user-namespace sandbox")
|
||||
Reference in new issue
Block a user