fix(prepare-win): run disk cleanup before the final reboot

Heavy servicing (DISM StartComponentCleanup in the -CleanupOnly step, like
WU finalization) destabilises the running shell session — explorer
crash-loops until the next reboot. Cleanup ran *after* the final reboot, so
the template ended on a crash-looping desktop and the idle check aborted.

Reorder: disk cleanup + autologin re-affirm now run before the final
reboot, making that reboot the last action before the idle check — the
shell comes up against fully-settled components and the snapshot captures a
clean, idle desktop.
This commit is contained in:
2026-06-09 22:00:08 +02:00
parent c1be0f276f
commit d4d349dee2
+12 -6
View File
@@ -807,11 +807,11 @@ Register-ScheduledTask -TaskName 'CI-StaticIp' `
f"[prepare-win] Validation script error:\n{val_result.stderr}", err=True f"[prepare-win] Validation script error:\n{val_result.stderr}", err=True
) )
# Final reboot to flush installation state # Disk cleanup BEFORE the final reboot. Heavy servicing ops (DISM
click.echo("[prepare-win] Final reboot to flush installation state ...") # StartComponentCleanup, WU finalization) destabilise the running shell
_reboot_and_wait(transport, guest_ip, 5986, winrm_timeout) # session — explorer crash-loops until the next reboot — so all such work
# must happen before the final reboot, never after it (otherwise the
# Disk cleanup — runs after final reboot on fully-installed system # template snapshots a crash-looping desktop).
if not skip_cleanup: if not skip_cleanup:
click.echo("[prepare-win] Running post-update disk cleanup (-CleanupOnly) ...") click.echo("[prepare-win] Running post-update disk cleanup (-CleanupOnly) ...")
cleanup_invoke = ( cleanup_invoke = (
@@ -839,7 +839,7 @@ Register-ScheduledTask -TaskName 'CI-StaticIp' `
raise click.ClickException(f"Disk cleanup failed (exit {cleanup_ec}).") raise click.ClickException(f"Disk cleanup failed (exit {cleanup_ec}).")
click.echo("[prepare-win] Post-update cleanup complete.") click.echo("[prepare-win] Post-update cleanup complete.")
# Re-affirm autologin # Re-affirm autologin (registry persists across the reboot below).
click.echo("[prepare-win] Re-affirming autologin registry settings ...") click.echo("[prepare-win] Re-affirming autologin registry settings ...")
transport.run( transport.run(
"$wl = 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon'\n" "$wl = 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon'\n"
@@ -851,6 +851,12 @@ Register-ScheduledTask -TaskName 'CI-StaticIp' `
"}\n" "}\n"
) )
# Final reboot — the LAST action before the idle check, so the shell
# comes up against fully-settled components (no crash loop) and the
# snapshot captures a clean, idle desktop.
click.echo("[prepare-win] Final reboot to flush installation state ...")
_reboot_and_wait(transport, guest_ip, 5986, winrm_timeout)
# Pre-snapshot idle check — abort (no snapshot) if the template is busy. # Pre-snapshot idle check — abort (no snapshot) if the template is busy.
if not skip_idle_check: if not skip_idle_check:
_check_guest_idle( _check_guest_idle(