Files
local-ci-cd-system/scripts/Get-BuildArtifacts.ps1
T
Simone fee5963a65 feat(linux): update orchestration scripts for dual-OS (Windows/Linux) support
Wait-VMReady.ps1:
- Phase 1: vmrun list + path matching instead of getGuestIPAddress (avoids hang)
- Phase 2/3: WinRM (Windows) or TCP:22 + ssh echo (Linux) based on -Transport param
- -Transport SSH auto-selected by Invoke-CIJob when guestOS=ubuntu-64

Invoke-CIJob.ps1:
- Auto-detect GuestOS from clone VMX guestOS field
- Pass -GuestOS Linux to Wait-VMReady, Invoke-RemoteBuild, Get-BuildArtifacts
- Git clone output streamed line-by-line (fix buffered stdout)

Invoke-RemoteBuild.ps1:
- -GuestOS Linux path: SSH+SCP via _Transport.psm1
- Always uses in-VM git clone for Linux builds

Get-BuildArtifacts.ps1:
- -GuestOS Linux path: scp -r ci_build@<ip>:/opt/ci/output/ to host artifact dir
2026-05-11 18:34:16 +02:00

183 lines
6.5 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('^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$')]
[string] $IPAddress,
[Parameter()]
[System.Management.Automation.PSCredential] $Credential,
[Parameter(Mandatory)]
[string] $GuestArtifactPath,
[Parameter(Mandatory)]
[string] $HostArtifactDir,
[switch] $IncludeLogs,
# Guest OS type — Linux uses SCP instead of WinRM.
[ValidateSet('Windows', 'Linux')]
[string] $GuestOS = 'Windows',
# SSH private key path (used when GuestOS=Linux).
[string] $SshKeyPath = 'F:\CI\keys\ci_linux',
# SSH username (used when GuestOS=Linux).
[string] $SshUser = 'ci_build'
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
Import-Module (Join-Path $PSScriptRoot '_Common.psm1') -Force
if ($GuestOS -eq 'Windows' -and $null -eq $Credential) {
throw "Credential is required when GuestOS is Windows."
}
# ── Linux branch: use scp to transfer artifacts ─────────────────────────────────────────────
if ($GuestOS -eq 'Linux') {
Import-Module (Join-Path $PSScriptRoot '_Transport.psm1') -Force
if (-not (Test-Path $HostArtifactDir)) {
New-Item -ItemType Directory -Path $HostArtifactDir -Force | Out-Null
Write-Host "[Get-BuildArtifacts] Created host artifact directory: $HostArtifactDir"
}
Write-Host "[Get-BuildArtifacts] Transferring artifacts via SCP from $GuestArtifactPath ..."
Copy-SshItem `
-Source "$GuestArtifactPath/." `
-Destination $HostArtifactDir `
-IP $IPAddress `
-User $SshUser `
-KeyPath $SshKeyPath `
-Direction 'FromGuest' `
-Recurse
$transferred = @(Get-ChildItem -Path $HostArtifactDir -Recurse -File -ErrorAction SilentlyContinue)
if ($transferred.Count -eq 0) {
throw "[Get-BuildArtifacts] No files found in $HostArtifactDir after SCP transfer."
}
Write-Host "[Get-BuildArtifacts] $($transferred.Count) file(s) collected from Linux guest."
return
}
# 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-CISessionOption
Write-Host "[Get-BuildArtifacts] Connecting to VM at $IPAddress..."
$session = $null
$attempts = 3
$delay = 10 # seconds between attempts
for ($i = 1; $i -le $attempts; $i++) {
try {
$session = New-PSSession `
-ComputerName $IPAddress `
-Credential $Credential `
-SessionOption $sessionOptions `
-UseSSL `
-Port 5986 `
-Authentication Basic `
-ErrorAction Stop
break
} catch {
if ($i -eq $attempts) { throw }
Write-Warning "[Get-BuildArtifacts] WinRM connect attempt $i/$attempts failed — retrying in ${delay}s... ($_)"
Start-Sleep -Seconds $delay
}
}
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
}