From e34b3dbd10e927c88b0969dc5a34e676c65deb43 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Fri, 27 Mar 2026 11:39:24 -0400 Subject: [PATCH 1/6] Fix Helix work item premature exit in cDAC dump tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build command lines in _HelixCommandLines ItemGroup (with %25 encoding for Windows env vars), write to HelixCommand.txt via WriteLinesToFile, then read back as the HelixWorkItem Command via ReadAllText. This follows the pattern established by helixpublishwitharcade.proj. The original inline commands used 'exit' (Unix: exit \, Windows: exit /b 1) which terminates the Helix work item shell prematurely, preventing post-commands and test result reporting from running. Commands use safe alternatives: - Windows: %ComSpec% /C exit — spawns a sub-shell to set ERRORLEVEL - Unix: set_return() { return \; } — returns from function Fixes #126196 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../cdac/tests/DumpTests/cdac-dump-helix.proj | 167 +++++++++++------- 1 file changed, 107 insertions(+), 60 deletions(-) diff --git a/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj b/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj index 9def584915c05e..65fef8877499c6 100644 --- a/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj +++ b/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj @@ -66,52 +66,53 @@ - - - <_DumpGenCommands>@(_Debuggee->'mkdir %HELIX_WORKITEM_PAYLOAD%\dumps\local\%(DumpDir)\%(Identity) & set "DOTNET_DbgMiniDumpType=%(MiniDumpType)" & set "DOTNET_DbgMiniDumpName=%HELIX_WORKITEM_PAYLOAD%\dumps\local\%(DumpDir)\%(Identity)\%(Identity).dmp" & %HELIX_CORRELATION_PAYLOAD%\dotnet.exe exec %HELIX_WORKITEM_PAYLOAD%\debuggees\%(Identity)\%(Identity).dll', ' & ') - <_DumpInfoCommand>echo {"os":"$(TargetOS)","arch":"$(TargetArchitecture)"}> %HELIX_WORKITEM_PAYLOAD%\dumps\local\dump-info.json - - - - - <_TestCommand>%HELIX_CORRELATION_PAYLOAD%\dotnet.exe exec --runtimeconfig %HELIX_WORKITEM_PAYLOAD%\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.runtimeconfig.json --depsfile %HELIX_WORKITEM_PAYLOAD%\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.deps.json %HELIX_WORKITEM_PAYLOAD%\tests\xunit.console.dll %HELIX_WORKITEM_PAYLOAD%\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.dll -xml testResults.xml -nologo - <_TarCommand>tar -czf %HELIX_WORKITEM_UPLOAD_ROOT%\dumps.tar.gz -C %HELIX_WORKITEM_PAYLOAD%\dumps . - <_FullCommand>$(_DumpGenCommands) & $(_DumpInfoCommand) & $(_TestCommand) & if errorlevel 1 set _FAIL=1 & $(_TarCommand) & if defined _FAIL exit /b 1 - - - - - <_TarCommand>tar -czf %HELIX_WORKITEM_UPLOAD_ROOT%\dumps.tar.gz -C %HELIX_WORKITEM_PAYLOAD%\dumps . - <_FullCommand>$(_DumpGenCommands) & $(_DumpInfoCommand) & $(_TarCommand) - - - - - <_DumpGenCommands>@(_Debuggee->'mkdir -p $HELIX_WORKITEM_PAYLOAD/dumps/local/%(DumpDir)/%(Identity) && DOTNET_DbgMiniDumpType=%(MiniDumpType) DOTNET_DbgMiniDumpName=$HELIX_WORKITEM_PAYLOAD/dumps/local/%(DumpDir)/%(Identity)/%(Identity).dmp $HELIX_CORRELATION_PAYLOAD/dotnet exec $HELIX_WORKITEM_PAYLOAD/debuggees/%(Identity)/%(Identity).dll || true', ' && ') - <_DumpInfoCommand>echo '{"os":"$(TargetOS)","arch":"$(TargetArchitecture)"}' > $HELIX_WORKITEM_PAYLOAD/dumps/local/dump-info.json - - - - - <_TestCommand>$HELIX_CORRELATION_PAYLOAD/dotnet exec --runtimeconfig $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.runtimeconfig.json --depsfile $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.deps.json $HELIX_WORKITEM_PAYLOAD/tests/xunit.console.dll $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.dll -xml testResults.xml -nologo - <_TarCommand>tar -czf $HELIX_WORKITEM_UPLOAD_ROOT/dumps.tar.gz -C $HELIX_WORKITEM_PAYLOAD/dumps . - <_FullCommand>$(_DumpGenCommands) && $(_DumpInfoCommand) && $(_TestCommand); _rc=$?; $(_TarCommand); exit $_rc + + <_DumpInfoJson>{"os":"$(TargetOS)","arch":"$(TargetArchitecture)"} + <_HelixCommandFile>$(DumpTestsPayload)/HelixCommand.txt - - - <_TarCommand>tar -czf $HELIX_WORKITEM_UPLOAD_ROOT/dumps.tar.gz -C $HELIX_WORKITEM_PAYLOAD/dumps . - <_FullCommand>$(_DumpGenCommands) && $(_DumpInfoCommand) && $(_TarCommand) - + + + + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" Include="echo === Generating crash dumps ===" /> + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" Include="echo '=== Generating crash dumps ==='" /> + + + + + + + + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="mkdir %25HELIX_WORKITEM_PAYLOAD%25\dumps\local\%(_Debuggee.DumpDir)\%(_Debuggee.Identity)" /> + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="echo Generating dump for %(_Debuggee.Identity) (%(_Debuggee.DumpDir))..." /> + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="set "DOTNET_DbgMiniDumpType=%(_Debuggee.MiniDumpType)"" /> + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="set "DOTNET_DbgMiniDumpName=%25HELIX_WORKITEM_PAYLOAD%25\dumps\local\%(_Debuggee.DumpDir)\%(_Debuggee.Identity)\%(_Debuggee.Identity).dmp"" /> + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="%25HELIX_CORRELATION_PAYLOAD%25\dotnet.exe exec %25HELIX_WORKITEM_PAYLOAD%25\debuggees\%(_Debuggee.Identity)\%(_Debuggee.Identity).dll" /> + + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" + Include="mkdir -p $HELIX_WORKITEM_PAYLOAD/dumps/local/%(_Debuggee.DumpDir)/%(_Debuggee.Identity)" /> + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" + Include="echo " Generating dump for %(_Debuggee.Identity) (%(_Debuggee.DumpDir))..."" /> + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" + Include="DOTNET_DbgMiniDumpType=%(_Debuggee.MiniDumpType) DOTNET_DbgMiniDumpName=$HELIX_WORKITEM_PAYLOAD/dumps/local/%(_Debuggee.DumpDir)/%(_Debuggee.Identity)/%(_Debuggee.Identity).dmp $HELIX_CORRELATION_PAYLOAD/dotnet exec $HELIX_WORKITEM_PAYLOAD/debuggees/%(_Debuggee.Identity)/%(_Debuggee.Identity).dll || true" /> + + @@ -138,24 +139,70 @@ @(HelixPreCommand) - - - - $(DumpTestsPayload) - $(_FullCommand) - $(WorkItemTimeout) - dumps.tar.gz - - - - - - - $(DumpTestsPayload) - $(_FullCommand) - $(WorkItemTimeout) - dumps.tar.gz - - + + + + + + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="echo $(_DumpInfoJson)> %25HELIX_WORKITEM_PAYLOAD%25\dumps\local\dump-info.json" /> + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" + Include="echo '$(_DumpInfoJson)' > $HELIX_WORKITEM_PAYLOAD/dumps/local/dump-info.json" /> + + + + + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="%25HELIX_CORRELATION_PAYLOAD%25\dotnet.exe exec --runtimeconfig %25HELIX_WORKITEM_PAYLOAD%25\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.runtimeconfig.json --depsfile %25HELIX_WORKITEM_PAYLOAD%25\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.deps.json %25HELIX_WORKITEM_PAYLOAD%25\tests\xunit.console.dll %25HELIX_WORKITEM_PAYLOAD%25\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.dll -xml testResults.xml -nologo" /> + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" + Include="$HELIX_CORRELATION_PAYLOAD/dotnet exec --runtimeconfig $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.runtimeconfig.json --depsfile $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.deps.json $HELIX_WORKITEM_PAYLOAD/tests/xunit.console.dll $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.dll -xml testResults.xml -nologo" /> + + + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="set test_exit_code=%25ERRORLEVEL%25" /> + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" + Include="test_exit_code=$?" /> + + + + + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="tar -czf %25HELIX_WORKITEM_UPLOAD_ROOT%25\dumps.tar.gz -C %25HELIX_WORKITEM_PAYLOAD%25\dumps ." /> + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" + Include="tar -czf $HELIX_WORKITEM_UPLOAD_ROOT/dumps.tar.gz -C $HELIX_WORKITEM_PAYLOAD/dumps ." /> + + + + + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="%25ComSpec%25 /C exit %25test_exit_code%25" /> + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" + Include="set_return() { return $1; }" /> + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" + Include="set_return $test_exit_code" /> + + + + + + + $(DumpTestsPayload) + $([System.IO.File]::ReadAllText('$(_HelixCommandFile)')) + $(WorkItemTimeout) + dumps.tar.gz + + + + + + $(DumpTestsPayload) + $([System.IO.File]::ReadAllText('$(_HelixCommandFile)')) + $(WorkItemTimeout) + dumps.tar.gz + + + From bbde86a06771381858535ea8e326654ffa65304b Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Fri, 27 Mar 2026 16:21:39 -0400 Subject: [PATCH 2/6] Apply same WriteLinesToFile pattern to cdac-dump-xplat-test-helix.proj Refactor the cross-platform Helix test proj to use the same patterns: - WriteLinesToFile -> ReadAllText for multi-line command generation - Target batching (Outputs) to keep per-platform commands grouped - Readable one-command-per-line structure instead of long inline properties Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../DumpTests/cdac-dump-xplat-test-helix.proj | 60 +++++++++++++------ 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/src/native/managed/cdac/tests/DumpTests/cdac-dump-xplat-test-helix.proj b/src/native/managed/cdac/tests/DumpTests/cdac-dump-xplat-test-helix.proj index 1ef4c4f60a4ff5..e41e6613988da5 100644 --- a/src/native/managed/cdac/tests/DumpTests/cdac-dump-xplat-test-helix.proj +++ b/src/native/managed/cdac/tests/DumpTests/cdac-dump-xplat-test-helix.proj @@ -52,21 +52,39 @@ - - <_TestCommands>@(_SourcePlatform->'set "CDAC_DUMP_ROOT=%HELIX_WORKITEM_PAYLOAD%\dumps\%(Identity)" & %HELIX_CORRELATION_PAYLOAD%\dotnet.exe exec --runtimeconfig %HELIX_WORKITEM_PAYLOAD%\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.runtimeconfig.json --depsfile %HELIX_WORKITEM_PAYLOAD%\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.deps.json %HELIX_WORKITEM_PAYLOAD%\tests\xunit.console.dll %HELIX_WORKITEM_PAYLOAD%\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.dll -xml testResults_%(Identity).xml -nologo', ' & ') - - - <_TestCommands>@(_SourcePlatform->'CDAC_DUMP_ROOT=$HELIX_WORKITEM_PAYLOAD/dumps/%(Identity) $HELIX_CORRELATION_PAYLOAD/dotnet exec --runtimeconfig $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.runtimeconfig.json --depsfile $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.deps.json $HELIX_WORKITEM_PAYLOAD/tests/xunit.console.dll $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.dll -xml testResults_%(Identity).xml -nologo', ' %3B ') + + <_HelixCommandFile>$(DumpTestsPayload)/HelixCommand.txt + + + + + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="echo === Running tests against %(_SourcePlatform.Identity) dumps ===" /> + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="set "CDAC_DUMP_ROOT=%25HELIX_WORKITEM_PAYLOAD%25\dumps\%(_SourcePlatform.Identity)"" /> + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" + Include="%25HELIX_CORRELATION_PAYLOAD%25\dotnet.exe exec --runtimeconfig %25HELIX_WORKITEM_PAYLOAD%25\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.runtimeconfig.json --depsfile %25HELIX_WORKITEM_PAYLOAD%25\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.deps.json %25HELIX_WORKITEM_PAYLOAD%25\tests\xunit.console.dll %25HELIX_WORKITEM_PAYLOAD%25\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.dll -xml testResults_%(_SourcePlatform.Identity).xml -nologo" /> + + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" + Include="echo '=== Running tests against %(_SourcePlatform.Identity) dumps ==='" /> + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" + Include="CDAC_DUMP_ROOT=$HELIX_WORKITEM_PAYLOAD/dumps/%(_SourcePlatform.Identity) $HELIX_CORRELATION_PAYLOAD/dotnet exec --runtimeconfig $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.runtimeconfig.json --depsfile $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.deps.json $HELIX_WORKITEM_PAYLOAD/tests/xunit.console.dll $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.dll -xml testResults_%(_SourcePlatform.Identity).xml -nologo" /> + + + @@ -76,13 +94,19 @@ @(HelixPreCommand) - - - - $(DumpTestsPayload) - $(_TestCommands) - $(WorkItemTimeout) - - + + + + + + + $(DumpTestsPayload) + $([System.IO.File]::ReadAllText('$(_HelixCommandFile)')) + $(WorkItemTimeout) + + + From 3d39be9a35827e916a0f540cb62593da976bc79e Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Mon, 30 Mar 2026 13:02:39 -0400 Subject: [PATCH 3/6] Fix xplat test reporting: one Helix work item per source platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The xplat cDAC dump tests had two pre-existing issues: 1. XUnit reporter could not find test result XMLs (logged 'No results file found') 2. Test failures were silently swallowed — only last platform's exit code was returned Root cause: a single work item ran all platforms sequentially with chained commands. The reporter expects testResults.xml in the standard location, and the exit code only reflected the final command. Fix: create one HelixWorkItem per source platform (CdacXPlatDumpTests_PLATFORM). Each work item has its own command file, uses the standard testResults.xml filename, and gets independent exit code tracking. This matches the single-leg pattern in cdac-dump-helix.proj that already works correctly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../DumpTests/cdac-dump-xplat-test-helix.proj | 54 +++++++++---------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/src/native/managed/cdac/tests/DumpTests/cdac-dump-xplat-test-helix.proj b/src/native/managed/cdac/tests/DumpTests/cdac-dump-xplat-test-helix.proj index 7541b1f1c75597..a38f88f00f7795 100644 --- a/src/native/managed/cdac/tests/DumpTests/cdac-dump-xplat-test-helix.proj +++ b/src/native/managed/cdac/tests/DumpTests/cdac-dump-xplat-test-helix.proj @@ -9,8 +9,9 @@ dumps/{source_platform}/ — Extracted dumps from each source platform local/{dumpType}/{r2rMode}/{name}/{name}.dmp - A single Helix work item runs xunit once per source platform, each time - with CDAC_DUMP_ROOT pointing to that platform's dump subdirectory. + One Helix work item is created per source platform, each running xunit with + CDAC_DUMP_ROOT pointing to that platform's dump subdirectory. This gives each + platform independent exit code tracking and test result reporting. Properties (set by pipeline): HelixTargetQueues — Helix queue(s) to run on @@ -58,50 +59,45 @@ Bare $VAR is safe — MSBuild only interprets $(…) with parens. --> + + + + + - <_HelixCommandFile>$(DumpTestsPayload)/HelixCommand.txt + @(HelixPreCommand) - + + + <_HelixCommandFile>$(DumpTestsPayload)/HelixCommand_%(_SourcePlatform.Identity).txt + + + <_HelixCommandLines Remove="@(_HelixCommandLines)" /> - <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" - Include="echo === Running tests against %(_SourcePlatform.Identity) dumps ===" /> <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" Include="set "CDAC_DUMP_ROOT=%25HELIX_WORKITEM_PAYLOAD%25\dumps\%(_SourcePlatform.Identity)"" /> <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" - Include="%25HELIX_CORRELATION_PAYLOAD%25\dotnet.exe exec --runtimeconfig %25HELIX_WORKITEM_PAYLOAD%25\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.runtimeconfig.json --depsfile %25HELIX_WORKITEM_PAYLOAD%25\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.deps.json %25HELIX_WORKITEM_PAYLOAD%25\tests\xunit.console.dll %25HELIX_WORKITEM_PAYLOAD%25\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.dll -xml testResults_%(_SourcePlatform.Identity).xml -nologo" /> - + Include="%25HELIX_CORRELATION_PAYLOAD%25\dotnet.exe exec --runtimeconfig %25HELIX_WORKITEM_PAYLOAD%25\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.runtimeconfig.json --depsfile %25HELIX_WORKITEM_PAYLOAD%25\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.deps.json %25HELIX_WORKITEM_PAYLOAD%25\tests\xunit.console.dll %25HELIX_WORKITEM_PAYLOAD%25\tests\Microsoft.Diagnostics.DataContractReader.DumpTests.dll -xml testResults.xml -nologo" /> + <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" - Include="echo '=== Running tests against %(_SourcePlatform.Identity) dumps ==='" /> + Include="export CDAC_DUMP_ROOT=$HELIX_WORKITEM_PAYLOAD/dumps/%(_SourcePlatform.Identity)" /> <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" - Include="CDAC_DUMP_ROOT=$HELIX_WORKITEM_PAYLOAD/dumps/%(_SourcePlatform.Identity) $HELIX_CORRELATION_PAYLOAD/dotnet exec --runtimeconfig $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.runtimeconfig.json --depsfile $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.deps.json $HELIX_WORKITEM_PAYLOAD/tests/xunit.console.dll $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.dll -xml testResults_%(_SourcePlatform.Identity).xml -nologo" /> + Include="$HELIX_CORRELATION_PAYLOAD/dotnet exec --runtimeconfig $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.runtimeconfig.json --depsfile $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.deps.json $HELIX_WORKITEM_PAYLOAD/tests/xunit.console.dll $HELIX_WORKITEM_PAYLOAD/tests/Microsoft.Diagnostics.DataContractReader.DumpTests.dll -xml testResults.xml -nologo" /> - - - - - - - - @(HelixPreCommand) - - - - - + $(DumpTestsPayload) $([System.IO.File]::ReadAllText('$(_HelixCommandFile)')) $(WorkItemTimeout) From ed3632ad38fb4aab184a1f218660883b674874cc Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Mon, 30 Mar 2026 14:24:17 -0400 Subject: [PATCH 4/6] Fix MSB4012: pre-compute dump-info echo commands at project scope The _DumpInfoJson property contains @(_Debuggee) item transforms with embedded quotes. When used inside a Target's Include attribute, MSBuild fails to parse the nested quotes (MSB4012). Fix by pre-computing the full echo commands as properties at project scope where the item transforms are safely evaluated. Also clarify the exit code propagation comment per reviewer feedback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../managed/cdac/tests/DumpTests/cdac-dump-helix.proj | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj b/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj index 2e0554afa976a7..eacea14f0b3a48 100644 --- a/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj +++ b/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj @@ -83,6 +83,8 @@ <_DumpInfoJson>{"os":"$(TargetOS)","arch":"$(TargetArchitecture)","debuggees":[$(_DebuggeeJsonArray)]} <_HelixCommandFile>$(DumpTestsPayload)/HelixCommand.txt + <_DumpInfoCommandWindows>echo $(_DumpInfoJson)> %25HELIX_WORKITEM_PAYLOAD%25\dumps\local\dump-info.json + <_DumpInfoCommandUnix>echo '$(_DumpInfoJson)' > $HELIX_WORKITEM_PAYLOAD/dumps/local/dump-info.json <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" - Include="echo $(_DumpInfoJson)> %25HELIX_WORKITEM_PAYLOAD%25\dumps\local\dump-info.json" /> + Include="$(_DumpInfoCommandWindows)" /> <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" - Include="echo '$(_DumpInfoJson)' > $HELIX_WORKITEM_PAYLOAD/dumps/local/dump-info.json" /> + Include="$(_DumpInfoCommandUnix)" /> @@ -184,7 +186,7 @@ Include="tar -czf $HELIX_WORKITEM_UPLOAD_ROOT/dumps.tar.gz -C $HELIX_WORKITEM_PAYLOAD/dumps ." /> - + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" Include="%25ComSpec%25 /C exit %25test_exit_code%25" /> From 0c7fd3f8eceea9bf69448db671767e5066bc8ee2 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Mon, 30 Mar 2026 15:31:17 -0400 Subject: [PATCH 5/6] Fix MSB4012: use CreateProperty to force-evaluate item transforms Properties containing @() item transforms are lazily evaluated in MSBuild. When used inside a Target's ItemGroup Include attribute, the deferred @() expansion conflicts with XML attribute parsing. Use CreateProperty task to force the item transform evaluation into a flat string before use. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../cdac/tests/DumpTests/cdac-dump-helix.proj | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj b/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj index eacea14f0b3a48..5f7d9120f45a6d 100644 --- a/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj +++ b/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj @@ -155,13 +155,21 @@ + + + + + + + + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" - Include="$(_DumpInfoCommandWindows)" /> + Include="$(_EvalDumpInfoCommandWindows)" /> <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" - Include="$(_DumpInfoCommandUnix)" /> + Include="$(_EvalDumpInfoCommandUnix)" /> From 1381cfadec6a288c2b60d23b61c0c7e96d9c5342 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Mon, 30 Mar 2026 16:31:58 -0400 Subject: [PATCH 6/6] Fix MSB4012: evaluate @() item transform directly in CreateProperty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous approach used CreateProperty on the full echo command property chain, which expanded to @(_Debuggee->'...') mixed with surrounding text — causing MSB4012 (item lists cannot be concatenated with other strings). Fix: use CreateProperty with the bare @() transform expression alone (no surrounding text), producing a flat string _EvalDebuggeeJsonArray. Then build the echo commands inline using that flat string. This matches codebase patterns (NativeAOT IlcArg, ILLink, nativepgo). Also encode semicolon as %3B in set_return() to prevent MSBuild splitting on ; in Include attributes (matching helixpublishwitharcade). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../cdac/tests/DumpTests/cdac-dump-helix.proj | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj b/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj index 5f7d9120f45a6d..cb0702d762d63d 100644 --- a/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj +++ b/src/native/managed/cdac/tests/DumpTests/cdac-dump-helix.proj @@ -68,11 +68,6 @@ - - - <_DebuggeeJsonArray>@(_Debuggee->'{"name":"%(Identity)","dumpDir":"%(DumpDir)","r2rDir":"%(R2RDir)"}', ',') - - - <_DumpInfoJson>{"os":"$(TargetOS)","arch":"$(TargetArchitecture)","debuggees":[$(_DebuggeeJsonArray)]} <_HelixCommandFile>$(DumpTestsPayload)/HelixCommand.txt - <_DumpInfoCommandWindows>echo $(_DumpInfoJson)> %25HELIX_WORKITEM_PAYLOAD%25\dumps\local\dump-info.json - <_DumpInfoCommandUnix>echo '$(_DumpInfoJson)' > $HELIX_WORKITEM_PAYLOAD/dumps/local/dump-info.json - - - - - + + + <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" - Include="$(_EvalDumpInfoCommandWindows)" /> + Include="echo {"os":"$(TargetOS)","arch":"$(TargetArchitecture)","debuggees":[$(_EvalDebuggeeJsonArray)]}> %25HELIX_WORKITEM_PAYLOAD%25\dumps\local\dump-info.json" /> <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" - Include="$(_EvalDumpInfoCommandUnix)" /> + Include="echo '{"os":"$(TargetOS)","arch":"$(TargetArchitecture)","debuggees":[$(_EvalDebuggeeJsonArray)]}' > $HELIX_WORKITEM_PAYLOAD/dumps/local/dump-info.json" /> @@ -199,7 +192,7 @@ <_HelixCommandLines Condition="'$(TargetOS)' == 'windows'" Include="%25ComSpec%25 /C exit %25test_exit_code%25" /> <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" - Include="set_return() { return $1; }" /> + Include="set_return() { return $1%3B }" /> <_HelixCommandLines Condition="'$(TargetOS)' != 'windows'" Include="set_return $test_exit_code" />