refactor(config): Update VMX path from CI-WinBuild to WinBuild2025

Replace all references to CI-WinBuild.vmx with WinBuild2025.vmx.
Update template path: F:\CI\Templates\WinBuild\ → F:\CI\Templates\WinBuild2025\

Files affected:
- runner/config.yaml: GITEA_CI_TEMPLATE_PATH env var
- docs: HOST-SETUP.md, WINDOWS-TEMPLATE-SETUP.md, TEST-PLAN, RUNBOOK
- scripts: Measure-CIBenchmark, Set-TemplateSharedFolders, Test-NsinnounpBuild
- TODO.md, Setup-Host.ps1, README.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Simone
2026-05-10 20:46:36 +02:00
parent a5719f2ac6
commit 914072fdd8
13 changed files with 124 additions and 387 deletions
+90 -89
View File
@@ -7,21 +7,21 @@ Organized by sprint area with pre-requisites, test steps, and pass/fail criteria
## Overview
| Area | Items | Status | Baseline |
|------|-------|--------|----------|
| **Sprint 2** (Reliability) | 2.1/2.2/2.3/2.5 | ✓ Done | IP allocation, orphaned VM cleanup, retention policy, snapshot versioning |
| **Sprint 3** (Observability) | 4.1/4.3/4.4 | ✓ Done | JSONL logging, disk space alerts, runbook documentation |
| **Sprint 4-6** (Quality/Perf) | 1.4/3.1/3.6/5.2/5.3/5.4 | Done | IP regex validation, shared cache, benchmarking, _Common.psm1 module, PSScriptAnalyzer |
| **Sprint 7** (Testing) | 5.1 | ✓ Done | Pester unit tests with fake vmrun |
| **§1.6** (Docs) | Threat model | ✓ Done | BEST-PRACTICES.md security feature trade-offs |
| **§3.2** (Perf) | 7-Zip compression | ✓ Done | Multi-threaded artifact compression with fallback |
| Area | Items | Status | Baseline |
| ----------------------------- | ----------------------- | -------- | -------------------------------------------------------------------------------------- |
| **Sprint 2** (Reliability) | 2.1/2.2/2.3/2.5 | [x] Done | IP allocation, orphaned VM cleanup, retention policy, snapshot versioning |
| **Sprint 3** (Observability) | 4.1/4.3/4.4 | [x] Done | JSONL logging, disk space alerts, runbook documentation |
| **Sprint 4-6** (Quality/Perf) | 1.4/3.1/3.6/5.2/5.3/5.4 | [x] Done | IP regex validation, shared cache, benchmarking, _Common.psm1 module, PSScriptAnalyzer |
| **Sprint 7** (Testing) | 5.1 | [x] Done | Pester unit tests with fake vmrun |
| **§1.6** (Docs) | Threat model | [x] Done | BEST-PRACTICES.md security feature trade-offs |
| **§3.2** (Perf) | 7-Zip compression | [x] Done | Multi-threaded artifact compression with fallback |
---
## Pre-Test Checklist
- [ ] Host Windows 11 with VMware Workstation 17+
- [ ] Template VM `F:\CI\Templates\WinBuild\CI-WinBuild.vmx` exists + BaseClean snapshot present
- [x] Host Windows 11 with VMware Workstation 17+
- [ ] Template VM `F:\CI\Templates\WinBuild2025\WinBuild2025.vmx` exists + BaseClean snapshot present
- [ ] `F:\CI\` directory structure intact (BuildVMs, Artifacts, Logs, Cache, State)
- [ ] act_runner service running (`Get-Service act_runner | Select Status`)
- [ ] Gitea available at `http://10.10.20.11:3100` or `https://gitea.emulab.it`
@@ -70,10 +70,10 @@ Get-ChildItem F:\CI\State\ip-leases\
```
**Pass Criteria**:
- All 4 jobs complete successfully
- No WinRM "connection to wrong VM" errors
- Each job receives unique IP
- Leases cleaned up after completion
- [x] All 4 jobs complete successfully
- [x] No WinRM "connection to wrong VM" errors
- [x] Each job receives unique IP
- [x] Leases cleaned up after completion
---
@@ -110,10 +110,10 @@ Test-Path $orphanDir
```
**Pass Criteria**:
- Scheduled task runs without error
- Orphaned VM detected and removed
- Recent clones (< 4 hours old) preserved
- Event log shows cleanup action
- [x] Scheduled task runs without error
- [x] Orphaned VM detected and removed
- [x] Recent clones (< 4 hours old) preserved
- [x] Event log shows cleanup action
---
@@ -156,10 +156,10 @@ if ($diskFree -lt 50) {
```
**Pass Criteria**:
- Artifacts older than 30 days removed
- Recent artifacts preserved
- Aggressive (7-day) cleanup if free space < 50 GB
- Event log entry created for cleanup action
- [x] Artifacts older than 30 days removed
- [x] Recent artifacts preserved
- [x] Aggressive (7-day) cleanup if free space < 50 GB
- [x] Event log entry created for cleanup action
---
@@ -184,12 +184,12 @@ to support rollback during template refresh.
# (Simulate template refresh scenario)
$snapName = "BaseClean_$(Get-Date -Format yyyyMMdd)"
& 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe' -T ws snapshot `
'F:\CI\Templates\WinBuild\CI-WinBuild.vmx' $snapName
'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx' $snapName
# Expected: Success, snapshot created
# 3. Verify old and new snapshots coexist
& 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe' -T ws listSnapshots `
'F:\CI\Templates\WinBuild\CI-WinBuild.vmx'
'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx'
# Expected: Output shows both BaseClean (old) and BaseClean_YYYYMMDD (new)
# 4. Update config to use new snapshot
@@ -202,10 +202,10 @@ $snapName = "BaseClean_$(Get-Date -Format yyyyMMdd)"
```
**Pass Criteria**:
- Multiple dated snapshots can exist simultaneously
- Jobs respect GITEA_CI_SNAPSHOT_NAME env var
- Default fallback to `BaseClean` if env var not set
- Rollback possible by reverting config to old snapshot name
- [x] Multiple dated snapshots can exist simultaneously
- [x] Jobs respect GITEA_CI_SNAPSHOT_NAME env var
- [x] Default fallback to `BaseClean` if env var not set
- [x] Rollback possible by reverting config to old snapshot name
---
@@ -246,11 +246,11 @@ Write-Host "Phases captured: $phases"
```
**Pass Criteria**:
- JSONL file created alongside text transcript
- Each phase emits valid JSON event
- Timestamps are ISO format (parseable)
- Job ID correctly recorded in events
- Status values are consistent (success/failure/started)
- [x] JSONL file created alongside text transcript
- [x] Each phase emits valid JSON event
- [x] Timestamps are ISO format (parseable)
- [x] Job ID correctly recorded in events
- [x] Status values are consistent (success/failure/started)
---
@@ -285,11 +285,11 @@ Get-EventLog -LogName Application -Source 'CI-DiskSpace' -Newest 5 | Select Time
```
**Pass Criteria**:
- Scheduled task runs without error
- Alert triggered if F: free < 50 GB
- Event log entry (ID 1003 for warning, 1004+ for error) created
- Webhook POST succeeds if configured
- No alert if F: free > 50 GB
- [x] Scheduled task runs without error
- [x] Alert triggered if F: free < 50 GB
- [x] Event log entry (ID 1003 for warning, 1004+ for error) created
- [x] Webhook POST succeeds if configured
- [x] No alert if F: free > 50 GB
---
@@ -323,10 +323,10 @@ Get-ChildItem 'N:\Code\Workspace\Local-CI-CD-System\docs\' | Where Name -Match '
```
**Pass Criteria**:
- Runbook file exists and is readable
- All diagnostic commands execute without error
- At least 3 incident types documented with clear symptom→triage→fix flow
- External references (log paths, service names) accurate and tested
- [x] Runbook file exists and is readable
- [x] All diagnostic commands execute without error
- [x] At least 3 incident types documented with clear symptom→triage→fix flow
- [x] External references (log paths, service names) accurate and tested
---
@@ -348,7 +348,7 @@ instead of loose pattern.
```powershell
# 1. Test valid IP in script parameter binding
& 'N:\Code\Workspace\Local-CI-CD-System\scripts\Wait-VMReady.ps1' `
-VMPath 'F:\CI\Templates\WinBuild\CI-WinBuild.vmx' `
-VMPath 'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx' `
-IPAddress '192.168.79.101' `
-VmrunPath 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe' `
-TimeoutSeconds 5 `
@@ -357,7 +357,7 @@ instead of loose pattern.
# 2. Test invalid IPs (should fail parameter validation)
& 'N:\Code\Workspace\Local-CI-CD-System\scripts\Wait-VMReady.ps1' `
-VMPath 'F:\CI\Templates\WinBuild\CI-WinBuild.vmx' `
-VMPath 'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx' `
-IPAddress '999.999.999.999' `
-VmrunPath 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe'
# Expected: Error message like "Cannot validate argument on parameter 'IPAddress'"
@@ -366,7 +366,7 @@ instead of loose pattern.
@('0.0.0.0', '255.255.255.255', '192.168.1.1', '10.0.0.256') | ForEach-Object {
try {
& 'N:\Code\Workspace\Local-CI-CD-System\scripts\Wait-VMReady.ps1' `
-VMPath 'F:\CI\Templates\WinBuild\CI-WinBuild.vmx' `
-VMPath 'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx' `
-IPAddress $_ `
-VmrunPath 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe' `
-TimeoutSeconds 1 `
@@ -380,10 +380,10 @@ instead of loose pattern.
```
**Pass Criteria**:
- Valid IPs (0-255 per octet) accepted
- Invalid IPs (256+, non-numeric, malformed) rejected before script logic
- Error message clear ("Cannot validate argument")
- All 4 scripts enforce same pattern
- [x] Valid IPs (0-255 per octet) accepted
- [x] Invalid IPs (256+, non-numeric, malformed) rejected before script logic
- [x] Error message clear ("Cannot validate argument")
- [x] All 4 scripts enforce same pattern
---
@@ -400,7 +400,7 @@ mounted as VMware shared folders in template, available at `\\vmware-host\Shared
```powershell
# 1. Verify shared folder configuration exists in template VMX
$vmxPath = 'F:\CI\Templates\WinBuild\CI-WinBuild.vmx'
$vmxPath = 'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx'
$vmx = Get-Content $vmxPath
$vmx | Select-String 'sharedFolder' | Select -First 3
# Expected: Lines like "sharedFolder0 = ...", "sharedFolder1 = ..."
@@ -414,7 +414,7 @@ Copy-Item "$vmxPath" (Join-Path $testClone 'test.vmx') -Force
$vmx = Get-Content (Join-Path $testClone 'test.vmx')
$vmx | Select-String -Pattern 'sharedFolder\d+' | ForEach-Object {
if ($_ -match 'nuget-cache|pip-cache') {
Write-Host " Cache folder found: $_"
Write-Host "[x] Cache folder found: $_"
}
}
# Expected: Both nuget-cache and pip-cache in VMX
@@ -432,11 +432,11 @@ $vmx | Select-String -Pattern 'sharedFolder\d+' | ForEach-Object {
```
**Pass Criteria**:
- VMX contains sharedFolder entries for NuGet and pip
- `-UseSharedCache` flag accepted without error
- Build logs show NUGET_PACKAGES/PIP_CACHE_DIR env vars set
- Cache directories persist across builds (not recreated)
- Performance improvement visible on second build (packages already cached)
- [x] VMX contains sharedFolder entries for NuGet and pip
- [x] `-UseSharedCache` flag accepted without error
- [x] Build logs show NUGET_PACKAGES/PIP_CACHE_DIR env vars set
- [x] Cache directories persist across builds (not recreated)
- [x] Performance improvement visible on second build (packages already cached)
---
@@ -453,7 +453,7 @@ pipeline, outputs JSONL for performance tracking.
```powershell
# 1. Run baseline benchmark (5 iterations for quick turnaround)
& 'N:\Code\Workspace\Local-CI-CD-System\scripts\Measure-CIBenchmark.ps1' `
-TemplatePath 'F:\CI\Templates\WinBuild\CI-WinBuild.vmx' `
-TemplatePath 'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx' `
-SnapshotName 'BaseClean' `
-CloneBaseDir 'F:\CI\BuildVMs\' `
-Iterations 5 `
@@ -477,11 +477,11 @@ Write-Host "Clone phase: avg=${avg}ms, min=${min}ms, max=${max}ms"
```
**Pass Criteria**:
- Script completes N iterations without error
- JSONL output created with correct structure
- Five phases present (clone, start, ip, winrm, destroy)
- Durations reasonable (clone 1-5s, start 2-5s, IP <5s, WinRM 1-3s, destroy <2s)
- Variance visible across iterations (natural fluctuation)
- [x] Script completes N iterations without error
- [x] JSONL output created with correct structure
- [x] Five phases present (clone, start, ip, winrm, destroy)
- [x] Durations reasonable (clone 1-5s, start 2-5s, IP <5s, WinRM 1-3s, destroy <2s)
- [x] Variance visible across iterations (natural fluctuation)
---
@@ -514,7 +514,7 @@ $sessionOpt | Select SkipCACheck, SkipCNCheck, SkipRevocationCheck
try {
Resolve-VmrunPath -VmrunPath 'C:\DoesNotExist\vmrun.exe'
} catch {
Write-Host " Correctly threw: $_"
Write-Host "[x] Correctly threw: $_"
}
# 4. Test Invoke-Vmrun with fake vmrun.cmd
@@ -537,11 +537,11 @@ Get-ChildItem 'N:\Code\Workspace\Local-CI-CD-System\scripts\*.ps1' -Exclude '_Co
```
**Pass Criteria**:
- _Common.psm1 exports 3 functions
- Functions work in isolation (parameters accepted, errors thrown appropriately)
- All production scripts import _Common
- PSScriptAnalyzer finds 0 critical violations
- Uniform vmrun invocation via Invoke-Vmrun (no direct `&vmrun` calls)
- [x] _Common.psm1 exports 3 functions
- [x] Functions work in isolation (parameters accepted, errors thrown appropriately)
- [x] All production scripts import _Common
- [x] PSScriptAnalyzer finds 0 critical violations
- [x] Uniform vmrun invocation via Invoke-Vmrun (no direct `&vmrun` calls)
---
@@ -590,12 +590,12 @@ Invoke-Pester -Path 'N:\Code\Workspace\Local-CI-CD-System\tests\' `
```
**Pass Criteria**:
- All 4 test files execute without compilation errors
- Total passed: ≥20 tests
- Total failed: 0 (all pass)
- Test duration: <30 seconds (fast, no VM overhead)
- No temp files left behind after tests complete
- Fake vmrun behavior matches real vmrun for tested scenarios
- [x] All 4 test files execute without compilation errors
- [x] Total passed: ≥20 tests
- [x] Total failed: 0 (all pass)
- [x] Test duration: <30 seconds (fast, no VM overhead)
- [x] No temp files left behind after tests complete
- [x] Fake vmrun behavior matches real vmrun for tested scenarios
---
@@ -618,7 +618,7 @@ $bp | Select-String -Pattern '2\.1.*Threat Model' -Context 1, 50 | Select -First
# 2. Spot-check content structure
$sections = @('Current state', 'Acceptable', 'Breaking', 'Mitigations')
$sections | ForEach-Object {
if ($bp -match $_) { Write-Host " Section: $_" }
if ($bp -match $_) { Write-Host "[x] Section: $_" }
else { Write-Host "✗ Missing: $_" }
}
@@ -633,12 +633,12 @@ $bp | Select-String -Pattern 'Feature.*Disabled.*Why.*Cost' -Context 0, 10
```
**Pass Criteria**:
- §2.1 section present in BEST-PRACTICES.md
- Explains why features disabled (AV overhead, firewall complexity, UAC elevation)
- Documents acceptable conditions (isolated lab, trusted code)
- Documents breaking conditions (shared host, LAN exposure)
- Provides step-by-step mitigations (code examples) if conditions change
- References existing features (HGFS, WinRM HTTPS) that work with protections
- [x] §2.1 section present in BEST-PRACTICES.md
- [x] Explains why features disabled (AV overhead, firewall complexity, UAC elevation)
- [x] Documents acceptable conditions (isolated lab, trusted code)
- [x] Documents breaking conditions (shared host, LAN exposure)
- [x] Provides step-by-step mitigations (code examples) if conditions change
- [x] References existing features (HGFS, WinRM HTTPS) that work with protections
---
@@ -696,13 +696,13 @@ if (Test-Path 'C:\Program Files\7-Zip\7z.exe') {
```
**Pass Criteria**:
- 7-Zip code path detects `C:\Program Files\7-Zip\7z.exe` correctly
- Falls back to Compress-Archive if 7-Zip missing
- Both compression paths produce valid ZIP files
- Extraction succeeds without corruption
- Build logs clearly show which compression method used
- Multi-threaded 7-Zip is faster than single-threaded Compress-Archive (when installed)
- No breaking changes (fallback ensures zero downtime before 7-Zip added to template)
- [x] 7-Zip code path detects `C:\Program Files\7-Zip\7z.exe` correctly
- [x] Falls back to Compress-Archive if 7-Zip missing
- [x] Both compression paths produce valid ZIP files
- [x] Extraction succeeds without corruption
- [x] Build logs clearly show which compression method used
- [x] Multi-threaded 7-Zip is faster than single-threaded Compress-Archive (when installed)
- [x] No breaking changes (fallback ensures zero downtime before 7-Zip added to template)
---
@@ -739,7 +739,7 @@ $testGroups | ForEach-Object {
Write-Host "━━━ Test: $($_.Name) ━━━"
try {
Invoke-Expression $_.Cmd
Write-Host " PASSED" -ForegroundColor Green
Write-Host "[x] PASSED" -ForegroundColor Green
} catch {
Write-Host "✗ FAILED: $_" -ForegroundColor Red
}
@@ -780,3 +780,4 @@ After validating new features, run one full end-to-end build to ensure nothing b
# Expected: Build completes successfully, artifact created, JSONL log present, no errors
```