feat(prepare-win): stream toolchain/WU output to the console live

pypsrp's execute_ps is fully blocking, so Install-CIToolchain / Windows
Update output only appeared at the end behind a "still running (Ns)"
heartbeat. Add WinRmTransport.run_streaming: drive the script via pypsrp's
incremental begin_invoke/poll_invoke, emitting output, Write-Host
(information) and error stream lines as they arrive over the same WinRM
channel.

_run_with_heartbeat now prefers run_streaming (suppressing the CI_EXITCODE
marker line) and falls back to the blocking heartbeat only on an unexpected
pypsrp error — TransportError still propagates so the 3010 reboot handling
is unaffected.
This commit is contained in:
2026-06-09 21:00:18 +02:00
parent 107bff8c8a
commit e0b1c1ddcc
4 changed files with 181 additions and 4 deletions
+9
View File
@@ -515,6 +515,15 @@ def test_prepare_win_explicit_toolchain_not_found(tmp_path: Path) -> None:
def _patch_prepare(monkeypatch: pytest.MonkeyPatch, backend: MagicMock, transport: MagicMock) -> None:
# _run_with_heartbeat prefers transport.run_streaming; route it through the
# test's transport.run side_effect and feed stdout to the on_line callback.
if not hasattr(transport.run_streaming, "side_effect") or transport.run_streaming.side_effect is None:
def _stream(script: str = "", on_line: object = None, **kwargs: object) -> WinRmResult:
res = transport.run(script, **kwargs)
if callable(on_line) and isinstance(res, WinRmResult):
on_line(res.stdout)
return res
transport.run_streaming.side_effect = _stream
monkeypatch.setattr(tmpl_mod, "load_config", lambda: _make_config())
monkeypatch.setattr(tmpl_mod, "WorkstationVmrunBackend", lambda **_: backend)
monkeypatch.setattr(tmpl_mod, "WinRmTransport", lambda **_: transport)