feat: stream build output in real-time + log capture and retention

Invoke-RemoteBuild.ps1:
- Custom build command: replace buffered collect-then-print with
  Write-Host streaming inside Invoke-Command (WinRM forwards Write-Host
  in real-time to the host console)
- Set PYTHONUNBUFFERED=1 in the remote session to prevent Python from
  holding lines in its internal buffer
- Same streaming approach for dotnet restore and dotnet build paths
- Return value is now just int exit code instead of hashtable

Invoke-CIJob.ps1:
- Add -LogDir parameter (default F:\CI\Logs)
- Add -LogRetentionDays parameter (default 30)
- Start-Transcript at job start -> F:\CI\Logs\<JobId>\invoke-ci.log
- Stop-Transcript in finally block (guaranteed execution)
- Auto-purge log directories older than LogRetentionDays after each job
This commit is contained in:
Simone
2026-05-08 23:56:10 +02:00
parent 968f01e398
commit b64d6c2c5d
2 changed files with 60 additions and 23 deletions
+22 -22
View File
@@ -132,13 +132,16 @@ try {
if ($BuildCommand -ne '') {
# ── Custom build command (e.g. python, msbuild, cmake…) ──────────
Write-Host "[Invoke-RemoteBuild] Running build command: $BuildCommand"
$buildResult = Invoke-Command -Session $session -ScriptBlock {
$buildExit = Invoke-Command -Session $session -ScriptBlock {
param($workDir, $cmd, $artifactZip, $artifactSrc)
# Unbuffered Python output — lines appear in real-time instead of being held in buffer
$env:PYTHONUNBUFFERED = '1'
Set-Location $workDir
$output = Invoke-Expression "$cmd 2>&1" | ForEach-Object { "$_" }
$buildExit = $LASTEXITCODE
# Stream each output line via Write-Host — WinRM forwards Write-Host in real-time
& cmd /c "$cmd 2>&1" | ForEach-Object { Write-Host $_ }
$exit = $LASTEXITCODE
if ($buildExit -eq 0) {
if ($exit -eq 0) {
$archiveDir = Split-Path $artifactZip -Parent
if (-not (Test-Path $archiveDir)) {
New-Item -ItemType Directory -Path $archiveDir -Force | Out-Null
@@ -147,38 +150,36 @@ try {
Compress-Archive -Path $srcPath -DestinationPath $artifactZip -Force
}
return @{ ExitCode = $buildExit; Output = ($output -join "`n") }
return $exit
} -ArgumentList $GuestWorkDir, $BuildCommand, $GuestArtifactZip, $GuestArtifactSource
Write-Host $buildResult.Output
if ($buildResult.ExitCode -ne 0) {
throw "Build command failed (exit $($buildResult.ExitCode))"
if ($buildExit -ne 0) {
throw "Build command failed (exit $buildExit)"
}
}
else {
# ── Default: dotnet restore + dotnet build ────────────────────────
Write-Host "[Invoke-RemoteBuild] Running dotnet restore..."
$restoreResult = Invoke-Command -Session $session -ScriptBlock {
$restoreExit = Invoke-Command -Session $session -ScriptBlock {
param($workDir)
Set-Location $workDir
$output = dotnet restore 2>&1
return @{ ExitCode = $LASTEXITCODE; Output = ($output -join "`n") }
dotnet restore 2>&1 | ForEach-Object { Write-Host $_ }
return $LASTEXITCODE
} -ArgumentList $GuestWorkDir
Write-Host $restoreResult.Output
if ($restoreResult.ExitCode -ne 0) {
throw "dotnet restore failed (exit $($restoreResult.ExitCode))"
if ($restoreExit -ne 0) {
throw "dotnet restore failed (exit $restoreExit)"
}
Write-Host "[Invoke-RemoteBuild] Running dotnet build (configuration: $Configuration)..."
$buildResult = Invoke-Command -Session $session -ScriptBlock {
$buildExit = Invoke-Command -Session $session -ScriptBlock {
param($workDir, $config, $artifactZip)
Set-Location $workDir
$outputDir = Join-Path $workDir 'bin\CIOutput'
$output = dotnet build --configuration $config --output $outputDir 2>&1
$buildExit = $LASTEXITCODE
dotnet build --configuration $config --output $outputDir 2>&1 | ForEach-Object { Write-Host $_ }
$exit = $LASTEXITCODE
if ($buildExit -eq 0) {
if ($exit -eq 0) {
$archiveDir = Split-Path $artifactZip -Parent
if (-not (Test-Path $archiveDir)) {
New-Item -ItemType Directory -Path $archiveDir -Force | Out-Null
@@ -186,12 +187,11 @@ try {
Compress-Archive -Path "$outputDir\*" -DestinationPath $artifactZip -Force
}
return @{ ExitCode = $buildExit; Output = ($output -join "`n") }
return $exit
} -ArgumentList $GuestWorkDir, $Configuration, $GuestArtifactZip
Write-Host $buildResult.Output
if ($buildResult.ExitCode -ne 0) {
throw "dotnet build failed (exit $($buildResult.ExitCode))"
if ($buildExit -ne 0) {
throw "dotnet build failed (exit $buildExit)"
}
}