Files
bare-operating-system/packages/bare-os-booter/scripts/run-fish-repro-pty.py
T
Raven Scott eca209b663
CI / test (push) Failing after 4m58s
Update
2026-04-03 01:37:34 -04:00

93 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""
Run fish-tty-repro.js under a pseudo-TTY and drain output so Node never blocks on write.
Usage (from anywhere):
python3 packages/bare-os-booter/scripts/run-fish-repro-pty.py
BARE_OS_REPRO_SKIP_STDERR=1 python3 packages/bare-os-booter/scripts/run-fish-repro-pty.py
BARE_OS_REPRO_PTY_ASSERT=1 ... # exit 2 if green prompt not detected (CI guard)
Requires: Unix (pty). Not for Windows CI.
"""
from __future__ import annotations
import os
import pty
import select
import sys
import threading
import time
HERE = os.path.dirname(os.path.abspath(__file__))
BOOTER = os.path.dirname(HERE)
def main() -> int:
chunks: list[bytes] = []
def reader(master_fd: int, done: threading.Event) -> None:
while not done.is_set():
try:
r, _, _ = select.select([master_fd], [], [], 0.2)
except (OSError, ValueError):
break
if done.is_set():
break
if not r:
continue
try:
data = os.read(master_fd, 65536)
except OSError:
break
if not data:
break
chunks.append(data)
pid, master_fd = pty.fork()
if pid == 0:
os.chdir(BOOTER)
os.execlp("node", "node", os.path.join(HERE, "fish-tty-repro.js"))
return 0 # unreachable
done = threading.Event()
t = threading.Thread(target=reader, args=(master_fd, done))
t.start()
time.sleep(0.6)
os.write(master_fd, b"hello\n")
time.sleep(0.35)
os.write(master_fd, b"exit\n")
# Wait for Node to exit before closing the PTY master (avoids exit code 1 / hang).
_, status = os.waitpid(pid, 0)
done.set()
t.join(timeout=5.0)
try:
os.close(master_fd)
except OSError:
pass
raw = b"".join(chunks)
try:
sys.stdout.buffer.write(raw)
except BrokenPipeError:
pass
text = raw.decode("utf-8", errors="replace")
ok_green = "\x1b[32m[user@bare-os" in text or "[user@bare-os" in text
sys.stderr.write(
f"\n--- pty harness: exit status {status}, bytes {len(raw)}, "
f"saw_full_prompt_hint={ok_green} ---\n"
)
if os.environ.get("BARE_OS_REPRO_PTY_ASSERT") == "1" and not ok_green:
sys.stderr.write("BARE_OS_REPRO_PTY_ASSERT: expected green [user@bare-os] prompt\n")
return 2
if os.WIFEXITED(status):
return os.WEXITSTATUS(status)
return 1
if __name__ == "__main__":
sys.exit(main())