Description
The test_exec_bash test in jumpstarter-common fails consistently on macOS CI runners (macos-15, Python 3.11) while passing on Linux. The root cause is that PTY output written by hook subprocesses is not fully drained before the test assertions run, causing the mocked logger to miss expected log lines.
Root Cause
In python/packages/jumpstarter/jumpstarter/exporter/hooks.py, the HookExecutor._run_hook method uses a PTY for subprocess output capture. On macOS, the PTY I/O timing differs from Linux -- the async reader task may not have consumed all output by the time it is cancelled after the subprocess exits. There is no drain step to read remaining buffered data from the PTY file descriptor after the reader task stops.
Affected CI
- Workflow: Python CI (
python.yml)
- Runner:
macos-15
- Python version: 3.11
- Test:
test_exec_bash in python/packages/jumpstarter/jumpstarter/exporter/hooks_test.py
- Failure pattern: Persistent (fails on every macOS run)
Reproduction
Run the test suite for jumpstarter-common on macOS:
cd python && make pkg-test-jumpstarter_common
The test passes on Linux but fails on macOS because the mocked logger does not receive the expected output lines.
Expected Behavior
test_exec_bash should pass on both Linux and macOS, with all hook subprocess output captured by the logger regardless of platform PTY timing differences.
Proposed Fix
- After the async reader task is cancelled, drain any remaining data from the PTY file descriptor synchronously before closing it
- Bound the drain loop to prevent indefinite blocking (max iterations + timeout)
- Properly handle
OSError during drain (PTY may already be closed)
Description
The
test_exec_bashtest injumpstarter-commonfails consistently on macOS CI runners (macos-15, Python 3.11) while passing on Linux. The root cause is that PTY output written by hook subprocesses is not fully drained before the test assertions run, causing the mocked logger to miss expected log lines.Root Cause
In
python/packages/jumpstarter/jumpstarter/exporter/hooks.py, theHookExecutor._run_hookmethod uses a PTY for subprocess output capture. On macOS, the PTY I/O timing differs from Linux -- the async reader task may not have consumed all output by the time it is cancelled after the subprocess exits. There is no drain step to read remaining buffered data from the PTY file descriptor after the reader task stops.Affected CI
python.yml)macos-15test_exec_bashinpython/packages/jumpstarter/jumpstarter/exporter/hooks_test.pyReproduction
Run the test suite for
jumpstarter-commonon macOS:The test passes on Linux but fails on macOS because the mocked logger does not receive the expected output lines.
Expected Behavior
test_exec_bashshould pass on both Linux and macOS, with all hook subprocess output captured by the logger regardless of platform PTY timing differences.Proposed Fix
OSErrorduring drain (PTY may already be closed)