From d3f129f7773312bf59ee26a847920240e1b9bac2 Mon Sep 17 00:00:00 2001 From: Simone Date: Sun, 17 May 2026 15:50:17 +0200 Subject: [PATCH] fix(build): run Windows build cmd as PowerShell; resolve absolute artifact-source Two Windows-guest build bugs: - The build command was wrapped in `cmd /c`, so PowerShell-authored commands failed ("'New-Item' is not recognized"). Run it as PS (seed LASTEXITCODE=0 so PS-only commands exit cleanly). - artifact_source was always Join-Path'd with the workdir; an absolute source (C:\CI\output) became C:\CI\build\C:\CI\output. Use the path as-is when rooted, else Join-Path the workdir. Co-Authored-By: Claude Opus 4.7 --- src/ci_orchestrator/commands/build.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/ci_orchestrator/commands/build.py b/src/ci_orchestrator/commands/build.py index a1d6dbb..0b44650 100644 --- a/src/ci_orchestrator/commands/build.py +++ b/src/ci_orchestrator/commands/build.py @@ -284,11 +284,18 @@ def _windows_build( "--output (Join-Path (Get-Location) 'bin\\CIOutput')" ) + # Run the build command as PowerShell on the Windows guest. It is + # authored in PS by the workflow (New-Item, Set-Content, ...) and + # may also invoke native exes (python, dotnet). Wrapping it in + # `cmd /c` broke PS-native commands ("'New-Item' is not + # recognized"). LASTEXITCODE is seeded to 0 so a PS-only command + # (which never sets it) exits cleanly; native tools still set it. full_ps = ( f"{env_setup}Set-Location {_ps_quote(workdir)}; " f"$ErrorActionPreference='Continue'; " - f"& cmd /c {_ps_quote(run_cmd + ' 2>&1')}; " - "exit $LASTEXITCODE" + f"$global:LASTEXITCODE = 0; " + f"{run_cmd}; " + "if ($null -eq $LASTEXITCODE) { exit 0 } else { exit $LASTEXITCODE }" ) result = t.run(full_ps, check=False) if result.stdout: @@ -305,14 +312,20 @@ def _windows_build( return # Package the artifact source into the requested zip on the guest. + # artifact_source may be absolute (e.g. C:\CI\output) or relative + # to the build workdir. PowerShell Join-Path does NOT treat a + # rooted second segment as absolute (it concatenates, yielding + # C:\CI\build\C:\CI\output), so resolve it explicitly. if build_command: src_rel = artifact_source or "dist" - src_expr = f"Join-Path {_ps_quote(workdir)} {_ps_quote(src_rel)}" else: - src_expr = f"Join-Path {_ps_quote(workdir)} 'bin\\CIOutput'" + src_rel = "bin\\CIOutput" pkg_ps = ( - f"$src = {src_expr}; " + f"$work = {_ps_quote(workdir)}; " + f"$rel = {_ps_quote(src_rel)}; " + "$src = if ([System.IO.Path]::IsPathRooted($rel)) " + "{ $rel } else { Join-Path $work $rel }; " f"$zip = {_ps_quote(artifact_zip)}; " "if (-not (Test-Path $src)) { " " throw \"[build run] artifact source not found: $src\" }; "