feat: Windows VM phase 3 β golden image automation, CI guide, examples#115
feat: Windows VM phase 3 β golden image automation, CI guide, examples#115Miyamura80 merged 3 commits intomasterfrom
Conversation
Two-stage `desktest init-windows` command that takes a Windows ISO + VirtIO driver ISO and produces a ready-to-use QCOW2 golden image: - Stage 1: Unattended Windows install via Autounattend.xml (UEFI GPT, VirtIO drivers, TPM bypass, OpenSSH, auto-login, OOBE skip) - Stage 2: SSH provisioning via provision.ps1 (Python 3, PyAutoGUI, uiautomation, WinFsp + VirtIO-FS mount, agent scripts, scheduled task, disabled UAC/Defender/Updates) Also adds CI/CD integration guide with GitHub Actions workflow YAML (annotated with KVM/runner limitations), Windows Calculator test example, and updates all markdown documentation to reflect Windows support alongside macOS. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce InitConfig struct to reduce stage1_install parameter count from 9 to 1, and remove unnecessary borrow on ssh_opts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR completes Phase 3 of Windows VM support for desktest: it adds the Key changes:
All three findings are P2 (style/UX) with no correctness or data-integrity impact. Confidence Score: 5/5Safe to merge β all remaining findings are P2 style/UX improvements with no correctness or data-integrity impact. The implementation is thorough and well-structured: prerequisite checks run before any side effects, child processes are cleaned up in both success and failure paths, the two-stage flow is clearly separated, and error messages are actionable. All three comments are P2: the example evaluator mismatch is cosmetic, the 120-second post-failure wait is a UX delay not a correctness bug, and the port-2222 conflict surfaces eventually via SSH timeout rather than immediately. examples/windows-calculator.json (evaluator mismatch), src/init_windows.rs lines 429-439 (unconditional shutdown wait on failure) Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant CLI as desktest CLI
participant S1 as Stage 1 (QEMU install)
participant S2 as Stage 2 (QEMU + SSH)
participant Win as Windows Guest
User->>CLI: desktest init-windows --windows-iso ... --virtio-iso ...
CLI->>CLI: preflight checks (QEMU, OVMF, swtpm, genisoimage, sshpass)
CLI->>CLI: validate ISO paths, check output doesn't exist
CLI->>CLI: find windows/ dir (scripts + Autounattend.xml)
CLI->>CLI: create temp work_dir
note over CLI,S1: Stage 1 β unattended OS install
CLI->>S1: spawn swtpm (TPM emulator)
CLI->>S1: genisoimage β autounattend.iso
CLI->>S1: qemu-img create β output.qcow2
CLI->>S1: spawn QEMU (Windows ISO + VirtIO ISO + autounattend.iso)
S1->>Win: boot from CD-ROM
Win->>Win: Autounattend.xml: partition, install OS, load VirtIO drivers
Win->>Win: Enable OpenSSH Server, disable Defender
Win->>Win: FirstLogonCommands: disable UAC, screensaver, set resolution
Win->>S1: shutdown /s (signals Stage 1 complete)
S1->>CLI: QEMU exits
CLI->>CLI: kill swtpm
note over CLI,S2: Stage 2 β SSH provisioning
CLI->>S2: spawn swtpm (new TPM state)
CLI->>S2: spawn QEMU (output.qcow2, hostfwd tcp::2222-:22)
S2->>Win: boot installed Windows
CLI->>CLI: wait_for_ssh() β poll localhost:2222 (3 min timeout)
CLI->>Win: sshpass/scp β copy vm-agent.py, execute-action.py, get-a11y-tree.py, win-screenshot.py
CLI->>Win: sshpass/scp β copy provision.ps1
CLI->>Win: ssh β powershell -File C:\\Temp\\provision.ps1
Win->>Win: install Python 3, pip packages, WinFsp
Win->>Win: configure VirtIO-FS (Z:\\), deploy scripts, register scheduled task
Win->>Win: disable UAC, Update, screensaver, configure auto-login
Win->>S2: shutdown /s (signals Stage 2 complete, SSH exits 255)
S2->>CLI: QEMU exits
CLI->>CLI: kill swtpm, clean up work_dir
CLI->>User: Golden image ready!
Reviews (2): Last reviewed commit: "fix: address PR review feedback β OVMF_V..." | Re-trigger Greptile |
β¦blocking - Reuse Stage 1's OVMF_VARS.fd in Stage 2 instead of copying a fresh template. The Windows installer writes EFI boot entries into this file; discarding it forces a slower UEFI fallback scan or potential boot failure. - Switch run_sshpass() from .status() to .output() so stderr is captured and included in error messages, making provisioning failures diagnosable. - Wrap check_iso_builder() and check_sshpass_installed() with spawn_blocking() to avoid blocking the Tokio worker thread. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
desktest init-windowscommand: Two-stage golden image builder β Stage 1 installs Windows 11 from ISO via Autounattend.xml (unattended, UEFI GPT, VirtIO drivers, TPM bypass, OpenSSH, auto-login), Stage 2 provisions dependencies via SSH (Python 3, PyAutoGUI, uiautomation, WinFsp + VirtIO-FS, agent scripts, scheduled task, system hardening)dev-docs/windows-ci-guide.md): GitHub Actions workflow YAML with explicit KVM/runner limitations, self-hosted runner setup, cloud nested virtualization matrix, golden image caching strategies, troubleshootingexamples/windows-calculator.json): Basic test exercising Calculator app interaction in a QEMU/KVM VMNew files
src/init_windows.rswindows/Autounattend.xmlwindows/provision.ps1dev-docs/windows-ci-guide.mdexamples/windows-calculator.jsonModified files
src/cli.rsInitWindowssubcommandsrc/main.rsmod init_windows+ dispatchsrc/warnings.rswarn_init_windows_resources()src/preflight.rsdesktest doctordev-docs/windows-support-plan.mdCLAUDE.md,README.md,docs/ci.md,docs/macos-support.md,examples/README.md,skills/desktest-skill.mdTest plan
cargo buildcompiles cleanly (verified)desktest --helpshowsinit-windowssubcommanddesktest init-windows --helpshows all options (windows-iso, virtio-iso, output, disk-size, ram, cpus)desktest doctorshows Windows VM status linedesktest validate examples/windows-calculator.jsonpassesinit-windowson a Linux host with KVM (requires Windows ISO + VirtIO ISO)π€ Generated with Claude Code