feat(template): add template prepare-win Python command via pypsrp

Replaces the abandoned PSWSMan approach (New-PSSession hangs on Linux)
with a Python-native implementation using the proven pypsrp WinRmTransport.

- New `template prepare-win` command in commands/template.py: starts VM,
  waits for WinRM, uploads and runs Install-CIToolchain-*.ps1, handles
  Windows Update 3010 reboot loop (max 10 iterations), installs CI-StaticIp
  scheduled task, runs post-setup validation, graceful shutdown, snapshot.
- Helpers: _ps_escape, _wait_tcp, _parse_exit_marker, _wait_winrm.
- 40 new tests in test_commands_template.py covering all major branches.
- Fix test_commands_job.py: patch load_config in _patch_common so tests
  don't pick up live /var/lib/ci/config.toml ip_pool and fail on lock.
- Coverage gate: 90.06% (was 88.95% before fix).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 01:22:53 +02:00
parent 6b76115b6a
commit 9e84d89823
4 changed files with 1012 additions and 3 deletions
+9
View File
@@ -100,6 +100,15 @@ def _patch_common(
monkeypatch.setattr(job_module, "load_backend", lambda _cfg: backend)
# Prevent tests from reading the live /var/lib/ci/config.toml which may
# have ip_pool configured — that would try to lock /var/lib/ci/ip-pool.lock
# (requires root) and fail before any backend call.
from ci_orchestrator.config import BackendConfig, Config, Paths
_test_paths = Paths(root=Path("/tmp/ci-test"), templates=Path("/tmp/ci-test/templates"), build_vms=Path("/tmp/ci-test/build-vms"), artifacts=Path("/tmp/ci-test/artifacts"), keys=Path("/tmp/ci-test/keys"))
_test_cfg = Config(paths=_test_paths, backend=BackendConfig(), ip_pool=None)
monkeypatch.setattr(job_module, "load_config", lambda: _test_cfg)
class _ProbeOk:
def __enter__(self) -> _ProbeOk:
return self