f373c0c24b
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>
124 lines
4.4 KiB
PowerShell
124 lines
4.4 KiB
PowerShell
#Requires -Version 5.1
|
|
<#
|
|
.SYNOPSIS
|
|
Copies build artifacts from an ephemeral VM to the host artifact directory.
|
|
|
|
.DESCRIPTION
|
|
Opens a WinRM session to the build VM and uses Copy-Item -FromSession
|
|
to transfer the artifact archive and optional log files.
|
|
Validates that at least one file was successfully transferred.
|
|
Throws on failure so the caller's try/finally can clean up the VM.
|
|
|
|
.PARAMETER IPAddress
|
|
IP of the build VM.
|
|
|
|
.PARAMETER Credential
|
|
PSCredential for the guest build user.
|
|
|
|
.PARAMETER GuestArtifactPath
|
|
Full path to the artifact file or directory inside the VM.
|
|
Example: C:\CI\output\artifacts.zip
|
|
|
|
.PARAMETER HostArtifactDir
|
|
Directory on the host where artifacts will be stored.
|
|
The directory is created if it does not exist.
|
|
Example: F:\CI\Artifacts\run-42
|
|
|
|
.PARAMETER IncludeLogs
|
|
If set, also copies *.log files from the guest work directory
|
|
(C:\CI\build\*.log) alongside the artifact archive.
|
|
|
|
.EXAMPLE
|
|
$cred = Get-Credential
|
|
.\Get-BuildArtifacts.ps1 `
|
|
-IPAddress "192.168.11.101" `
|
|
-Credential $cred `
|
|
-GuestArtifactPath "C:\CI\output\artifacts.zip" `
|
|
-HostArtifactDir "F:\CI\Artifacts\run-42"
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory)]
|
|
[ValidatePattern('^(\d{1,3}\.){3}\d{1,3}$')]
|
|
[string] $IPAddress,
|
|
|
|
[Parameter(Mandatory)]
|
|
[System.Management.Automation.PSCredential] $Credential,
|
|
|
|
[Parameter(Mandatory)]
|
|
[string] $GuestArtifactPath,
|
|
|
|
[Parameter(Mandatory)]
|
|
[string] $HostArtifactDir,
|
|
|
|
[switch] $IncludeLogs
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
# Ensure destination exists on host
|
|
if (-not (Test-Path $HostArtifactDir)) {
|
|
New-Item -ItemType Directory -Path $HostArtifactDir -Force | Out-Null
|
|
Write-Host "[Get-BuildArtifacts] Created host artifact directory: $HostArtifactDir"
|
|
}
|
|
|
|
$sessionOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
|
|
|
|
Write-Host "[Get-BuildArtifacts] Connecting to VM at $IPAddress..."
|
|
$session = New-PSSession `
|
|
-ComputerName $IPAddress `
|
|
-Credential $Credential `
|
|
-SessionOption $sessionOptions `
|
|
-ErrorAction Stop
|
|
|
|
try {
|
|
# ── Verify artifact exists in guest ──────────────────────────────────
|
|
$guestExists = Invoke-Command -Session $session -ScriptBlock {
|
|
param($path)
|
|
Test-Path $path
|
|
} -ArgumentList $GuestArtifactPath
|
|
|
|
if (-not $guestExists) {
|
|
throw "Artifact not found in guest at: $GuestArtifactPath"
|
|
}
|
|
|
|
# ── Copy main artifact ────────────────────────────────────────────────
|
|
$artifactFileName = Split-Path $GuestArtifactPath -Leaf
|
|
$hostDestPath = Join-Path $HostArtifactDir $artifactFileName
|
|
|
|
Write-Host "[Get-BuildArtifacts] Copying $artifactFileName from guest..."
|
|
Copy-Item -Path $GuestArtifactPath -Destination $hostDestPath -FromSession $session -Force
|
|
|
|
# ── Copy logs if requested ────────────────────────────────────────────
|
|
if ($IncludeLogs) {
|
|
$logFiles = Invoke-Command -Session $session -ScriptBlock {
|
|
Get-ChildItem -Path 'C:\CI\build' -Filter '*.log' -Recurse -ErrorAction SilentlyContinue |
|
|
Select-Object -ExpandProperty FullName
|
|
}
|
|
|
|
foreach ($log in $logFiles) {
|
|
$logDest = Join-Path $HostArtifactDir (Split-Path $log -Leaf)
|
|
Write-Host "[Get-BuildArtifacts] Copying log: $(Split-Path $log -Leaf)"
|
|
Copy-Item -Path $log -Destination $logDest -FromSession $session -Force
|
|
}
|
|
}
|
|
|
|
# ── Validate at least the main artifact landed ────────────────────────
|
|
if (-not (Test-Path $hostDestPath)) {
|
|
throw "Artifact was not found at expected host path after copy: $hostDestPath"
|
|
}
|
|
|
|
$fileItem = Get-Item $hostDestPath
|
|
if ($fileItem.Length -eq 0) {
|
|
throw "Artifact file exists but is empty: $hostDestPath"
|
|
}
|
|
$sizeKB = [math]::Round($fileItem.Length / 1KB, 1)
|
|
|
|
Write-Host "[Get-BuildArtifacts] Artifact collected: $hostDestPath ($sizeKB KB)"
|
|
return $hostDestPath
|
|
}
|
|
finally {
|
|
Remove-PSSession $session -ErrorAction SilentlyContinue
|
|
}
|