From bc847ea6d98f6ffa40a68c160defebec4a1d0b2b Mon Sep 17 00:00:00 2001 From: sysadmin Date: Tue, 9 Jun 2026 15:14:48 +0100 Subject: [PATCH] fix(build): discard stale image mounts at startup + ephemeral CI WorkDir A prior aborted build left a DISM image mounted in the fixed WorkDir, locking install.wim and breaking the Stage 2 extract clean-up. Add a Stage 0 that discards any orphaned SilverMetal mounts + loaded hives before recreating the work dirs, and run CI in an ephemeral per-job RUNNER_TEMP WorkDir so concurrent/aborted runs can't collide. Co-Authored-By: Claude Opus 4.8 --- .gitea/workflows/build-iso-windows.yaml | 1 + windows/installer/build.ps1 | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/.gitea/workflows/build-iso-windows.yaml b/.gitea/workflows/build-iso-windows.yaml index 9ca239c..3f3d1c9 100644 --- a/.gitea/workflows/build-iso-windows.yaml +++ b/.gitea/workflows/build-iso-windows.yaml @@ -132,6 +132,7 @@ jobs: run: | .\windows\installer\build.ps1 ` -SourceIso '${{ steps.iso.outputs.path }}' ` + -WorkDir "$env:RUNNER_TEMP\smbuild" ` -OutputIso "$env:RUNNER_TEMP\out\SilverMetal-Enhanced-Windows.iso" - name: Validate baked payload (offline assertions) diff --git a/windows/installer/build.ps1 b/windows/installer/build.ps1 index ddf78a1..b35922c 100644 --- a/windows/installer/build.ps1 +++ b/windows/installer/build.ps1 @@ -53,6 +53,23 @@ $m = Get-Content $Manifest -Raw | ConvertFrom-Json $isoRoot = Join-Path $WorkDir 'iso' # writable copy of ISO contents $mount = Join-Path $WorkDir 'mount' # install.wim mount point $bootmnt = Join-Path $WorkDir 'bootmnt' # boot.wim mount point + +# --- 0. Discard stale state from a prior interrupted build ----------------- +# An aborted run can leave a DISM image mounted (locking install.wim/boot.wim) +# or registry hives loaded, which breaks the Stage 2 extract clean-up with +# "the process cannot access the file ... because it is being used by another +# process". Discard anything of ours before (re)creating the work dirs. Match +# by 'silvermetal' so orphans from any prior WorkDir are cleaned too. +Write-Stage 'Stage 0: discard stale SilverMetal image mounts / hives from prior runs' +Get-WindowsImage -Mounted -ErrorAction SilentlyContinue | + Where-Object { $_.ImagePath -match 'silvermetal' -or $_.MountPath -match 'silvermetal' } | + ForEach-Object { + Write-Host " discarding stale mount: $($_.MountPath)" + Dismount-WindowsImage -Path $_.MountPath -Discard -ErrorAction SilentlyContinue | Out-Null + } +foreach ($h in 'SM_BRAND_SW','SM_BRAND_DU','SM_OFFLINE','SM_BOOT') { & reg unload "HKLM\$h" 2>$null | Out-Null } +if (Test-Path $WorkDir) { Remove-Item $WorkDir -Recurse -Force -ErrorAction SilentlyContinue } + $null = New-Item -ItemType Directory -Force -Path $WorkDir,$mount,$bootmnt,(Split-Path $OutputIso) # --- 1. Verify input -------------------------------------------------------