fix: apply all FIX-TODO items (P0/P1/P2)
P0 bugs: - Invoke-CIJob.ps1: skip --depth 1 when $Commit specified (shallow clone + checkout specific commit was silently failing) - Get-BuildArtifacts.ps1: check .Length -eq 0 not rounded sizeKB (false fail on artifacts smaller than 50 bytes) - build-nsis.yml: upgrade upload-artifact v3 -> v4 (v3 deprecated) P0 security: - Remove hardcoded default password CIBuild!ChangeMe2026 from all scripts, README, TODO; prompt Read-Host -AsSecureString at runtime instead - Setup-TemplateVM.ps1: replace `net user $u $p /add` (password in argv / audit log 4688) with New-LocalUser + local ConvertTo-SecureString - Prepare-TemplateSetup.ps1: save and restore WSMan AllowUnencrypted + TrustedHosts in finally block (was permanently mutating host WinRM config) - Setup-TemplateVM.ps1: remove duplicate MaxMemoryPerShellMB (winrm set + Set-Item both setting same value) P1 doc (stale Host-Only / VMnet11 era): - Setup-TemplateVM.ps1: rewrite NETWORK REQUIREMENT block + final steps (system uses VMnet8 NAT permanently, not VMnet11 Host-Only) - Invoke-CIJob.ps1 Phase 1 comment: correct network model - ARCHITECTURE.md: remove Git from toolchain list (not installed); clarify zip-transfer rationale (no PAT in VM, not network isolation) - BEST-PRACTICES.md: rewrite Step 8 as NAT topology verification P1 minor: - Invoke-RemoteBuild.ps1: remove wasted first New-Item (created then immediately removed and recreated) - Wait-VMReady.ps1: remove unused $elapsed; simplify try/catch around native command (exit codes don't throw) - Install-Runner.ps1: add deprecation notice pointing to Setup-Host.ps1 P2 operational: - Add scripts/Cleanup-OrphanedBuildVMs.ps1 with -WhatIf support - Get-BuildArtifacts.ps1 -IncludeLogs: add -Recurse (msbuild logs in subdir) - Add gitea/workflows/lint.yml (PSScriptAnalyzer on .ps1 push/PR) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -24,9 +24,9 @@
|
||||
1. Shut down the VM
|
||||
2. Take snapshot: VM → Snapshot → Take Snapshot → name: BaseClean
|
||||
(VM stays on VMnet8 NAT — internet access is required for builds)
|
||||
3. Store credentials on host:
|
||||
3. Store credentials on host (use the same password chosen during provisioning):
|
||||
New-StoredCredential -Target 'BuildVMGuest' -UserName 'ci_build' `
|
||||
-Password 'CIBuild!ChangeMe2026' -Persist LocalMachine
|
||||
-Password '<your-build-password>' -Persist LocalMachine
|
||||
|
||||
.PARAMETER VMIPAddress
|
||||
IP address of the template VM while it is on NAT (VMnet8).
|
||||
@@ -69,7 +69,7 @@ param(
|
||||
|
||||
[string] $AdminPassword = '',
|
||||
|
||||
[string] $BuildPassword = 'CIBuild!ChangeMe2026',
|
||||
[string] $BuildPassword = '',
|
||||
|
||||
[string] $DotNetSdkVersion = '10.0',
|
||||
|
||||
@@ -81,6 +81,15 @@ $ErrorActionPreference = 'Stop'
|
||||
|
||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
|
||||
# Prompt for BuildPassword if not supplied — never use a hardcoded default.
|
||||
if ($BuildPassword -eq '') {
|
||||
Write-Host "[Prepare] No -BuildPassword supplied. Enter password for the CI build account inside the VM:"
|
||||
$secPwd = Read-Host -Prompt " BuildPassword" -AsSecureString
|
||||
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secPwd)
|
||||
$BuildPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
|
||||
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
|
||||
}
|
||||
|
||||
# ── Build PSCredential ────────────────────────────────────────────────────────
|
||||
if ($AdminPassword -eq '') {
|
||||
Write-Host "[Prepare] Enter administrator credentials for the template VM ($VMIPAddress):"
|
||||
@@ -94,15 +103,19 @@ else {
|
||||
$sessionOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
|
||||
|
||||
# ── Configure HOST-side WinRM client (required for Basic auth over HTTP) ──────
|
||||
# These settings apply to this machine (the host), not the VM.
|
||||
# AllowUnencrypted is needed for HTTP/5985 Basic auth in a lab environment.
|
||||
Write-Host "[Prepare] Configuring host WinRM client for unencrypted Basic auth..."
|
||||
# AllowUnencrypted is needed for HTTP/5985 Basic auth. We save the prior value
|
||||
# and restore it in the finally block so this script doesn't permanently change
|
||||
# the host security posture.
|
||||
Write-Host "[Prepare] Configuring host WinRM client for unencrypted Basic auth (will be restored on exit)..."
|
||||
$prevAllowUnencrypted = $null
|
||||
$prevTrustedHosts = $null
|
||||
try {
|
||||
$prevAllowUnencrypted = (Get-Item WSMan:\localhost\Client\AllowUnencrypted -ErrorAction Stop).Value
|
||||
$prevTrustedHosts = (Get-Item WSMan:\localhost\Client\TrustedHosts -ErrorAction Stop).Value
|
||||
Set-Item WSMan:\localhost\Client\AllowUnencrypted $true -Force -ErrorAction Stop
|
||||
# Add VM IP to TrustedHosts if not already present
|
||||
$currentTrusted = (Get-Item WSMan:\localhost\Client\TrustedHosts).Value
|
||||
if ($currentTrusted -ne '*' -and $currentTrusted -notlike "*$VMIPAddress*") {
|
||||
$newTrusted = if ($currentTrusted -eq '') { $VMIPAddress } else { "$currentTrusted,$VMIPAddress" }
|
||||
if ($prevTrustedHosts -ne '*' -and $prevTrustedHosts -notlike "*$VMIPAddress*") {
|
||||
$newTrusted = if ($prevTrustedHosts -eq '') { $VMIPAddress } else { "$prevTrustedHosts,$VMIPAddress" }
|
||||
Set-Item WSMan:\localhost\Client\TrustedHosts -Value $newTrusted -Force -ErrorAction Stop
|
||||
}
|
||||
Write-Host "[Prepare] Host WinRM client configured."
|
||||
@@ -230,7 +243,7 @@ try {
|
||||
Write-Host " 3. Store CI credentials on this HOST:"
|
||||
Write-Host " (run in elevated PowerShell with CredentialManager module)"
|
||||
Write-Host " New-StoredCredential -Target 'BuildVMGuest' ``"
|
||||
Write-Host " -UserName 'ci_build' -Password '$BuildPassword' ``"
|
||||
Write-Host " -UserName 'ci_build' -Password '<your-build-password>' ``"
|
||||
Write-Host " -Persist LocalMachine"
|
||||
Write-Host ""
|
||||
Write-Host " 4. Verify runner online in Gitea: http://10.10.20.11:3100"
|
||||
@@ -239,4 +252,13 @@ try {
|
||||
}
|
||||
finally {
|
||||
Remove-PSSession $session -ErrorAction SilentlyContinue
|
||||
|
||||
# Restore host WinRM client settings to their original values
|
||||
if ($null -ne $prevAllowUnencrypted) {
|
||||
Set-Item WSMan:\localhost\Client\AllowUnencrypted $prevAllowUnencrypted -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
if ($null -ne $prevTrustedHosts) {
|
||||
Set-Item WSMan:\localhost\Client\TrustedHosts -Value $prevTrustedHosts -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
Write-Host "[Prepare] Host WinRM client settings restored."
|
||||
}
|
||||
|
||||
@@ -22,18 +22,17 @@
|
||||
╔══════════════════════════════════════════════════════════════════════╗
|
||||
║ NETWORK REQUIREMENT DURING SETUP ║
|
||||
║ The VM must have internet access while this script runs so it can ║
|
||||
║ download Windows Updates and tool installers. Configure the VM NIC ║
|
||||
║ to VMnet8 (NAT) before running setup, then switch back to VMnet11 ║
|
||||
║ (Host-Only) BEFORE taking the BaseClean snapshot. ║
|
||||
║ download Windows Updates and tool installers. The VM NIC must be ║
|
||||
║ set to VMnet8 (NAT) — keep it on NAT permanently (builds use NAT ║
|
||||
║ for pip/nuget downloads at runtime). ║
|
||||
╚══════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
After this script completes:
|
||||
1. Switch VM NIC from VMnet8 (NAT) → VMnet11 (Host-Only) in VMware
|
||||
Workstation: VM → Settings → Network Adapter → Custom: VMnet11
|
||||
2. Shut down the VM (Start → Shut down)
|
||||
3. In VMware Workstation: VM → Snapshot → Take Snapshot
|
||||
1. Shut down the VM (Start → Shut down)
|
||||
The VM stays on VMnet8 (NAT) — internet access is required for builds.
|
||||
2. In VMware Workstation: VM → Snapshot → Take Snapshot
|
||||
Name it exactly: BaseClean
|
||||
4. Power off the VM and leave it powered off permanently
|
||||
3. Power off the VM and leave it powered off permanently
|
||||
|
||||
.PARAMETER SkipWindowsUpdate
|
||||
Skip the Windows Update step (useful if updates were already applied).
|
||||
@@ -50,9 +49,10 @@ param(
|
||||
[string] $BuildUsername = 'ci_build',
|
||||
|
||||
# Password for the build account.
|
||||
# IMPORTANT: Change this to a strong password and store it in
|
||||
# Windows Credential Manager on the HOST as target "BuildVMGuest".
|
||||
[string] $BuildPassword = 'CIBuild!ChangeMe2026',
|
||||
# Must be supplied by the caller (Prepare-TemplateSetup.ps1 prompts interactively).
|
||||
# Store the same password in Windows Credential Manager on the HOST as target "BuildVMGuest".
|
||||
[Parameter(Mandatory)]
|
||||
[string] $BuildPassword,
|
||||
|
||||
# .NET SDK channel to install (should match the host SDK version)
|
||||
[string] $DotNetSdkVersion = '10.0',
|
||||
@@ -187,11 +187,9 @@ winrm set winrm/config/service '@{AllowUnencrypted="true"}' | Out-Null
|
||||
winrm set winrm/config/service/auth '@{Basic="true"}' | Out-Null
|
||||
|
||||
# Increase shell memory and timeout limits for long builds
|
||||
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="2048"}' | Out-Null
|
||||
winrm set winrm/config/winrs '@{MaxProcessesPerShell="25"}' | Out-Null
|
||||
|
||||
Set-Item WSMan:\localhost\Shell\MaxMemoryPerShellMB 2048 -Force 3>$null
|
||||
Set-Item WSMan:\localhost\Shell\IdleTimeOut 7200000 -Force 3>$null # 2 hours
|
||||
Set-Item WSMan:\localhost\Shell\MaxMemoryPerShellMB 2048 -Force 3>$null
|
||||
Set-Item WSMan:\localhost\Shell\IdleTimeOut 7200000 -Force 3>$null # 2 hours
|
||||
|
||||
# Ensure WinRM starts automatically
|
||||
Set-Service -Name WinRM -StartupType Automatic 3>$null
|
||||
@@ -202,9 +200,10 @@ Write-Host "WinRM configured."
|
||||
# ── Step 2: Firewall ──────────────────────────────────────────────────────────
|
||||
Write-Step "Disabling Windows Firewall (all profiles) — isolated lab VM"
|
||||
|
||||
# Disable all firewall profiles entirely. This VM lives on a Host-Only network
|
||||
# (VMnet11) with no external exposure, so full disable is acceptable and avoids
|
||||
# any rule-order or profile-classification issues that would block WinRM/ICMP.
|
||||
# Disable all firewall profiles entirely. This VM lives on VMnet8 NAT behind
|
||||
# the VMware NAT gateway with no inbound exposure from outside the host, so
|
||||
# full disable is acceptable and avoids profile-classification issues blocking
|
||||
# WinRM/ICMP from the host.
|
||||
Set-NetFirewallProfile -Profile Domain,Private,Public -Enabled False
|
||||
Write-Host "Windows Firewall disabled on all profiles."
|
||||
|
||||
@@ -216,11 +215,16 @@ if ($existingUser) {
|
||||
Write-Host "User '$BuildUsername' already exists — skipping creation."
|
||||
}
|
||||
else {
|
||||
# Use net user instead of New-LocalUser: the LocalAccounts cmdlets have a known
|
||||
# bug where SecureString deserialized over WinRM causes InvalidPasswordException.
|
||||
$netResult = & net user $BuildUsername $BuildPassword /add /y 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Failed to create user '$BuildUsername': $netResult"
|
||||
# Convert to SecureString locally (inside the VM session) to avoid exposing
|
||||
# the password as a process argument visible in audit log event 4688.
|
||||
$secPwd = ConvertTo-SecureString $BuildPassword -AsPlainText -Force
|
||||
try {
|
||||
New-LocalUser -Name $BuildUsername -Password $secPwd `
|
||||
-PasswordNeverExpires -Description 'CI build account' `
|
||||
-ErrorAction Stop | Out-Null
|
||||
}
|
||||
catch {
|
||||
throw "Failed to create user '$BuildUsername': $_"
|
||||
}
|
||||
Write-Host "User '$BuildUsername' created."
|
||||
}
|
||||
@@ -639,21 +643,17 @@ Write-Host "============================================================" -Foreg
|
||||
Write-Host ""
|
||||
Write-Host " MANDATORY NEXT STEPS:"
|
||||
Write-Host ""
|
||||
Write-Host " 1. SWITCH NIC TO HOST-ONLY (critical before snapshot!):"
|
||||
Write-Host " VMware Workstation -> VM -> Settings -> Network Adapter"
|
||||
Write-Host " Change from: VMnet8 (NAT)"
|
||||
Write-Host " Change to: Custom: VMnet11"
|
||||
Write-Host " 1. Shut down this VM: Start -> Shut down"
|
||||
Write-Host " (Keep NIC on VMnet8 NAT — internet is required for builds)"
|
||||
Write-Host ""
|
||||
Write-Host " 2. Shut down this VM: Start -> Shut down"
|
||||
Write-Host ""
|
||||
Write-Host " 3. Take snapshot in VMware Workstation:"
|
||||
Write-Host " 2. Take snapshot in VMware Workstation:"
|
||||
Write-Host " VM -> Snapshot -> Take Snapshot"
|
||||
Write-Host " Name it EXACTLY: BaseClean"
|
||||
Write-Host ""
|
||||
Write-Host " 4. Leave VM powered off permanently."
|
||||
Write-Host " 3. Leave VM powered off permanently."
|
||||
Write-Host ""
|
||||
Write-Host " 5. On the HOST - store credentials in Windows Credential Manager:"
|
||||
Write-Host " 4. On the HOST - store credentials in Windows Credential Manager:"
|
||||
Write-Host " New-StoredCredential -Target 'BuildVMGuest' -UserName '$BuildUsername' ``"
|
||||
Write-Host " -Password '$BuildPassword' -Persist LocalMachine"
|
||||
Write-Host " -Password '<your-build-password>' -Persist LocalMachine"
|
||||
Write-Host " (Run in an elevated PowerShell with CredentialManager module)"
|
||||
Write-Host ""
|
||||
|
||||
Reference in New Issue
Block a user