mirror of
https://github.com/Mesh-LLM/mesh-llm.git
synced 2026-08-08 22:23:19 -04:00
* ci: compose reusable products and add Depot routing * ci: configure job-local sccache storage * fix: harden Windows artifact composition * test: assert pinned nightly artifact action * ci: allow superseded SDK smokes to cancel * docs: document cancellable CI fan-in gates * ci: harden composable build graph and metrics * fix(ci): install actionlint from verified release * fix(installer): normalize runtime digest paths * fix(ci): align installer contract output * docs(ci): ground runner image migration plan * ci: route trusted ARM lanes through Depot selector * ci: enable remote sccache for fast lanes * fix(ci): await remote sccache writes * fix(ci): align sccache policy contract * refactor(ci): reuse typed SDK and static ABI inputs * fix(ci): reuse configured sccache server * fix(ci): harden exact native cache reuse * fix(ci): make PR compiler cache read-only * fix(ci): isolate pull request compiler writes * feat(ci): produce immutable Node addon artifacts * fix(ci): restrict Depot canary to main * fix(ci): isolate Depot canary cache keys
114 lines
3.6 KiB
Python
114 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Windows process-group support for the client-readiness smoke."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import os
|
|
import signal
|
|
import subprocess
|
|
from pathlib import Path
|
|
from typing import Sequence
|
|
|
|
|
|
def creationflags_for_platform(is_windows: bool) -> int:
|
|
if not is_windows:
|
|
return 0
|
|
return getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0)
|
|
|
|
|
|
def command_for_platform(command: Sequence[str], *, is_windows: bool) -> list[str]:
|
|
prepared = list(command)
|
|
if prepared[:1] == ["--"]:
|
|
prepared = prepared[1:]
|
|
if not prepared:
|
|
raise ValueError("run requires a program after --")
|
|
if is_windows:
|
|
# Git Bash accepts repository-relative POSIX-style paths, but the native
|
|
# Python CreateProcess call does not reliably resolve them. Convert the
|
|
# executable to the native absolute path before crossing that boundary.
|
|
prepared[0] = str(Path(prepared[0]).resolve())
|
|
return prepared
|
|
|
|
|
|
def launch(
|
|
command: Sequence[str], pid_file: Path, log_file: Path, *, is_windows: bool
|
|
) -> int:
|
|
with log_file.open("ab", buffering=0) as log_handle:
|
|
process = subprocess.Popen(
|
|
command_for_platform(command, is_windows=is_windows),
|
|
stdout=log_handle,
|
|
stderr=subprocess.STDOUT,
|
|
creationflags=creationflags_for_platform(is_windows),
|
|
)
|
|
pid_file.write_text(f"{process.pid}\n", encoding="utf-8")
|
|
return process.wait()
|
|
|
|
|
|
def request_ctrl_break(pid: int) -> None:
|
|
ctrl_break = getattr(signal, "CTRL_BREAK_EVENT", None)
|
|
if ctrl_break is None:
|
|
raise RuntimeError("CTRL_BREAK_EVENT is only available on Windows")
|
|
os.kill(pid, ctrl_break)
|
|
|
|
|
|
def is_running(pid: int, *, is_windows: bool) -> bool:
|
|
try:
|
|
os.kill(pid, 0)
|
|
except ProcessLookupError:
|
|
return False
|
|
except PermissionError:
|
|
return True
|
|
except OSError as error:
|
|
# Windows reports ERROR_INVALID_PARAMETER after a process has exited
|
|
# instead of raising ProcessLookupError for os.kill(pid, 0).
|
|
if is_windows and getattr(error, "winerror", None) == 87:
|
|
return False
|
|
raise
|
|
return True
|
|
|
|
|
|
def force_stop(pid: int) -> None:
|
|
subprocess.run(
|
|
["taskkill.exe", "/PID", str(pid), "/T", "/F"],
|
|
check=False,
|
|
stdout=subprocess.DEVNULL,
|
|
stderr=subprocess.DEVNULL,
|
|
)
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser()
|
|
subcommands = parser.add_subparsers(dest="command", required=True)
|
|
|
|
run = subcommands.add_parser("run")
|
|
run.add_argument("--pid-file", type=Path, required=True)
|
|
run.add_argument("--log", type=Path, required=True)
|
|
run.add_argument("program", nargs=argparse.REMAINDER)
|
|
|
|
for name in ("ctrl-break", "is-running", "force-stop"):
|
|
command = subcommands.add_parser(name)
|
|
command.add_argument("--pid", type=int, required=True)
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def main() -> int:
|
|
args = parse_args()
|
|
if args.command == "run":
|
|
if not args.program or args.program == ["--"]:
|
|
raise SystemExit("run requires a program after --")
|
|
return launch(args.program, args.pid_file, args.log, is_windows=os.name == "nt")
|
|
if args.command == "ctrl-break":
|
|
request_ctrl_break(args.pid)
|
|
return 0
|
|
if args.command == "is-running":
|
|
return 0 if is_running(args.pid, is_windows=os.name == "nt") else 1
|
|
if args.command == "force-stop":
|
|
force_stop(args.pid)
|
|
return 0
|
|
raise AssertionError(f"unexpected command: {args.command}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|