feat(templates): install ci-static-ip/ci-report-ip via Prepare+Install scripts

Windows (Prepare-WinBuild2025/2022): read ci-static-ip.ps1 from
guest-setup/windows/ on the host, push content over WinRM, register the
CI-StaticIp scheduled task (AtStartup/SYSTEM). Adds StaticIpTask and
StaticIpScript post-setup assertions.

Linux (Install-CIToolchain-Linux2404.sh): embed ci-report-ip.sh and
ci-report-ip.service content inline via heredoc tee, replacing the broken
cp-from-relative-path approach (the script runs inside the VM where the
host-side guest-setup/ directory does not exist).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 00:37:07 +02:00
parent 1bc3ec601c
commit 41a0a113df
3 changed files with 173 additions and 21 deletions
+40 -9
View File
@@ -497,6 +497,33 @@ try {
-Authentication Basic -ErrorAction Stop
}
# ── Install CI-StaticIp scheduled task (ip_pool guestinfo static IP) ────────
# Reads ci-static-ip.ps1 from alongside this script and installs it into the
# guest as C:\CI\ci-static-ip.ps1, then registers the CI-StaticIp task
# (At Startup, SYSTEM) so the guest applies a pre-assigned static IP from
# guestinfo.ip-assignment before WinRM starts on each clone boot.
$staticIpScriptPath = Join-Path $scriptDir 'guest-setup\windows\ci-static-ip.ps1'
if (Test-Path $staticIpScriptPath -PathType Leaf) {
Write-Host "[Prepare] Installing CI-StaticIp scheduled task on guest..."
$staticIpContent = Get-Content -LiteralPath $staticIpScriptPath -Raw
Invoke-Command -Session $session -ScriptBlock {
param([string]$ScriptContent)
Set-Content -LiteralPath 'C:\CI\ci-static-ip.ps1' -Value $ScriptContent `
-Encoding UTF8 -Force
$action = New-ScheduledTaskAction `
-Execute 'powershell.exe' `
-Argument '-NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\CI\ci-static-ip.ps1'
$trigger = New-ScheduledTaskTrigger -AtStartup
$principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' `
-LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName 'CI-StaticIp' -Action $action `
-Trigger $trigger -Principal $principal -Force | Out-Null
} -ArgumentList $staticIpContent
Write-Host "[Prepare] CI-StaticIp task registered." -ForegroundColor Green
} else {
Write-Warning "[Prepare] guest-setup\windows\ci-static-ip.ps1 not found alongside this script — skipping CI-StaticIp task. ip_pool feature will not work for this template."
}
# ── Post-setup remote validation ──────────────────────────────────────────
Write-Host "[Prepare] Running post-setup validation against guest..."
$guestState = Invoke-Command -Session $session -ScriptBlock {
@@ -505,15 +532,17 @@ try {
$env:PATH = [System.Environment]::GetEnvironmentVariable('PATH','Machine') + ';' +
[System.Environment]::GetEnvironmentVariable('PATH','User')
[PSCustomObject]@{
WinRMRunning = (Get-Service WinRM -ErrorAction SilentlyContinue).Status -eq 'Running'
UserExists = [bool](Get-LocalUser -Name $BuildUser -ErrorAction SilentlyContinue)
UserIsAdmin = [bool](& net localgroup Administrators 2>&1 | Select-String -SimpleMatch $BuildUser)
UACDisabled = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' -Name EnableLUA -ErrorAction SilentlyContinue).EnableLUA -eq 0
FirewallOff = -not (Get-NetFirewallProfile | Where-Object Enabled -eq $true)
DotNetVersion = (Get-Command dotnet -ErrorAction SilentlyContinue) | ForEach-Object { (& $_.Source --version 2>&1) }
PythonExists = Test-Path 'C:\Python\python.exe' -PathType Leaf
MSBuildExists = Test-Path $msbuildPath -PathType Leaf
CIDirsPresent = (Test-Path 'C:\CI\build') -and (Test-Path 'C:\CI\output') -and (Test-Path 'C:\CI\scripts')
WinRMRunning = (Get-Service WinRM -ErrorAction SilentlyContinue).Status -eq 'Running'
UserExists = [bool](Get-LocalUser -Name $BuildUser -ErrorAction SilentlyContinue)
UserIsAdmin = [bool](& net localgroup Administrators 2>&1 | Select-String -SimpleMatch $BuildUser)
UACDisabled = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' -Name EnableLUA -ErrorAction SilentlyContinue).EnableLUA -eq 0
FirewallOff = -not (Get-NetFirewallProfile | Where-Object Enabled -eq $true)
DotNetVersion = (Get-Command dotnet -ErrorAction SilentlyContinue) | ForEach-Object { (& $_.Source --version 2>&1) }
PythonExists = Test-Path 'C:\Python\python.exe' -PathType Leaf
MSBuildExists = Test-Path $msbuildPath -PathType Leaf
CIDirsPresent = (Test-Path 'C:\CI\build') -and (Test-Path 'C:\CI\output') -and (Test-Path 'C:\CI\scripts')
StaticIpTask = [bool](Get-ScheduledTask -TaskName 'CI-StaticIp' -ErrorAction SilentlyContinue)
StaticIpScript = Test-Path 'C:\CI\ci-static-ip.ps1' -PathType Leaf
}
} -ArgumentList $BuildUsername
@@ -526,6 +555,8 @@ try {
Assert-Step 'PostSetup' 'guest Python installed' { $guestState.PythonExists }
Assert-Step 'PostSetup' 'guest MSBuild present' { $guestState.MSBuildExists }
Assert-Step 'PostSetup' 'guest C:\CI\{build,output,scripts} present' { $guestState.CIDirsPresent }
Assert-Step 'PostSetup' 'guest CI-StaticIp task registered' { $guestState.StaticIpTask }
Assert-Step 'PostSetup' 'guest C:\CI\ci-static-ip.ps1 present' { $guestState.StaticIpScript }
Write-Host "[Prepare] All post-setup validations passed (.NET $($guestState.DotNetVersion))." -ForegroundColor Green