Files
local-ci-cd-system/scripts/Remove-BuildVM.ps1
T
Simone 552eb628b7 feat(sprint4-6): quality, reliability, perf baseline
Sprint 4 — qualità codice:
- scripts/_Common.psm1: New-CISessionOption, Resolve-VmrunPath, Invoke-Vmrun
- PSScriptAnalyzerSettings.psd1: project-wide PSSA rules (security + formatting)
- Remove-BuildVM.ps1: SupportsShouldProcess (-WhatIf support)
- Invoke-RemoteBuild.ps1, Get-BuildArtifacts.ps1: use New-CISessionOption from module
- New-BuildVM.ps1: use Resolve-VmrunPath + Invoke-Vmrun from module

Sprint 5 — affidabilità:
- Backup-CITemplate.ps1: stop runner, timestamped VMDK backup, prune old, restart
- Watch-RunnerHealth.ps1: auto-restart act_runner, cooldown 3/h, EventLog + webhook
- Register-CIScheduledTasks.ps1: add CI-RunnerHealth task (every 15 min)

Sprint 6 — perf baseline:
- Set-TemplateSharedFolders.ps1: idempotent VMX editor for NuGet/pip shared folders
- Invoke-RemoteBuild.ps1: -UseSharedCache injects NUGET_PACKAGES + PIP_CACHE_DIR in guest
- Measure-CIBenchmark.ps1: times clone/start/IP/WinRM/destroy, appends to benchmark.jsonl

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 20:08:19 +02:00

124 lines
4.7 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#Requires -Version 5.1
<#
.SYNOPSIS
Stops and permanently deletes an ephemeral build VM.
.DESCRIPTION
Performs a graceful shutdown (soft stop) with a timeout fallback to
a hard stop, then uses vmrun deleteVM to remove all VM files.
Finally, removes the clone directory from disk.
This script is designed to be called from a try/finally block so
it always runs, even on build failure.
.PARAMETER VMPath
Full path to the clone VM's .vmx file.
.PARAMETER VmrunPath
Full path to vmrun.exe.
Default: C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe
.PARAMETER GracefulTimeoutSeconds
Seconds to wait for graceful shutdown before forcing power-off.
Default: 15
.EXAMPLE
.\Remove-BuildVM.ps1 -VMPath "F:\CI\BuildVMs\Clone_run-42_20260508_143022\Clone_run-42_20260508_143022.vmx"
#>
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory)]
[string] $VMPath,
[string] $VmrunPath = 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe',
[ValidateRange(5, 60)]
[int] $GracefulTimeoutSeconds = 15
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Continue' # Don't stop on errors — always try next step
$cloneDir = Split-Path $VMPath -Parent
Write-Host "[Remove-BuildVM] Destroying VM: $VMPath"
# ── Step 1: Check if VM exists at all ────────────────────────────────────────
if (-not (Test-Path $VMPath -PathType Leaf)) {
Write-Warning "[Remove-BuildVM] VMX file not found — nothing to remove: $VMPath"
# Still attempt to remove the directory in case of partial clone
if ((Test-Path $cloneDir) -and $PSCmdlet.ShouldProcess($cloneDir, 'Remove partial clone directory')) {
Remove-Item $cloneDir -Recurse -Force -ErrorAction SilentlyContinue
}
return
}
if (-not $PSCmdlet.ShouldProcess($VMPath, 'Stop and delete build VM')) { return }
# ── Step 2: Graceful stop ─────────────────────────────────────────────────────
Write-Host "[Remove-BuildVM] Sending soft stop..."
& $VmrunPath -T ws stop $VMPath soft 2>&1 | Out-Null
$deadline = (Get-Date).AddSeconds($GracefulTimeoutSeconds)
while ((Get-Date) -lt $deadline) {
Start-Sleep -Seconds 2
$stateOutput = & $VmrunPath -T ws getState $VMPath 2>&1
if ($stateOutput -notmatch 'running') {
Write-Host "[Remove-BuildVM] VM stopped gracefully."
break
}
}
# ── Step 3: Force stop if still running ──────────────────────────────────────
$stateOutput = & $VmrunPath -T ws getState $VMPath 2>&1
if ($stateOutput -match 'running') {
Write-Host "[Remove-BuildVM] Graceful stop timed out — forcing hard stop..."
& $VmrunPath -T ws stop $VMPath hard 2>&1 | Out-Null
}
# Poll vmrun list until VMX is gone — vmware-vmx.exe may hold file locks briefly
# after stop. Waiting for the entry to disappear ensures deleteVM won't race the
# process exit.
$vmxNorm = $VMPath.Trim().ToLower()
$releaseDeadline = (Get-Date).AddSeconds(20)
while ((Get-Date) -lt $releaseDeadline) {
$listedVMs = & $VmrunPath -T ws list 2>&1 |
Where-Object { $_ -notmatch '^Total running' } |
ForEach-Object { "$_".Trim().ToLower() }
if ($listedVMs -notcontains $vmxNorm) { break }
Start-Sleep -Seconds 2
}
# ── Step 4: Delete VM via vmrun — retry up to 3× with backoff ────────────────
Write-Host "[Remove-BuildVM] Deleting VM..."
$deleteOutput = ''
$deleteExit = -1
foreach ($delay in @(0, 3, 6)) {
if ($delay -gt 0) {
Write-Host "[Remove-BuildVM] Retrying deleteVM in ${delay}s..."
Start-Sleep -Seconds $delay
}
$deleteOutput = & $VmrunPath -T ws deleteVM $VMPath 2>&1
$deleteExit = $LASTEXITCODE
if ($deleteExit -eq 0) { break }
}
if ($deleteExit -ne 0) {
Write-Warning "[Remove-BuildVM] vmrun deleteVM failed after retries (exit $deleteExit): $deleteOutput"
Write-Warning "[Remove-BuildVM] Will attempt manual directory removal."
}
# ── Step 5: Remove clone directory (catches any leftover files) ───────────────
if (Test-Path $cloneDir) {
Write-Host "[Remove-BuildVM] Removing clone directory: $cloneDir"
Remove-Item $cloneDir -Recurse -Force -ErrorAction SilentlyContinue
if (Test-Path $cloneDir) {
Write-Warning "[Remove-BuildVM] Clone directory could not be fully removed: $cloneDir"
Write-Warning " Manual cleanup required."
} else {
Write-Host "[Remove-BuildVM] Clone directory removed."
}
}
Write-Host "[Remove-BuildVM] VM destruction complete."