feat(deploy-win): cache the patched ISO, skip repack when inputs unchanged

The ISO repack (extract + xorriso, ~minutes) ran on every deploy. Cache it
per VM dir: store an inputs key (base ISO size+mtime + rendered
autounattend.xml + post-install.ps1) in a `.iso.inputs` sidecar next to
install-noprompt.iso. Step 4 skips the repack when the patched ISO and a
matching sidecar already exist, and re-patches automatically when the base
ISO or either answer file changes.
This commit is contained in:
2026-06-08 23:53:18 +02:00
parent 6626b25a52
commit a0497ffa4e
2 changed files with 74 additions and 6 deletions
+30 -6
View File
@@ -848,6 +848,19 @@ def _sha256_file(path: Path) -> str:
return h.hexdigest().upper()
def _patched_iso_inputs_key(
base_iso: Path, autounattend_xml: str, post_install_ps1: str
) -> str:
"""Cache key for a patched ISO — changes if the base ISO or answer files do."""
st = base_iso.stat()
h = hashlib.sha256()
h.update(f"{base_iso.name}|{st.st_size}|{int(st.st_mtime)}\n".encode())
h.update(autounattend_xml.encode("utf-8"))
h.update(b"\x00")
h.update(post_install_ps1.encode("utf-8"))
return h.hexdigest()
def _build_seed_iso(staging_dir: Path, iso_path: Path) -> None:
tool = shutil.which("genisoimage") or shutil.which("mkisofs")
if not tool:
@@ -2219,13 +2232,24 @@ def template_deploy_win(
# ── Step 4: patch ISO (inject answer files + no-prompt boot) ───────────────
_deploy_step("Step 4: patch ISO (inject autounattend + no-prompt boot)", 4, start_from_step)
if start_from_step <= 4:
win_iso_patch.patch_iso(
base_iso,
autounattend_xml=autounattend_xml,
post_install_ps1=post_install_ps1,
out_iso=patched_iso,
work_dir=vm_dir,
key = _patched_iso_inputs_key(base_iso, autounattend_xml, post_install_ps1)
sidecar = patched_iso.with_suffix(patched_iso.suffix + ".inputs")
cached = (
patched_iso.is_file()
and sidecar.is_file()
and sidecar.read_text(encoding="utf-8").strip() == key
)
if cached:
click.echo(f" [OK] patched ISO up to date — skipping repack: {patched_iso}")
else:
win_iso_patch.patch_iso(
base_iso,
autounattend_xml=autounattend_xml,
post_install_ps1=post_install_ps1,
out_iso=patched_iso,
work_dir=vm_dir,
)
sidecar.write_text(key, encoding="utf-8")
# ── Step 5: create VMDK ────────────────────────────────────────────────────
_deploy_step("Step 5: create VMDK", 5, start_from_step)