From 187b5ab6326fcfa0281af640080f071ac1ccca43 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 11 Feb 2026 16:14:03 -0500
Subject: [PATCH 01/48] add helix sdk
---
global.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/global.json b/global.json
index 0530bb2185..1aef5fd93c 100644
--- a/global.json
+++ b/global.json
@@ -18,6 +18,7 @@
"msbuild-sdks": {
"Microsoft.Build.NoTargets": "3.5.0",
"Microsoft.Build.Traversal": "3.4.0",
- "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26080.4"
+ "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26080.4",
+ "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.26080.4"
}
}
From d6bb8df6dd83b8407e96e8e03d6b4a5e8b55d6c6 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 11 Feb 2026 16:14:39 -0500
Subject: [PATCH 02/48] refactor cdb/testassets to be copied to artifacts dir
---
.../DbgShim.UnitTests.csproj | 24 +++-----
src/tests/Directory.Build.props | 9 +++
src/tests/Directory.Build.targets | 58 ++++++++++++++++++-
src/tests/SOS.UnitTests/SOS.UnitTests.csproj | 7 +--
4 files changed, 76 insertions(+), 22 deletions(-)
diff --git a/src/tests/DbgShim.UnitTests/DbgShim.UnitTests.csproj b/src/tests/DbgShim.UnitTests/DbgShim.UnitTests.csproj
index c931e79852..f17b7599e9 100644
--- a/src/tests/DbgShim.UnitTests/DbgShim.UnitTests.csproj
+++ b/src/tests/DbgShim.UnitTests/DbgShim.UnitTests.csproj
@@ -6,6 +6,8 @@
$(OutputPath)$(TargetFramework)\Debugger.Tests.Common.txt
1.0.351101
true
+ true
+ true
@@ -28,16 +30,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -48,10 +40,10 @@
$(Configuration)
$(ArtifactsDir)
- $(NuGetPackageRoot)testassets.windows.x64.6.0\$(TestAssetsVersion)\content
- $(NuGetPackageRoot)testassets.windows.x86.6.0\$(TestAssetsVersion)\content
- $(NuGetPackageRoot)testassets.linux.x64.6.0\$(TestAssetsVersion)\content
- $(NuGetPackageRoot)testassets.linux.arm64.6.0\$(TestAssetsVersion)\content
+ %24(ArtifactsDir)test\packages\testassets.windows.x64.6.0\$(TestAssetsVersion)\content
+ %24(ArtifactsDir)test\packages\testassets.windows.x86.6.0\$(TestAssetsVersion)\content
+ %24(ArtifactsDir)test\packages\testassets.linux.x64.6.0\$(TestAssetsVersion)\content
+ %24(ArtifactsDir)test\packages\testassets.linux.arm64.6.0\$(TestAssetsVersion)\content
]]>
@@ -68,8 +60,8 @@
$(Configuration)
$(ArtifactsDir)
- $(NuGetPackageRoot)testassets.linux.x64.6.0/$(TestAssetsVersion)/content
- $(NuGetPackageRoot)testassets.linux.arm64.6.0/$(TestAssetsVersion)/content
+ %24(ArtifactsDir)test/packages/testassets.linux.x64.6.0/$(TestAssetsVersion)/content
+ %24(ArtifactsDir)test/packages/testassets.linux.arm64.6.0/$(TestAssetsVersion)/content
]]>
diff --git a/src/tests/Directory.Build.props b/src/tests/Directory.Build.props
index e36d68d633..9f63e06a15 100644
--- a/src/tests/Directory.Build.props
+++ b/src/tests/Directory.Build.props
@@ -1,3 +1,12 @@
+
+
+ $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'test', 'packages'))
+
+
+
+ true
+ true
+
diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets
index ab42c9ad55..373bd53110 100644
--- a/src/tests/Directory.Build.targets
+++ b/src/tests/Directory.Build.targets
@@ -6,7 +6,8 @@
Projects opt-in by setting CopyDebuggeeSourcesToArtifacts=true.
Optional: Set CopyLldbPluginTests=true to also copy lldbplugin.tests.
-->
-
+
$(ArtifactsDir)test/DebuggeeSources/$(MSBuildProjectName)/Debuggees
$(ArtifactsDir)test/AuxMsbuildFiles
@@ -32,4 +33,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_cdbFiles Include="$(NuGetPackageRoot)cdb-sos\$(cdbsosversion)\**\*"
+ Condition="'$(NeedsCdb)' == 'true'" />
+
+ <_testAssetsWinx64 Include="$(NuGetPackageRoot)testassets.windows.x64.6.0\$(TestAssetsVersion)\**\*"
+ Condition="'$(NeedsTestAssets)' == 'true' and '$(OS)' == 'Windows_NT'" />
+
+ <_testAssetsWinx86 Include="$(NuGetPackageRoot)testassets.windows.x86.6.0\$(TestAssetsVersion)\**\*"
+ Condition="'$(NeedsTestAssets)' == 'true' and '$(OS)' == 'Windows_NT'" />
+
+ <_testAssetsLinux64 Include="$(NuGetPackageRoot)testassets.linux.x64.6.0\$(TestAssetsVersion)\**\*"
+ Condition="'$(NeedsTestAssets)' == 'true'" />
+
+ <_testAssetsLinuxArm64 Include="$(NuGetPackageRoot)testassets.linux.arm64.6.0\$(TestAssetsVersion)\**\*"
+ Condition="'$(NeedsTestAssets)' == 'true'" />
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/tests/SOS.UnitTests/SOS.UnitTests.csproj b/src/tests/SOS.UnitTests/SOS.UnitTests.csproj
index f4a9e017d0..ef2ff4364a 100644
--- a/src/tests/SOS.UnitTests/SOS.UnitTests.csproj
+++ b/src/tests/SOS.UnitTests/SOS.UnitTests.csproj
@@ -8,6 +8,7 @@
$(OutputPath)$(TargetFramework)\Debugger.Tests.Common.txt
true
true
+ true
@@ -36,10 +37,6 @@
-
-
-
-
@@ -49,7 +46,7 @@
$(DesktopTargetFramework)
$(NetCoreAppMinTargetFramework)
$(ArtifactsDir)
- $(NuGetPackageRoot)cdb-sos\$(cdbsosversion)\runtimes\win-%24(TargetArchitecture)\native\cdb.exe
+ %24(ArtifactsDir)test\packages\cdb-sos\$(cdbsosversion)\runtimes\win-%24(TargetArchitecture)\native\cdb.exe
]]>
From 4753f3c391b9cbb6c47662601a2348a52cc2da38 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 11 Feb 2026 16:24:18 -0500
Subject: [PATCH 03/48] update DebugServices.UnitTests to get rid of
$(RepoRoot)
---
.../Unix/Debugger.Tests.Config.txt | 3 +-
.../Windows/Debugger.Tests.Config.txt | 3 +-
...Diagnostics.DebugServices.UnitTests.csproj | 31 +++++++------------
3 files changed, 13 insertions(+), 24 deletions(-)
diff --git a/src/tests/Microsoft.Diagnostics.DebugServices.UnitTests/ConfigFiles/Unix/Debugger.Tests.Config.txt b/src/tests/Microsoft.Diagnostics.DebugServices.UnitTests/ConfigFiles/Unix/Debugger.Tests.Config.txt
index e72e581b9e..400f9cf56d 100644
--- a/src/tests/Microsoft.Diagnostics.DebugServices.UnitTests/ConfigFiles/Unix/Debugger.Tests.Config.txt
+++ b/src/tests/Microsoft.Diagnostics.DebugServices.UnitTests/ConfigFiles/Unix/Debugger.Tests.Config.txt
@@ -1,8 +1,7 @@
- $(RepoRootDir)/artifacts
- $(RootBinDir)/bin/$(OS).$(TargetArchitecture).$(TargetConfiguration)
+ $(ArtifactsDir)bin/$(OS).$(TargetArchitecture).$(TargetConfiguration)
@@ -19,17 +21,6 @@
-
-
-
-
-
-
-
-
-
-
-
Debugger.Tests.Config.txt
@@ -50,13 +41,13 @@
$(Configuration)
- $(RepoRoot)
+ $(ArtifactsDir)
$(RunTests)
- $(NuGetPackageRoot)cdb-sos\$(cdbsosversion)\runtimes\win-%24(TargetArchitecture)\native\dbgeng.dll
- $(NuGetPackageRoot)testassets.windows.x64.6.0\$(TestAssetsVersion)\content
- $(NuGetPackageRoot)testassets.windows.x86.6.0\$(TestAssetsVersion)\content
- $(NuGetPackageRoot)testassets.linux.x64.6.0\$(TestAssetsVersion)\content
- $(NuGetPackageRoot)testassets.linux.arm64.6.0\$(TestAssetsVersion)\content
+ %24(ArtifactsDir)test\packages\cdb-sos\$(cdbsosversion)\runtimes\win-%24(TargetArchitecture)\native\dbgeng.dll
+ %24(ArtifactsDir)test\packages\testassets.windows.x64.6.0\$(TestAssetsVersion)\content
+ %24(ArtifactsDir)test\packages\testassets.windows.x86.6.0\$(TestAssetsVersion)\content
+ %24(ArtifactsDir)test\packages\testassets.linux.x64.6.0\$(TestAssetsVersion)\content
+ %24(ArtifactsDir)test\packages\testassets.linux.arm64.6.0\$(TestAssetsVersion)\content
]]>
@@ -72,10 +63,10 @@
$(Configuration)
- $(RepoRoot)
+ $(ArtifactsDir)
$(RunTests)
- $(NuGetPackageRoot)testassets.linux.x64.6.0/$(TestAssetsVersion)/content
- $(NuGetPackageRoot)testassets.linux.arm64.6.0/$(TestAssetsVersion)/content
+ %24(ArtifactsDir)test/packages/testassets.linux.x64.6.0/$(TestAssetsVersion)/content
+ %24(ArtifactsDir)test/packages/testassets.linux.arm64.6.0/$(TestAssetsVersion)/content
]]>
From 40c1ddba41d4174ef2ae9d93351313409db51b83 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 11 Feb 2026 18:20:45 -0500
Subject: [PATCH 04/48] update AuxMsbuildFiles to not use Arcade
---
eng/AuxMsbuildFiles/Directory.Build.props | 5 +----
eng/AuxMsbuildFiles/Directory.Build.targets | 2 --
src/tests/Directory.Build.targets | 21 ++++++++++++++++++++-
3 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/eng/AuxMsbuildFiles/Directory.Build.props b/eng/AuxMsbuildFiles/Directory.Build.props
index 8231a8a4fd..22b6efee36 100644
--- a/eng/AuxMsbuildFiles/Directory.Build.props
+++ b/eng/AuxMsbuildFiles/Directory.Build.props
@@ -1,8 +1,5 @@
-
-
-
+
bin\
diff --git a/eng/AuxMsbuildFiles/Directory.Build.targets b/eng/AuxMsbuildFiles/Directory.Build.targets
index 6384491004..8bf348bb69 100644
--- a/eng/AuxMsbuildFiles/Directory.Build.targets
+++ b/eng/AuxMsbuildFiles/Directory.Build.targets
@@ -1,6 +1,4 @@
-
-
diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets
index 373bd53110..9061e8ca91 100644
--- a/src/tests/Directory.Build.targets
+++ b/src/tests/Directory.Build.targets
@@ -7,7 +7,8 @@
Optional: Set CopyLldbPluginTests=true to also copy lldbplugin.tests.
-->
+ Condition="'$(CopyDebuggeeSourcesToArtifacts)' == 'true' or '$(NeedsCdb)' == 'true'"
+ DependsOnTargets="CopyVersionsProps">
$(ArtifactsDir)test/DebuggeeSources/$(MSBuildProjectName)/Debuggees
$(ArtifactsDir)test/AuxMsbuildFiles
@@ -33,6 +34,24 @@
+
+
+
+ <_AuxDir>$(ArtifactsDir)test/AuxMsbuildFiles/
+
+
+
+
+
+
Date: Wed, 11 Feb 2026 18:21:52 -0500
Subject: [PATCH 05/48] add helix support
---
diagnostics.yml | 55 ++++
eng/helix.proj | 245 ++++++++++++++++++
eng/pipelines/global-variables.yml | 35 +++
eng/pipelines/helix.yml | 183 +++++++++++++
eng/send-to-helix.cmd | 170 ++++++++++++
eng/send-to-helix.sh | 217 ++++++++++++++++
.../TestConfiguration.cs | 37 +++
7 files changed, 942 insertions(+)
create mode 100644 eng/helix.proj
create mode 100644 eng/pipelines/helix.yml
create mode 100644 eng/send-to-helix.cmd
create mode 100644 eng/send-to-helix.sh
diff --git a/diagnostics.yml b/diagnostics.yml
index 389526e741..fa9efc693b 100644
--- a/diagnostics.yml
+++ b/diagnostics.yml
@@ -19,6 +19,10 @@ parameters:
displayName: Build only (skip tests)
type: boolean
default: false
+- name: useHelix
+ displayName: Run tests on Helix (distributed testing)
+ type: boolean
+ default: false
trigger: none
@@ -282,9 +286,60 @@ extends:
- configuration: Debug
architecture: x64
+ ############################
+ # #
+ # Helix Test Stage #
+ # #
+ ############################
+
+ - ${{ if and(eq(parameters.useHelix, true), ne(parameters.buildOnly, true)) }}:
+ - stage: helix
+ displayName: Run Tests on Helix
+ dependsOn: build
+ jobs:
+ # Windows x64 Helix tests
+ - template: /eng/pipelines/helix.yml
+ parameters:
+ name: Helix_Windows
+ jobTemplate: ${{ variables.jobTemplate }}
+ osGroup: Windows_NT
+ configuration: Release
+ architecture: x64
+ helixQueues: $(HelixQueuesWindows_x64)
+ isInternal: ${{ ne(variables['System.TeamProject'], 'public') }}
+ dependsOn: Windows_x64_Release
+
+ # Linux x64 Helix tests
+ - template: /eng/pipelines/helix.yml
+ parameters:
+ name: Helix_Linux
+ jobTemplate: ${{ variables.jobTemplate }}
+ osGroup: Linux
+ configuration: Release
+ architecture: x64
+ helixQueues: $(HelixQueuesLinux_x64)
+ isInternal: ${{ ne(variables['System.TeamProject'], 'public') }}
+ dependsOn: Linux_x64_Release
+
+ # MacOS x64 Helix tests
+ - template: /eng/pipelines/helix.yml
+ parameters:
+ name: Helix_MacOS
+ jobTemplate: ${{ variables.jobTemplate }}
+ osGroup: MacOS
+ configuration: Release
+ architecture: x64
+ helixQueues: $(HelixQueuesMacOS_x64)
+ isInternal: ${{ ne(variables['System.TeamProject'], 'public') }}
+ dependsOn: MacOS_x64_Release
+
- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- stage: package
displayName: Package, Sign, and Generate BAR Manifests
+ ${{ if eq(parameters.useHelix, true) }}:
+ dependsOn: helix
+ ${{ else }}:
+ dependsOn: build
jobs:
- template: /eng/common/templates-official/job/job.yml
parameters:
diff --git a/eng/helix.proj b/eng/helix.proj
new file mode 100644
index 0000000000..452633dc7d
--- /dev/null
+++ b/eng/helix.proj
@@ -0,0 +1,245 @@
+
+
+
+
+
+
+ msbuild
+ net8.0
+
+
+ pr/$(BUILD_REPOSITORY_NAME)/$(BUILD_SOURCEBRANCH)
+ local/diagnostics
+ test/$(Configuration)/$(TargetArchitecture)/
+ $(BUILD_BUILDNUMBER)
+ 0.0.0.0
+
+
+ $(ArtifactsDir)
+ 00:30:00
+
+
+ true
+ true
+
+
+ true
+ sdk
+ 10.0.102
+
+
+ <_CorrelationPayload Condition="'$(TargetOS)' == 'Windows_NT'">%HELIX_CORRELATION_PAYLOAD%
+ <_CorrelationPayload Condition="'$(TargetOS)' != 'Windows_NT'">$HELIX_CORRELATION_PAYLOAD
+ <_UploadRoot Condition="'$(TargetOS)' == 'Windows_NT'">%HELIX_WORKITEM_UPLOAD_ROOT%
+ <_UploadRoot Condition="'$(TargetOS)' != 'Windows_NT'">$HELIX_WORKITEM_UPLOAD_ROOT
+ <_PathSep Condition="'$(TargetOS)' == 'Windows_NT'">\
+ <_PathSep Condition="'$(TargetOS)' != 'Windows_NT'">/
+ <_DotNetCliDir>$(_CorrelationPayload)$(_PathSep)dotnet-cli
+ <_ArtifactsDir>$(_CorrelationPayload)$(_PathSep)artifacts$(_PathSep)
+ <_VersionsFile>$(_ArtifactsDir)dotnet-test$(_PathSep)Debugger.Tests.Versions.txt
+
+
+ set "DIAGNOSTICS_ARTIFACTS_DIR=$(_ArtifactsDir)" && set "RunningOnHelix=true" && copy /Y "$(_VersionsFile)" "$(_DotNetCliDir)$(_PathSep)Debugger.Tests.Versions.txt"
+ export DIAGNOSTICS_ARTIFACTS_DIR="$(_ArtifactsDir)" && export RunningOnHelix=true && cp -f "$(_VersionsFile)" "$(_DotNetCliDir)/Debugger.Tests.Versions.txt"
+
+
+ <_VersionsStagingDir>$(ArtifactsDir)tmp\helix\dotnet-test\
+
+ <_BuildConfigStagingDir>$(ArtifactsDir)tmp\helix\build-config\
+
+
+
+
+
+
+ runtime
+
+
+ aspnetcore-runtime
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ artifacts/bin/dotnet-trace
+
+
+ artifacts/bin/dotnet-dump
+
+
+ artifacts/bin/dotnet-counters
+
+
+
+
+
+
+ artifacts/test
+
+
+
+
+
+
+ artifacts/bin/$(TargetOS).$(TargetArchitecture).$(Configuration)
+
+
+
+
+
+
+ artifacts/bin/SOS.UnitTests
+
+
+
+
+
+ <_DebuggeeName Include="Tracee;EventPipeTracee;ExitCodeTracee;StackTracee" />
+ <_DebuggeeName Include="SimpleDebuggee;AsyncMain;DivZero;DumpGCData;WebApp3;LineNums;Overflow;SimpleThrow" />
+ <_DebuggeeName Include="NestedExceptionTest;TaskNestedException;ReflectionTest;GCPOH;GCWhere" />
+ <_DebuggeeName Include="MiniDumpLocalVarLookup;VarargPInvokeInteropMD;DynamicMethod;DotnetDumpCommands" />
+ <_DebuggeeName Include="FindRootsOlderGeneration;SymbolTestApp;SymbolTestDll;RandomUserLibrary;TestExtension" />
+
+
+
+
+
+ artifacts/bin/%(Identity)
+
+
+
+
+
+
+
+
+
+
+ <_VersionsLines Include="<Configuration>" />
+ <_VersionsLines Include="@(RuntimeTestVersions->' <RuntimeVersion%(Identity)>%(Runtime)</RuntimeVersion%(Identity)>')" />
+ <_VersionsLines Include="@(RuntimeTestVersions->' <AspNetCoreVersion%(Identity)>%(AspNet)</AspNetCoreVersion%(Identity)>')" />
+ <_VersionsLines Include="@(RuntimeTestVersions->' <TargetFramework%(Identity)>%(TargetFramework)</TargetFramework%(Identity)>')" />
+ <_VersionsLines Include="</Configuration>" />
+
+
+
+
+
+
+
+
+
+ artifacts/dotnet-test
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ artifacts
+
+
+
+
+
+
+
+
+
+
+
+ $(TestArtifactsDir)bin\%(HelixPureTestProject.Identity)\$(Configuration)\$(NetCoreAppMinTargetFramework)
+ dotnet test %(HelixPureTestProject.Identity).dll --logger "trx;LogFileName=%(HelixPureTestProject.Identity).trx" --results-directory $(_UploadRoot)
+ $(TestTimeout)
+
+
+
+
+
+
+ $(TestArtifactsDir)bin\%(HelixComplexTestProject.Identity)\$(Configuration)\$(NetCoreAppMinTargetFramework)
+ dotnet test %(HelixComplexTestProject.Identity).dll --logger "trx;LogFileName=%(HelixComplexTestProject.Identity).trx" --results-directory $(_UploadRoot)
+ $(TestTimeout)
+
+
+
+
+
+
+ $(TestArtifactsDir)bin\%(HelixNativeTestProject.Identity)\$(Configuration)\$(NetCoreAppMinTargetFramework)
+ dotnet test %(HelixNativeTestProject.Identity).dll --logger "trx;LogFileName=%(HelixNativeTestProject.Identity).trx" --results-directory $(_UploadRoot)
+ $(TestTimeout)
+
+
+
+
+
+
+
diff --git a/eng/pipelines/global-variables.yml b/eng/pipelines/global-variables.yml
index 92a3439d9f..3b5cadd6ef 100644
--- a/eng/pipelines/global-variables.yml
+++ b/eng/pipelines/global-variables.yml
@@ -57,3 +57,38 @@ variables:
- ${{ if eq(parameters.runtimeFeedToken, 'dotnetclimsrc-sas-token-base64') }}:
- name: RuntimeFeedBase64SasToken
value: $(dotnetclimsrc-read-sas-token-base64)
+
+# Helix queue configuration
+# Public (open) queues for PR validation
+- ${{ if eq(variables['System.TeamProject'], 'public') }}:
+ - name: HelixQueuesWindows_x64
+ value: Windows.10.Amd64.Open
+ - name: HelixQueuesWindows_x86
+ value: Windows.10.Amd64.Open
+ - name: HelixQueuesLinux_x64
+ value: Ubuntu.2204.Amd64.Open
+ - name: HelixQueuesLinux_arm64
+ value: Ubuntu.2204.Arm64.Open
+ - name: HelixQueuesMacOS_x64
+ value: OSX.1200.Amd64.Open
+ - name: HelixQueuesMacOS_arm64
+ value: OSX.1200.Arm64.Open
+ - name: HelixQueuesFreeBSD
+ value: ''
+
+# Internal queues for official builds
+- ${{ if ne(variables['System.TeamProject'], 'public') }}:
+ - name: HelixQueuesWindows_x64
+ value: Windows.10.Amd64
+ - name: HelixQueuesWindows_x86
+ value: Windows.10.Amd64
+ - name: HelixQueuesLinux_x64
+ value: Ubuntu.2204.Amd64
+ - name: HelixQueuesLinux_arm64
+ value: Ubuntu.2204.Arm64
+ - name: HelixQueuesMacOS_x64
+ value: OSX.1200.Amd64
+ - name: HelixQueuesMacOS_arm64
+ value: OSX.1200.Arm64
+ - name: HelixQueuesFreeBSD
+ value: ''
diff --git a/eng/pipelines/helix.yml b/eng/pipelines/helix.yml
new file mode 100644
index 0000000000..53d9045f16
--- /dev/null
+++ b/eng/pipelines/helix.yml
@@ -0,0 +1,183 @@
+# Pipeline template for running tests on Helix
+# This template sends test workloads to Helix machines for distributed execution
+
+parameters:
+ # Job name suffix
+- name: name
+ type: string
+ default: 'Helix'
+
+- name: jobTemplate
+ type: string
+ default: /eng/common/templates/job/job.yml@self
+ values:
+ - /eng/common/templates-official/job/job.yml@self
+ - /eng/common/templates/job/job.yml@self
+
+- name: osGroup
+ type: string
+ default: Windows_NT
+ values:
+ - Windows_NT
+ - Linux
+ - MacOS
+
+ # Build configuration
+- name: configuration
+ type: string
+ default: Debug
+
+ # Target architecture
+- name: architecture
+ type: string
+ default: x64
+
+ # Helix queue to target (semicolon-delimited list supported)
+- name: helixQueues
+ type: string
+ default: ''
+
+ # Whether this is an internal (authenticated) build
+- name: isInternal
+ type: boolean
+ default: false
+
+ # Job timeout
+- name: timeoutInMinutes
+ type: number
+ default: 120
+
+ # Job dependencies (build job name without architecture/configuration suffix)
+- name: dependsOn
+ type: string
+ default: ''
+
+ # Template context for 1ES pipeline
+- name: templateContext
+ type: object
+ default: {}
+
+jobs:
+- template: ${{ parameters.jobTemplate }}
+ parameters:
+ name: ${{ parameters.name }}_${{ parameters.architecture }}_${{ parameters.configuration }}
+ timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
+ templateContext: ${{ parameters.templateContext }}
+
+ # Note: cross-stage job dependencies are not supported in Azure Pipelines.
+ # The stage-level dependsOn handles this. We keep dependsOn parameter for
+ # artifact naming only.
+
+ pool:
+ ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
+ name: $(BuildPool)
+ demands: ImageOverride -equals $(WindowsImage)
+ os: windows
+
+ ${{ if eq(parameters.osGroup, 'Linux') }}:
+ name: $(BuildPool)
+ demands: ImageOverride -equals $(LinuxImage)
+ os: linux
+
+ ${{ if eq(parameters.osGroup, 'MacOS') }}:
+ name: Azure Pipelines
+ vmImage: $(macOSImage)
+ os: macOS
+
+ workspace:
+ clean: all
+
+ variables:
+ - _BuildConfig: ${{ parameters.configuration }}
+ - _HelixType: test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+
+ # Determine target OS for helix.proj
+ - ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
+ - _TargetOS: Windows_NT
+ - ${{ if eq(parameters.osGroup, 'Linux') }}:
+ - _TargetOS: linux
+ - ${{ if eq(parameters.osGroup, 'MacOS') }}:
+ - _TargetOS: osx
+
+ # Helix queue configuration
+ - _HelixQueues: ${{ parameters.helixQueues }}
+
+ # For internal builds, use the Helix access token
+ - ${{ if eq(parameters.isInternal, true) }}:
+ - group: DotNet-HelixApi-Access
+ - _HelixAccessToken: $(HelixApiAccessToken)
+ - _HelixSource: official/diagnostics/$(Build.SourceBranch)
+ - ${{ else }}:
+ - _HelixAccessToken: ''
+ - _HelixSource: pr/diagnostics/$(Build.SourceBranch)
+ - _Creator: $(Build.RequestedFor)
+
+ steps:
+ # Download build artifacts from the build job
+ - task: DownloadPipelineArtifact@2
+ displayName: 'Download Build Artifacts'
+ inputs:
+ targetPath: '$(Build.SourcesDirectory)/artifacts'
+ artifactName: Build_${{ parameters.dependsOn }}
+ checkDownloadedFiles: true
+
+ # Send tests to Helix
+ - ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
+ - script: >
+ $(Build.SourcesDirectory)\eng\common\msbuild.cmd
+ $(Build.SourcesDirectory)\eng\helix.proj
+ /restore
+ /t:Test
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=$(_TargetOS)
+ /p:HelixTargetQueues=$(_HelixQueues)
+ /p:HelixSource=$(_HelixSource)
+ /p:HelixType=$(_HelixType)
+ /p:HelixAccessToken=$(_HelixAccessToken)
+ ${{ if eq(parameters.isInternal, false) }}:/p:Creator=$(_Creator)
+ /p:TestArtifactsDir=$(Build.SourcesDirectory)/artifacts/
+ /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
+ displayName: Send Tests to Helix
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+
+ - ${{ if ne(parameters.osGroup, 'Windows_NT') }}:
+ - script: >
+ $(Build.SourcesDirectory)/eng/common/msbuild.sh
+ $(Build.SourcesDirectory)/eng/helix.proj
+ /restore
+ /t:Test
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=$(_TargetOS)
+ /p:HelixTargetQueues=$(_HelixQueues)
+ /p:HelixSource=$(_HelixSource)
+ /p:HelixType=$(_HelixType)
+ /p:HelixAccessToken=$(_HelixAccessToken)
+ ${{ if eq(parameters.isInternal, false) }}:/p:Creator=$(_Creator)
+ /p:TestArtifactsDir=$(Build.SourcesDirectory)/artifacts/
+ /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
+ displayName: Send Tests to Helix
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+
+ # Publish Helix logs
+ - task: CopyFiles@2
+ displayName: Gather Helix Logs
+ inputs:
+ sourceFolder: '$(Build.SourcesDirectory)/artifacts'
+ contents: 'log/**'
+ targetFolder: '$(Build.StagingDirectory)/HelixLogs'
+ continueOnError: true
+ condition: always()
+
+ - template: /eng/pipelines/publish-pipeline-artifact-shim.yml@self
+ parameters:
+ displayName: Publish Helix Logs
+ inputs:
+ targetPath: '$(Build.StagingDirectory)/HelixLogs'
+ artifactName: HelixLogs_${{ parameters.name }}_${{ parameters.osGroup }}_${{ parameters.architecture }}_${{ parameters.configuration }}
+ sbomEnabled: false
+ continueOnError: true
+ condition: always()
diff --git a/eng/send-to-helix.cmd b/eng/send-to-helix.cmd
new file mode 100644
index 0000000000..cce321a0bd
--- /dev/null
+++ b/eng/send-to-helix.cmd
@@ -0,0 +1,170 @@
+@echo off
+REM Licensed to the .NET Foundation under one or more agreements.
+REM The .NET Foundation licenses this file to you under the MIT license.
+
+REM Send diagnostics tests to Helix for remote execution.
+REM
+REM Usage: send-to-helix.cmd [options]
+REM
+REM Options:
+REM -configuration Build configuration (default: Debug)
+REM -architecture Target architecture (default: x64)
+REM -queue Helix queue to target (default: Windows.10.Amd64.Open)
+REM -accesstoken Helix access token for internal queues (optional)
+REM -creator Creator name for public builds (optional)
+REM -bl Generate binary log
+REM -help Show this help message
+
+setlocal enabledelayedexpansion
+
+set "EngRoot=%~dp0"
+set "EngRoot=%EngRoot:~0,-1%"
+for %%i in ("%EngRoot%\..") do set "RepoRoot=%%~fi"
+set "Configuration=Debug"
+set "Architecture=x64"
+set "TargetOS=Windows_NT"
+set "HelixQueue=Windows.10.Amd64"
+set "HelixAccessToken=AAAE1Eq55IR3-s8xjJvkFcHtmI0"
+set "Creator="
+set "BinaryLog="
+
+REM Parse arguments
+:parse_args
+if "%~1"=="" goto :done_parsing
+if /i "%~1"=="-configuration" (
+ set "Configuration=%~2"
+ shift
+ shift
+ goto :parse_args
+)
+if /i "%~1"=="-c" (
+ set "Configuration=%~2"
+ shift
+ shift
+ goto :parse_args
+)
+if /i "%~1"=="-architecture" (
+ set "Architecture=%~2"
+ shift
+ shift
+ goto :parse_args
+)
+if /i "%~1"=="-a" (
+ set "Architecture=%~2"
+ shift
+ shift
+ goto :parse_args
+)
+if /i "%~1"=="-queue" (
+ set "HelixQueue=%~2"
+ shift
+ shift
+ goto :parse_args
+)
+if /i "%~1"=="-accesstoken" (
+ set "HelixAccessToken=%~2"
+ shift
+ shift
+ goto :parse_args
+)
+if /i "%~1"=="-creator" (
+ set "Creator=%~2"
+ shift
+ shift
+ goto :parse_args
+)
+if /i "%~1"=="-bl" (
+ if not exist "%RepoRoot%\artifacts\helix-log" mkdir "%RepoRoot%\artifacts\helix-log"
+ set "BinaryLog=/bl:%RepoRoot%\artifacts\helix-log\SendToHelix.binlog"
+ shift
+ goto :parse_args
+)
+if /i "%~1"=="-help" goto :show_help
+if /i "%~1"=="-h" goto :show_help
+if /i "%~1"=="/?" goto :show_help
+
+echo Unknown argument: %~1
+goto :show_help
+
+:done_parsing
+
+REM Set required environment variables for local Helix execution
+if "%BUILD_SOURCEBRANCH%"=="" set "BUILD_SOURCEBRANCH=local"
+if "%BUILD_REPOSITORY_NAME%"=="" set "BUILD_REPOSITORY_NAME=diagnostics"
+if "%SYSTEM_TEAMPROJECT%"=="" set "SYSTEM_TEAMPROJECT=dnceng"
+if "%BUILD_REASON%"=="" set "BUILD_REASON=Manual"
+
+REM Build creator argument if specified
+set "CreatorArg="
+if not "%Creator%"=="" set "CreatorArg=/p:Creator=%Creator%"
+
+REM Build access token argument if specified
+set "AccessTokenArg="
+if not "%HelixAccessToken%"=="" set "AccessTokenArg=/p:HelixAccessToken=%HelixAccessToken%"
+
+echo.
+echo ===========================
+echo Sending tests to Helix
+echo ===========================
+echo Configuration: %Configuration%
+echo Architecture: %Architecture%
+echo Target OS: %TargetOS%
+echo Helix Queue: %HelixQueue%
+echo Artifacts Dir: %RepoRoot%\artifacts\
+echo.
+
+REM Verify artifacts exist
+if not exist "%RepoRoot%\artifacts\bin" (
+ echo ERROR: Build artifacts not found at %RepoRoot%\artifacts\bin
+ echo Please run Build.cmd first to build the tests.
+ exit /b 1
+)
+
+REM Send to Helix using PowerShell (use /tl:off to disable terminal logger for better output)
+REM The PrepareCorrelationPayload target runs automatically before Test
+REM Set environment variables in PowerShell scope for the Helix SDK to read
+powershell -ExecutionPolicy ByPass -NoProfile -command "$env:BUILD_SOURCEBRANCH='%BUILD_SOURCEBRANCH%'; $env:BUILD_REPOSITORY_NAME='%BUILD_REPOSITORY_NAME%'; $env:SYSTEM_TEAMPROJECT='%SYSTEM_TEAMPROJECT%'; $env:BUILD_REASON='%BUILD_REASON%'; & '%RepoRoot%\eng\common\msbuild.ps1' '%RepoRoot%\eng\helix.proj' /restore /t:Test /tl:off /p:Configuration=%Configuration% /p:TargetArchitecture=%Architecture% /p:TargetOS=%TargetOS% /p:HelixTargetQueues=%HelixQueue% /p:TestArtifactsDir='%RepoRoot%\artifacts\' /p:EnableAzurePipelinesReporter=false %AccessTokenArg% %CreatorArg% %BinaryLog%"
+
+if %ERRORLEVEL% neq 0 (
+ echo.
+ echo ERROR: Failed to send tests to Helix
+ exit /b %ERRORLEVEL%
+)
+
+echo.
+echo Tests submitted to Helix successfully!
+echo View results at: https://helix.dot.net/
+exit /b 0
+
+:show_help
+echo.
+echo Send diagnostics tests to Helix for remote execution.
+echo.
+echo Usage: send-to-helix.cmd [options]
+echo.
+echo Options:
+echo -configuration ^ Build configuration (default: Debug)
+echo -architecture ^ Target architecture (default: x64)
+echo -queue ^ Helix queue to target (default: Windows.10.Amd64.Open)
+echo -accesstoken ^ Helix access token for internal queues
+echo -creator ^ Creator name for public builds
+echo -bl Generate binary log
+echo -help Show this help message
+echo.
+echo Examples:
+echo send-to-helix.cmd
+echo send-to-helix.cmd -configuration Release -queue Windows.11.Amd64.Open
+echo send-to-helix.cmd -architecture arm64 -queue Windows.11.Arm64.Open
+echo send-to-helix.cmd -creator "MyName" -bl
+echo.
+echo Notes:
+echo - Run Build.cmd first to build the test artifacts
+echo - For internal queues (not ending in .Open), provide -accesstoken
+echo - Public queues require -creator to be set
+echo.
+echo Available public Windows queues:
+echo Windows.10.Amd64.Open
+echo Windows.11.Amd64.Open
+echo Windows.11.Arm64.Open
+echo.
+exit /b 0
diff --git a/eng/send-to-helix.sh b/eng/send-to-helix.sh
new file mode 100644
index 0000000000..e4e3232625
--- /dev/null
+++ b/eng/send-to-helix.sh
@@ -0,0 +1,217 @@
+#!/usr/bin/env bash
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+
+# Send diagnostics tests to Helix for remote execution.
+#
+# Usage: send-to-helix.sh [options]
+#
+# Options:
+# -configuration Build configuration (default: Debug)
+# -architecture Target architecture (default: x64)
+# -os Target OS (default: auto-detected)
+# -queue Helix queue to target (default: auto-selected based on OS)
+# -accesstoken Helix access token for internal queues (optional)
+# -creator Creator name for public builds (optional)
+# -bl Generate binary log
+# -help Show this help message
+
+set -e
+
+# Get script directory
+script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+repo_root="$(cd "$script_dir/.." && pwd)"
+
+# Default values
+configuration="Debug"
+architecture="x64"
+target_os=""
+helix_queue=""
+helix_access_token=""
+creator=""
+binary_log=""
+
+# Detect OS
+detect_os() {
+ case "$(uname -s)" in
+ Linux*) echo "linux" ;;
+ Darwin*) echo "osx" ;;
+ *) echo "unknown" ;;
+ esac
+}
+
+# Get default Helix queue based on OS and architecture
+get_default_queue() {
+ local os=$1
+ local arch=$2
+
+ case "$os" in
+ linux)
+ case "$arch" in
+ x64) echo "Ubuntu.2204.Amd64.Open" ;;
+ arm64) echo "Ubuntu.2204.Arm64.Open" ;;
+ *) echo "Ubuntu.2204.Amd64.Open" ;;
+ esac
+ ;;
+ osx)
+ case "$arch" in
+ x64) echo "OSX.1200.Amd64.Open" ;;
+ arm64) echo "OSX.1200.Arm64.Open" ;;
+ *) echo "OSX.1200.Amd64.Open" ;;
+ esac
+ ;;
+ *)
+ echo "Ubuntu.2204.Amd64.Open"
+ ;;
+ esac
+}
+
+show_help() {
+ cat << EOF
+
+Send diagnostics tests to Helix for remote execution.
+
+Usage: send-to-helix.sh [options]
+
+Options:
+ -configuration Build configuration (default: Debug)
+ -architecture Target architecture (default: x64)
+ -os Target OS (default: auto-detected)
+ -queue Helix queue to target (default: auto-selected based on OS)
+ -accesstoken Helix access token for internal queues
+ -creator Creator name for public builds
+ -bl Generate binary log
+ -help Show this help message
+
+Examples:
+ ./send-to-helix.sh
+ ./send-to-helix.sh -configuration Release -queue Ubuntu.2404.Amd64.Open
+ ./send-to-helix.sh -architecture arm64 -os linux
+ ./send-to-helix.sh -creator "MyName" -bl
+
+Notes:
+ - Run build.sh first to build the test artifacts
+ - For internal queues (not ending in .Open), provide -accesstoken
+ - Public queues require -creator to be set
+
+Available public Linux queues:
+ Ubuntu.2204.Amd64.Open
+ Ubuntu.2404.Amd64.Open
+ Ubuntu.2204.Arm64.Open
+ Debian.12.Amd64.Open
+
+Available public macOS queues:
+ OSX.1200.Amd64.Open
+ OSX.1200.Arm64.Open
+ OSX.1300.Amd64.Open
+
+EOF
+ exit 0
+}
+
+# Parse arguments
+while [[ $# -gt 0 ]]; do
+ opt="$(echo "${1}" | tr '[:upper:]' '[:lower:]')"
+ case "$opt" in
+ -configuration|-c)
+ configuration="$2"
+ shift 2
+ ;;
+ -architecture|-a)
+ architecture="$2"
+ shift 2
+ ;;
+ -os)
+ target_os="$2"
+ shift 2
+ ;;
+ -queue)
+ helix_queue="$2"
+ shift 2
+ ;;
+ -accesstoken)
+ helix_access_token="$2"
+ shift 2
+ ;;
+ -creator)
+ creator="$2"
+ shift 2
+ ;;
+ -bl)
+ binary_log="/bl:$repo_root/artifacts/log/$configuration/SendToHelix.binlog"
+ shift
+ ;;
+ -help|-h|--help)
+ show_help
+ ;;
+ *)
+ echo "Unknown argument: $1"
+ show_help
+ ;;
+ esac
+done
+
+# Auto-detect OS if not specified
+if [[ -z "$target_os" ]]; then
+ target_os=$(detect_os)
+fi
+
+# Auto-select queue if not specified
+if [[ -z "$helix_queue" ]]; then
+ helix_queue=$(get_default_queue "$target_os" "$architecture")
+fi
+
+# Set required environment variables for local Helix execution
+export BUILD_SOURCEBRANCH="${BUILD_SOURCEBRANCH:-local}"
+export BUILD_REPOSITORY_NAME="${BUILD_REPOSITORY_NAME:-diagnostics}"
+export SYSTEM_TEAMPROJECT="${SYSTEM_TEAMPROJECT:-dnceng}"
+export BUILD_REASON="${BUILD_REASON:-Manual}"
+
+# Build optional arguments
+creator_arg=""
+if [[ -n "$creator" ]]; then
+ creator_arg="/p:Creator=$creator"
+fi
+
+access_token_arg=""
+if [[ -n "$helix_access_token" ]]; then
+ access_token_arg="/p:HelixAccessToken=$helix_access_token"
+fi
+
+echo ""
+echo "==========================="
+echo "Sending tests to Helix"
+echo "==========================="
+echo "Configuration: $configuration"
+echo "Architecture: $architecture"
+echo "Target OS: $target_os"
+echo "Helix Queue: $helix_queue"
+echo "Artifacts Dir: $repo_root/artifacts/"
+echo ""
+
+# Verify artifacts exist
+if [[ ! -d "$repo_root/artifacts/bin" ]]; then
+ echo "ERROR: Build artifacts not found at $repo_root/artifacts/bin"
+ echo "Please run build.sh first to build the tests."
+ exit 1
+fi
+
+# Send to Helix (use -tl:off to disable terminal logger for better output)
+"$repo_root/eng/common/msbuild.sh" \
+ "$repo_root/eng/helix.proj" \
+ /restore \
+ /t:Test \
+ -tl:off \
+ /p:Configuration="$configuration" \
+ /p:TargetArchitecture="$architecture" \
+ /p:TargetOS="$target_os" \
+ /p:HelixTargetQueues="$helix_queue" \
+ /p:TestArtifactsDir="$repo_root/artifacts/" \
+ /p:EnableAzurePipelinesReporter=false \
+ $access_token_arg \
+ $creator_arg \
+ $binary_log
+
+echo ""
+echo "Tests submitted to Helix successfully!"
+echo "View results at: https://helix.dot.net/"
diff --git a/src/Microsoft.Diagnostics.TestHelpers/TestConfiguration.cs b/src/Microsoft.Diagnostics.TestHelpers/TestConfiguration.cs
index 01821e3244..ccbd53dae2 100644
--- a/src/Microsoft.Diagnostics.TestHelpers/TestConfiguration.cs
+++ b/src/Microsoft.Diagnostics.TestHelpers/TestConfiguration.cs
@@ -38,6 +38,10 @@ private static TestRunConfiguration ParseDefaultConfigFile()
private readonly DateTime _timestamp = DateTime.Now;
+ // Properties set from Helix environment variables that should not be overwritten
+ // by values in imported config files (e.g., Debugger.Tests.Common.txt).
+ private readonly HashSet _helixProtectedProperties = new();
+
public IEnumerable Configurations { get; private set; }
private void ParseConfigFile(string path)
@@ -86,7 +90,35 @@ private void ParseConfigFile(string path)
{
initialConfig["WinDir"] = Path.GetFullPath(Environment.GetEnvironmentVariable("WINDIR"));
}
+
+ // On Helix, override ArtifactsDir and DotNetRoot before parsing config files
+ // so all $(ArtifactsDir) and $(DotNetRoot) references resolve to Helix paths.
+ // These are marked as protected so imported config files cannot overwrite them.
+ if (Environment.GetEnvironmentVariable("RunningOnHelix") == "true")
+ {
+ initialConfig["RunningOnHelix"] = "true";
+
+ string helixArtifactsDir = Environment.GetEnvironmentVariable("DIAGNOSTICS_ARTIFACTS_DIR");
+ if (!string.IsNullOrEmpty(helixArtifactsDir))
+ {
+ initialConfig["ArtifactsDir"] = helixArtifactsDir;
+ _helixProtectedProperties.Add("ArtifactsDir");
+ }
+
+ string helixDotNetRoot = Environment.GetEnvironmentVariable("DOTNET_ROOT");
+ if (string.IsNullOrEmpty(helixDotNetRoot))
+ {
+ helixDotNetRoot = Environment.GetEnvironmentVariable("DIAGNOSTICS_DOTNET_ROOT");
+ }
+ if (!string.IsNullOrEmpty(helixDotNetRoot))
+ {
+ initialConfig["DotNetRoot"] = helixDotNetRoot;
+ _helixProtectedProperties.Add("DotNetRoot");
+ }
+ }
+
IEnumerable> configs = ParseConfigFile(path, new Dictionary[] { initialConfig });
+
Configurations = configs.Select(c => new TestConfiguration(c)).ToList();
}
@@ -179,6 +211,11 @@ private Dictionary[] ParseConfigSetting(Dictionary
Date: Fri, 13 Feb 2026 11:02:43 -0500
Subject: [PATCH 06/48] move version defs to versions.props so they are defined
in helix
---
Directory.Build.props | 17 -----------
eng/Versions.props | 18 ++++++++++++
eng/helix.proj | 67 ++++++++++++++-----------------------------
3 files changed, 40 insertions(+), 62 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index c2fceffbab..02acad504c 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -57,21 +57,4 @@
$(TargetRidOS)-$(TargetArch)
-
- net462
-
- 8.0
- net$(NetCoreAppMinVersion)
-
- net8.0;net9.0;net10.0
-
- net8.0
-
-
diff --git a/eng/Versions.props b/eng/Versions.props
index 52988e350d..4f3961966d 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -98,6 +98,24 @@
true
-runtimesourcefeed '$(RuntimeSourceFeed)' -runtimesourcefeedkey '$(RuntimeSourceFeedKey)'
+
+
+ net462
+
+ 8.0
+ net$(NetCoreAppMinVersion)
+
+ net8.0;net9.0;net10.0
+
+ net8.0
+
+
$(MicrosoftNETCorePlatformsVersion)
diff --git a/eng/helix.proj b/eng/helix.proj
index 452633dc7d..2e0356e18a 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -45,7 +45,7 @@
true
sdk
- 10.0.102
+ $([System.Text.RegularExpressions.Regex]::Match('$(MicrosoftNETSdkVersion)', '^\d+\.\d+\.\d+').Value)
<_CorrelationPayload Condition="'$(TargetOS)' == 'Windows_NT'">%HELIX_CORRELATION_PAYLOAD%
@@ -62,6 +62,10 @@
set "DIAGNOSTICS_ARTIFACTS_DIR=$(_ArtifactsDir)" && set "RunningOnHelix=true" && copy /Y "$(_VersionsFile)" "$(_DotNetCliDir)$(_PathSep)Debugger.Tests.Versions.txt"
export DIAGNOSTICS_ARTIFACTS_DIR="$(_ArtifactsDir)" && export RunningOnHelix=true && cp -f "$(_VersionsFile)" "$(_DotNetCliDir)/Debugger.Tests.Versions.txt"
+
+
+
+
<_VersionsStagingDir>$(ArtifactsDir)tmp\helix\dotnet-test\
@@ -82,26 +86,20 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -209,32 +207,11 @@
-
-
-
- $(TestArtifactsDir)bin\%(HelixPureTestProject.Identity)\$(Configuration)\$(NetCoreAppMinTargetFramework)
- dotnet test %(HelixPureTestProject.Identity).dll --logger "trx;LogFileName=%(HelixPureTestProject.Identity).trx" --results-directory $(_UploadRoot)
- $(TestTimeout)
-
-
-
-
-
-
- $(TestArtifactsDir)bin\%(HelixComplexTestProject.Identity)\$(Configuration)\$(NetCoreAppMinTargetFramework)
- dotnet test %(HelixComplexTestProject.Identity).dll --logger "trx;LogFileName=%(HelixComplexTestProject.Identity).trx" --results-directory $(_UploadRoot)
- $(TestTimeout)
-
-
-
-
-
- $(TestArtifactsDir)bin\%(HelixNativeTestProject.Identity)\$(Configuration)\$(NetCoreAppMinTargetFramework)
- dotnet test %(HelixNativeTestProject.Identity).dll --logger "trx;LogFileName=%(HelixNativeTestProject.Identity).trx" --results-directory $(_UploadRoot)
+
+ $(TestArtifactsDir)bin\%(HelixTestProject.Identity)\$(Configuration)\$(NetCoreAppMinTargetFramework)
+ dotnet test %(HelixTestProject.Identity).dll --logger "trx;LogFileName=$(_UploadRoot)\%(HelixTestProject.Identity).trx"
$(TestTimeout)
From ba1562403ed718ac514528ae878955b6029e15a9 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 11:03:01 -0500
Subject: [PATCH 07/48] update queues to use windows server 2022
---
eng/pipelines/global-variables.yml | 4 ++--
eng/send-to-helix.cmd | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/eng/pipelines/global-variables.yml b/eng/pipelines/global-variables.yml
index 3b5cadd6ef..99bdff7f53 100644
--- a/eng/pipelines/global-variables.yml
+++ b/eng/pipelines/global-variables.yml
@@ -79,9 +79,9 @@ variables:
# Internal queues for official builds
- ${{ if ne(variables['System.TeamProject'], 'public') }}:
- name: HelixQueuesWindows_x64
- value: Windows.10.Amd64
+ value: windows.amd64.server2022
- name: HelixQueuesWindows_x86
- value: Windows.10.Amd64
+ value: windows.amd64.server2022
- name: HelixQueuesLinux_x64
value: Ubuntu.2204.Amd64
- name: HelixQueuesLinux_arm64
diff --git a/eng/send-to-helix.cmd b/eng/send-to-helix.cmd
index cce321a0bd..c9cdde80a2 100644
--- a/eng/send-to-helix.cmd
+++ b/eng/send-to-helix.cmd
@@ -23,7 +23,7 @@ for %%i in ("%EngRoot%\..") do set "RepoRoot=%%~fi"
set "Configuration=Debug"
set "Architecture=x64"
set "TargetOS=Windows_NT"
-set "HelixQueue=Windows.10.Amd64"
+set "HelixQueue=windows.amd64.server2022"
set "HelixAccessToken=AAAE1Eq55IR3-s8xjJvkFcHtmI0"
set "Creator="
set "BinaryLog="
From 9ce16943a65325e33bbf77aae0445d54e83d63bf Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 11:17:02 -0500
Subject: [PATCH 08/48] add check in CollectCommand to not crash if file is not
created
---
src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs b/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs
index c72f43686c..4d74f8a95b 100644
--- a/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs
+++ b/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs
@@ -400,7 +400,8 @@ internal async Task Collect(CancellationToken ct, CommandLineConfiguration
wroteStatus = true;
}
fileInfo.Refresh();
- ConsoleWriteLine($"[{stopwatch.Elapsed:dd\\:hh\\:mm\\:ss}]\tRecording trace {GetSize(fileInfo.Length)}");
+ long fileLength = fileInfo.Exists ? fileInfo.Length : 0;
+ ConsoleWriteLine($"[{stopwatch.Elapsed:dd\\:hh\\:mm\\:ss}]\tRecording trace {GetSize(fileLength)}");
ConsoleWriteLine("Press or to exit...");
}
From 925e9b961c3c065b9c82f0b2cbbc2cb5560ffe57 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 11:23:12 -0500
Subject: [PATCH 09/48] use helix in CI
---
diagnostics.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/diagnostics.yml b/diagnostics.yml
index fa9efc693b..d89706d3d0 100644
--- a/diagnostics.yml
+++ b/diagnostics.yml
@@ -22,7 +22,7 @@ parameters:
- name: useHelix
displayName: Run tests on Helix (distributed testing)
type: boolean
- default: false
+ default: true
trigger: none
From 0835b43057406c7d5709ea7d3aef92d4423bc4f8 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 12:01:38 -0500
Subject: [PATCH 10/48] fix pipeline
---
eng/pipelines/helix.yml | 46 +++++++++++++++++++++++++++++++++++++----
1 file changed, 42 insertions(+), 4 deletions(-)
diff --git a/eng/pipelines/helix.yml b/eng/pipelines/helix.yml
index 53d9045f16..4b55e529b3 100644
--- a/eng/pipelines/helix.yml
+++ b/eng/pipelines/helix.yml
@@ -135,10 +135,29 @@ jobs:
/p:HelixSource=$(_HelixSource)
/p:HelixType=$(_HelixType)
/p:HelixAccessToken=$(_HelixAccessToken)
- ${{ if eq(parameters.isInternal, false) }}:/p:Creator=$(_Creator)
/p:TestArtifactsDir=$(Build.SourcesDirectory)/artifacts/
/bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
- displayName: Send Tests to Helix
+ displayName: Send Tests to Helix (internal)
+ condition: and(succeeded(), eq('${{ parameters.isInternal }}', 'True'))
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+
+ - script: >
+ $(Build.SourcesDirectory)\eng\common\msbuild.cmd
+ $(Build.SourcesDirectory)\eng\helix.proj
+ /restore
+ /t:Test
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=$(_TargetOS)
+ /p:HelixTargetQueues=$(_HelixQueues)
+ /p:HelixSource=$(_HelixSource)
+ /p:HelixType=$(_HelixType)
+ /p:Creator=$(_Creator)
+ /p:TestArtifactsDir=$(Build.SourcesDirectory)/artifacts/
+ /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
+ displayName: Send Tests to Helix (public)
+ condition: and(succeeded(), ne('${{ parameters.isInternal }}', 'True'))
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
@@ -155,10 +174,29 @@ jobs:
/p:HelixSource=$(_HelixSource)
/p:HelixType=$(_HelixType)
/p:HelixAccessToken=$(_HelixAccessToken)
- ${{ if eq(parameters.isInternal, false) }}:/p:Creator=$(_Creator)
/p:TestArtifactsDir=$(Build.SourcesDirectory)/artifacts/
/bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
- displayName: Send Tests to Helix
+ displayName: Send Tests to Helix (internal)
+ condition: and(succeeded(), eq('${{ parameters.isInternal }}', 'True'))
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+
+ - script: >
+ $(Build.SourcesDirectory)/eng/common/msbuild.sh
+ $(Build.SourcesDirectory)/eng/helix.proj
+ /restore
+ /t:Test
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=$(_TargetOS)
+ /p:HelixTargetQueues=$(_HelixQueues)
+ /p:HelixSource=$(_HelixSource)
+ /p:HelixType=$(_HelixType)
+ /p:Creator=$(_Creator)
+ /p:TestArtifactsDir=$(Build.SourcesDirectory)/artifacts/
+ /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
+ displayName: Send Tests to Helix (public)
+ condition: and(succeeded(), ne('${{ parameters.isInternal }}', 'True'))
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
From 9bd642599b1ec604a8dbf9580a1e7c7087e6e518 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 13:08:06 -0500
Subject: [PATCH 11/48] refactor props to use Common.props
---
Directory.Build.props | 16 +++++-----
eng/AuxMsbuildFiles/Directory.Build.props | 1 +
eng/Common.props | 38 +++++++++++++++++++++++
eng/Versions.props | 17 ----------
src/tests/Directory.Build.targets | 7 +++--
5 files changed, 51 insertions(+), 28 deletions(-)
create mode 100644 eng/Common.props
diff --git a/Directory.Build.props b/Directory.Build.props
index 02acad504c..b92fa8c8f7 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -4,15 +4,6 @@
false
-
- false
- Latest
- 4
- true
- true
- <_SkipUpgradeNetAnalyzersNuGetWarning>true
-
-
http://go.microsoft.com/fwlink/?LinkID=288859
git
@@ -21,6 +12,13 @@
diagnostics
+
+
+
+
+ Latest
+ false
+ 4
+ true
+ true
+ <_SkipUpgradeNetAnalyzersNuGetWarning>true
+
+ net462
+
+ 8.0
+ net$(NetCoreAppMinVersion)
+
+ net8.0;net9.0;net10.0
+
+ net8.0
+
+
diff --git a/eng/Versions.props b/eng/Versions.props
index 4f3961966d..fd526a554a 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -99,23 +99,6 @@
-runtimesourcefeed '$(RuntimeSourceFeed)' -runtimesourcefeedkey '$(RuntimeSourceFeedKey)'
-
- net462
-
- 8.0
- net$(NetCoreAppMinVersion)
-
- net8.0;net9.0;net10.0
-
- net8.0
-
-
$(MicrosoftNETCorePlatformsVersion)
diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets
index 9061e8ca91..8ee633b6fb 100644
--- a/src/tests/Directory.Build.targets
+++ b/src/tests/Directory.Build.targets
@@ -35,14 +35,17 @@
<_AuxDir>$(ArtifactsDir)test/AuxMsbuildFiles/
+
From d129cc91abb2a356ad31d3cd6c62e51d59e07a00 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 13:08:27 -0500
Subject: [PATCH 12/48] refactor race condition fix for dotnet trace unittests
---
src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs | 3 +--
src/tests/dotnet-trace/CollectCommandFunctionalTests.cs | 4 ++++
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs b/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs
index 4d74f8a95b..c72f43686c 100644
--- a/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs
+++ b/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs
@@ -400,8 +400,7 @@ internal async Task Collect(CancellationToken ct, CommandLineConfiguration
wroteStatus = true;
}
fileInfo.Refresh();
- long fileLength = fileInfo.Exists ? fileInfo.Length : 0;
- ConsoleWriteLine($"[{stopwatch.Elapsed:dd\\:hh\\:mm\\:ss}]\tRecording trace {GetSize(fileLength)}");
+ ConsoleWriteLine($"[{stopwatch.Elapsed:dd\\:hh\\:mm\\:ss}]\tRecording trace {GetSize(fileInfo.Length)}");
ConsoleWriteLine("Press or to exit...");
}
diff --git a/src/tests/dotnet-trace/CollectCommandFunctionalTests.cs b/src/tests/dotnet-trace/CollectCommandFunctionalTests.cs
index 634834b07c..a0a4b076d3 100644
--- a/src/tests/dotnet-trace/CollectCommandFunctionalTests.cs
+++ b/src/tests/dotnet-trace/CollectCommandFunctionalTests.cs
@@ -91,6 +91,10 @@ public async Task CollectCommand_InvalidProcessSpecifierConfigurations(CollectAr
private static async Task RunAsync(CollectArgs config, MockConsole console, bool hasChildProcess = false)
{
+ // Suppress timing-dependent status output (e.g. "Recording trace 0.00 (B)")
+ // so tests can validate provider configuration output deterministically.
+ console.IsOutputRedirected = true;
+
var handler = new CollectCommandHandler(console);
handler.StartTraceSessionAsync = (client, cfg, ct) => Task.FromResult(new TestCollectSession());
handler.ResumeRuntimeAsync = (client, ct) => Task.CompletedTask;
From 810fe9ef37c11462496b769dbfdfdd67813aa7c8 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 13:08:42 -0500
Subject: [PATCH 13/48] update pipelines
---
diagnostics.yml | 109 +++++++++--------------------
eng/pipelines/global-variables.yml | 4 ++
eng/pipelines/helix.yml | 43 ++++++------
3 files changed, 59 insertions(+), 97 deletions(-)
diff --git a/diagnostics.yml b/diagnostics.yml
index d89706d3d0..854f809872 100644
--- a/diagnostics.yml
+++ b/diagnostics.yml
@@ -56,7 +56,7 @@ extends:
parameters:
stages:
- stage: build
- displayName: Build and Test Diagnostics
+ displayName: Build Diagnostics
jobs:
############################
@@ -83,7 +83,7 @@ extends:
jobTemplate: ${{ variables.jobTemplate }}
name: Windows
osGroup: Windows_NT
- buildOnly: ${{ parameters.buildOnly }}
+ buildOnly: true
buildConfigs:
- configuration: Debug
architecture: x64
@@ -138,7 +138,7 @@ extends:
parameters:
jobTemplate: ${{ variables.jobTemplate }}
osGroup: MacOS
- buildOnly: ${{ parameters.buildOnly }}
+ buildOnly: true
buildConfigs:
- configuration: Release
architecture: x64
@@ -218,84 +218,15 @@ extends:
############################
# #
- # Test only legs #
+ # Helix Test Stage #
# #
############################
- - ${{ if ne(parameters.buildOnly, true) }}:
- - template: /eng/pipelines/build.yml
- parameters:
- jobTemplate: ${{ variables.jobTemplate }}
- name: Ubuntu_22_04
- osGroup: Linux
- container: test_ubuntu_22_04
- dependsOn: Linux
- testOnly: true
- buildConfigs:
- - configuration: Release
- architecture: x64
- - ${{ if in(variables['Build.Reason'], 'PullRequest') }}:
- - configuration: Debug
- architecture: x64
-
- - template: /eng/pipelines/build.yml
- parameters:
- jobTemplate: ${{ variables.jobTemplate }}
- name: Alpine3_19
- osGroup: Linux
- osSuffix: -musl
- container: test_linux_musl_x64
- dependsOn: Linux_musl
- testOnly: true
- disableComponentGovernance: true
- buildConfigs:
- - configuration: Release
- architecture: x64
- - ${{ if in(variables['Build.Reason'], 'PullRequest') }}:
- - configuration: Debug
- architecture: x64
-
- - ${{ if ne(variables['System.TeamProject'], 'public') }}:
- - template: /eng/pipelines/build.yml
- parameters:
- jobTemplate: ${{ variables.jobTemplate }}
- name: Debian_Bullseye
- osGroup: Linux
- container: test_debian_11_amd64
- dependsOn: Linux
- testOnly: true
- buildConfigs:
- - configuration: Release
- architecture: x64
- - ${{ if in(variables['Build.Reason'], 'PullRequest') }}:
- - configuration: Debug
- architecture: x64
-
- - template: /eng/pipelines/build.yml
- parameters:
- jobTemplate: ${{ variables.jobTemplate }}
- name: Fedora_39
- osGroup: Linux
- container: test_fedora
- dependsOn: Linux
- testOnly: true
- buildConfigs:
- - configuration: Release
- architecture: x64
- - ${{ if in(variables['Build.Reason'], 'PullRequest') }}:
- - configuration: Debug
- architecture: x64
-
- ############################
- # #
- # Helix Test Stage #
- # #
- ############################
-
- ${{ if and(eq(parameters.useHelix, true), ne(parameters.buildOnly, true)) }}:
- stage: helix
displayName: Run Tests on Helix
dependsOn: build
+ condition: not(canceled())
jobs:
# Windows x64 Helix tests
- template: /eng/pipelines/helix.yml
@@ -333,11 +264,37 @@ extends:
isInternal: ${{ ne(variables['System.TeamProject'], 'public') }}
dependsOn: MacOS_x64_Release
+ # Windows arm64 Helix tests
+ - template: /eng/pipelines/helix.yml
+ parameters:
+ name: Helix_Windows
+ jobTemplate: ${{ variables.jobTemplate }}
+ osGroup: Windows_NT
+ configuration: Release
+ architecture: arm64
+ helixQueues: $(HelixQueuesWindows_arm64)
+ isInternal: ${{ ne(variables['System.TeamProject'], 'public') }}
+ dependsOn: Windows_arm64_Release
+
+ # Linux arm64 Helix tests
+ - template: /eng/pipelines/helix.yml
+ parameters:
+ name: Helix_Linux
+ jobTemplate: ${{ variables.jobTemplate }}
+ osGroup: Linux
+ configuration: Release
+ architecture: arm64
+ helixQueues: $(HelixQueuesLinux_arm64)
+ isInternal: ${{ ne(variables['System.TeamProject'], 'public') }}
+ dependsOn: Linux_arm64_Release
+
- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- stage: package
displayName: Package, Sign, and Generate BAR Manifests
- ${{ if eq(parameters.useHelix, true) }}:
- dependsOn: helix
+ ${{ if and(eq(parameters.useHelix, true), ne(parameters.buildOnly, true)) }}:
+ dependsOn:
+ - build
+ - helix
${{ else }}:
dependsOn: build
jobs:
diff --git a/eng/pipelines/global-variables.yml b/eng/pipelines/global-variables.yml
index 99bdff7f53..53522d8c02 100644
--- a/eng/pipelines/global-variables.yml
+++ b/eng/pipelines/global-variables.yml
@@ -65,6 +65,8 @@ variables:
value: Windows.10.Amd64.Open
- name: HelixQueuesWindows_x86
value: Windows.10.Amd64.Open
+ - name: HelixQueuesWindows_arm64
+ value: Windows.11.Arm64.Open
- name: HelixQueuesLinux_x64
value: Ubuntu.2204.Amd64.Open
- name: HelixQueuesLinux_arm64
@@ -82,6 +84,8 @@ variables:
value: windows.amd64.server2022
- name: HelixQueuesWindows_x86
value: windows.amd64.server2022
+ - name: HelixQueuesWindows_arm64
+ value: windows.11.arm64
- name: HelixQueuesLinux_x64
value: Ubuntu.2204.Amd64
- name: HelixQueuesLinux_arm64
diff --git a/eng/pipelines/helix.yml b/eng/pipelines/helix.yml
index 4b55e529b3..1166f95d2c 100644
--- a/eng/pipelines/helix.yml
+++ b/eng/pipelines/helix.yml
@@ -1,5 +1,6 @@
# Pipeline template for running tests on Helix
-# This template sends test workloads to Helix machines for distributed execution
+# This template downloads build artifacts and sends test workloads to Helix
+# machines for distributed execution.
parameters:
# Job name suffix
@@ -47,7 +48,7 @@ parameters:
type: number
default: 120
- # Job dependencies (build job name without architecture/configuration suffix)
+ # Job dependency name for artifact download (e.g. Windows_x64_Release)
- name: dependsOn
type: string
default: ''
@@ -63,11 +64,7 @@ jobs:
name: ${{ parameters.name }}_${{ parameters.architecture }}_${{ parameters.configuration }}
timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
templateContext: ${{ parameters.templateContext }}
-
- # Note: cross-stage job dependencies are not supported in Azure Pipelines.
- # The stage-level dependsOn handles this. We keep dependsOn parameter for
- # artifact naming only.
-
+
pool:
${{ if eq(parameters.osGroup, 'Windows_NT') }}:
name: $(BuildPool)
@@ -90,7 +87,7 @@ jobs:
variables:
- _BuildConfig: ${{ parameters.configuration }}
- _HelixType: test/${{ parameters.configuration }}/${{ parameters.architecture }}/
-
+
# Determine target OS for helix.proj
- ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
- _TargetOS: Windows_NT
@@ -98,10 +95,16 @@ jobs:
- _TargetOS: linux
- ${{ if eq(parameters.osGroup, 'MacOS') }}:
- _TargetOS: osx
-
+
+ # Build script
+ - ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
+ - _buildScript: $(Build.SourcesDirectory)\build.cmd
+ - ${{ if ne(parameters.osGroup, 'Windows_NT') }}:
+ - _buildScript: $(Build.SourcesDirectory)/build.sh
+
# Helix queue configuration
- _HelixQueues: ${{ parameters.helixQueues }}
-
+
# For internal builds, use the Helix access token
- ${{ if eq(parameters.isInternal, true) }}:
- group: DotNet-HelixApi-Access
@@ -113,13 +116,15 @@ jobs:
- _Creator: $(Build.RequestedFor)
steps:
- # Download build artifacts from the build job
- - task: DownloadPipelineArtifact@2
- displayName: 'Download Build Artifacts'
- inputs:
- targetPath: '$(Build.SourcesDirectory)/artifacts'
- artifactName: Build_${{ parameters.dependsOn }}
- checkDownloadedFiles: true
+ # Build locally (build-only, no tests) to produce test assemblies and artifacts
+ - script: $(_buildScript)
+ -ci
+ -binaryLog
+ -configuration ${{ parameters.configuration }}
+ -architecture ${{ parameters.architecture }}
+ /p:OfficialBuildId=$(BUILD.BUILDNUMBER)
+ displayName: Build
+ condition: succeeded()
# Send tests to Helix
- ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
@@ -135,7 +140,6 @@ jobs:
/p:HelixSource=$(_HelixSource)
/p:HelixType=$(_HelixType)
/p:HelixAccessToken=$(_HelixAccessToken)
- /p:TestArtifactsDir=$(Build.SourcesDirectory)/artifacts/
/bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
displayName: Send Tests to Helix (internal)
condition: and(succeeded(), eq('${{ parameters.isInternal }}', 'True'))
@@ -154,7 +158,6 @@ jobs:
/p:HelixSource=$(_HelixSource)
/p:HelixType=$(_HelixType)
/p:Creator=$(_Creator)
- /p:TestArtifactsDir=$(Build.SourcesDirectory)/artifacts/
/bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
displayName: Send Tests to Helix (public)
condition: and(succeeded(), ne('${{ parameters.isInternal }}', 'True'))
@@ -174,7 +177,6 @@ jobs:
/p:HelixSource=$(_HelixSource)
/p:HelixType=$(_HelixType)
/p:HelixAccessToken=$(_HelixAccessToken)
- /p:TestArtifactsDir=$(Build.SourcesDirectory)/artifacts/
/bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
displayName: Send Tests to Helix (internal)
condition: and(succeeded(), eq('${{ parameters.isInternal }}', 'True'))
@@ -193,7 +195,6 @@ jobs:
/p:HelixSource=$(_HelixSource)
/p:HelixType=$(_HelixType)
/p:Creator=$(_Creator)
- /p:TestArtifactsDir=$(Build.SourcesDirectory)/artifacts/
/bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
displayName: Send Tests to Helix (public)
condition: and(succeeded(), ne('${{ parameters.isInternal }}', 'True'))
From 4f57f9adf00071a41e88f691cddf60256051cced Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 13:53:25 -0500
Subject: [PATCH 14/48] update pipelines
---
diagnostics.yml | 107 +++-----------
eng/pipelines/build.yml | 85 ++++-------
eng/pipelines/global-variables.yml | 12 +-
eng/pipelines/helix.yml | 222 -----------------------------
eng/pipelines/send-to-helix.yml | 138 ++++++++++++++++++
5 files changed, 193 insertions(+), 371 deletions(-)
delete mode 100644 eng/pipelines/helix.yml
create mode 100644 eng/pipelines/send-to-helix.yml
diff --git a/diagnostics.yml b/diagnostics.yml
index 854f809872..1d74c38f4d 100644
--- a/diagnostics.yml
+++ b/diagnostics.yml
@@ -83,7 +83,9 @@ extends:
jobTemplate: ${{ variables.jobTemplate }}
name: Windows
osGroup: Windows_NT
- buildOnly: true
+ buildOnly: ${{ parameters.buildOnly }}
+ useHelix: ${{ parameters.useHelix }}
+ helixQueues: $(HelixQueuesWindows_x64)
buildConfigs:
- configuration: Debug
architecture: x64
@@ -104,7 +106,9 @@ extends:
osGroup: Linux
container: linux_x64
crossBuild: true
- buildOnly: true
+ buildOnly: ${{ parameters.buildOnly }}
+ useHelix: ${{ parameters.useHelix }}
+ helixQueues: $(HelixQueuesLinux_x64)
buildConfigs:
- configuration: Release
architecture: x64
@@ -122,7 +126,9 @@ extends:
osSuffix: -musl
container: linux_musl_x64
crossBuild: true
- buildOnly: true
+ buildOnly: ${{ parameters.buildOnly }}
+ useHelix: ${{ parameters.useHelix }}
+ helixQueues: $(HelixQueuesLinux_musl_x64)
buildConfigs:
- configuration: Release
architecture: x64
@@ -138,7 +144,9 @@ extends:
parameters:
jobTemplate: ${{ variables.jobTemplate }}
osGroup: MacOS
- buildOnly: true
+ buildOnly: ${{ parameters.buildOnly }}
+ useHelix: ${{ parameters.useHelix }}
+ helixQueues: $(HelixQueuesMacOS_x64)
buildConfigs:
- configuration: Release
architecture: x64
@@ -152,7 +160,9 @@ extends:
jobTemplate: ${{ variables.jobTemplate }}
osGroup: MacOS
crossBuild: true
- buildOnly: true
+ buildOnly: ${{ parameters.buildOnly }}
+ useHelix: ${{ parameters.useHelix }}
+ helixQueues: $(HelixQueuesMacOS_arm64)
buildConfigs:
- configuration: Release
architecture: arm64
@@ -180,7 +190,9 @@ extends:
osGroup: Linux
container: linux_arm64
crossBuild: true
- buildOnly: true
+ buildOnly: ${{ parameters.buildOnly }}
+ useHelix: ${{ parameters.useHelix }}
+ helixQueues: $(HelixQueuesLinux_arm64)
buildConfigs:
- configuration: Release
architecture: arm64
@@ -209,94 +221,19 @@ extends:
osSuffix: -musl
container: linux_musl_arm64
crossBuild: true
- buildOnly: true
+ buildOnly: ${{ parameters.buildOnly }}
+ useHelix: ${{ parameters.useHelix }}
+ helixQueues: $(HelixQueuesLinux_musl_arm64)
buildConfigs:
- configuration: Release
architecture: arm64
artifactUploadPath: bin/linux.arm64.Release
artifactTargetPath: bin/linux-musl.arm64.Release
- ############################
- # #
- # Helix Test Stage #
- # #
- ############################
-
- - ${{ if and(eq(parameters.useHelix, true), ne(parameters.buildOnly, true)) }}:
- - stage: helix
- displayName: Run Tests on Helix
- dependsOn: build
- condition: not(canceled())
- jobs:
- # Windows x64 Helix tests
- - template: /eng/pipelines/helix.yml
- parameters:
- name: Helix_Windows
- jobTemplate: ${{ variables.jobTemplate }}
- osGroup: Windows_NT
- configuration: Release
- architecture: x64
- helixQueues: $(HelixQueuesWindows_x64)
- isInternal: ${{ ne(variables['System.TeamProject'], 'public') }}
- dependsOn: Windows_x64_Release
-
- # Linux x64 Helix tests
- - template: /eng/pipelines/helix.yml
- parameters:
- name: Helix_Linux
- jobTemplate: ${{ variables.jobTemplate }}
- osGroup: Linux
- configuration: Release
- architecture: x64
- helixQueues: $(HelixQueuesLinux_x64)
- isInternal: ${{ ne(variables['System.TeamProject'], 'public') }}
- dependsOn: Linux_x64_Release
-
- # MacOS x64 Helix tests
- - template: /eng/pipelines/helix.yml
- parameters:
- name: Helix_MacOS
- jobTemplate: ${{ variables.jobTemplate }}
- osGroup: MacOS
- configuration: Release
- architecture: x64
- helixQueues: $(HelixQueuesMacOS_x64)
- isInternal: ${{ ne(variables['System.TeamProject'], 'public') }}
- dependsOn: MacOS_x64_Release
-
- # Windows arm64 Helix tests
- - template: /eng/pipelines/helix.yml
- parameters:
- name: Helix_Windows
- jobTemplate: ${{ variables.jobTemplate }}
- osGroup: Windows_NT
- configuration: Release
- architecture: arm64
- helixQueues: $(HelixQueuesWindows_arm64)
- isInternal: ${{ ne(variables['System.TeamProject'], 'public') }}
- dependsOn: Windows_arm64_Release
-
- # Linux arm64 Helix tests
- - template: /eng/pipelines/helix.yml
- parameters:
- name: Helix_Linux
- jobTemplate: ${{ variables.jobTemplate }}
- osGroup: Linux
- configuration: Release
- architecture: arm64
- helixQueues: $(HelixQueuesLinux_arm64)
- isInternal: ${{ ne(variables['System.TeamProject'], 'public') }}
- dependsOn: Linux_arm64_Release
-
- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- stage: package
displayName: Package, Sign, and Generate BAR Manifests
- ${{ if and(eq(parameters.useHelix, true), ne(parameters.buildOnly, true)) }}:
- dependsOn:
- - build
- - helix
- ${{ else }}:
- dependsOn: build
+ dependsOn: build
jobs:
- template: /eng/common/templates-official/job/job.yml
parameters:
diff --git a/eng/pipelines/build.yml b/eng/pipelines/build.yml
index ba061cc2f2..d144caadd5 100644
--- a/eng/pipelines/build.yml
+++ b/eng/pipelines/build.yml
@@ -50,25 +50,16 @@ parameters:
type: string
default: ''
- # Optional: build only job if true
+ # Optional: build only, skip tests
- name: buildOnly
type: boolean
default: false
- # Optional: test only job if true
-- name: testOnly
- type: boolean
- default: false
-
# Optional: architecture cross build if true
- name: crossBuild
type: boolean
default: false
-- name: dependsOn
- type: string
- default: ''
-
- name: isCodeQLRun
type: boolean
default: false
@@ -77,6 +68,16 @@ parameters:
type: boolean
default: false
+ # Send tests to Helix for distributed execution
+- name: useHelix
+ type: boolean
+ default: false
+
+ # Helix queue to target (required when useHelix is true)
+- name: helixQueues
+ type: string
+ default: ''
+
jobs:
- ${{ each config in parameters.buildConfigs }}:
- template: ${{ parameters.jobTemplate }}
@@ -118,9 +119,6 @@ jobs:
${{ if ne(parameters.strategy, '') }}:
'error, we can no longer support the strategy feature in the new pipeline system. Please remove the strategy from the job template.': error
- ${{ if ne(parameters.dependsOn, '') }}:
- dependsOn: ${{ parameters.dependsOn }}_${{ config.architecture }}_${{ config.configuration }}
-
workspace:
clean: all
@@ -130,7 +128,6 @@ jobs:
- _PhaseName: ${{ coalesce(parameters.name, parameters.osGroup) }}_${{ config.architecture }}_${{ config.configuration }}
- _Pipeline_StreamDumpDir: $(Build.SourcesDirectory)/artifacts/tmp/${{ config.configuration }}/streams
- - _TestArgs: '-test'
- _Cross: ''
- ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
@@ -138,15 +135,6 @@ jobs:
- ${{ if ne(parameters.osGroup, 'Windows_NT') }}:
- _buildScript: $(Build.SourcesDirectory)/build.sh
- - ${{ if and(eq(parameters.testOnly, 'true'), eq(parameters.buildOnly, 'true')) }}:
- 'error, testOnly and buildOnly cannot be true at the same time': error
-
- - ${{ if eq(parameters.testOnly, 'true') }}:
- - _TestArgs: '-test -skipnative'
-
- - ${{ if or(eq(parameters.buildOnly, 'true'), eq(parameters.isCodeQLRun, 'true')) }}:
- - _TestArgs: ''
-
# For testing msrc's and service releases. The RuntimeSourceVersion is either "default" or the service release version to test
- _InternalInstallArgs: ''
- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.isCodeQLRun, 'false')) }}:
@@ -160,22 +148,11 @@ jobs:
- ${{ if eq(parameters.crossBuild, true) }}:
- _Cross: -cross
- steps:
- - ${{ if eq(parameters.testOnly, true) }}:
- - ${{ if ne(parameters.osGroup, 'Linux') }}:
- - 'error, testOnly is only supported on Linux': error
- - task: DownloadPipelineArtifact@2
- displayName: 'Download Build Artifacts'
- inputs:
- targetPath: '$(Build.ArtifactStagingDirectory)/__download__'
- itemPattern: Build_${{ parameters.dependsOn }}_${{ config.architecture }}_${{ config.configuration }}/bin/**
- checkDownloadedFiles: true
- - task: CopyFiles@2
- displayName: 'Binplace Downloaded Product'
- inputs:
- sourceFolder: $(Build.ArtifactStagingDirectory)/__download__/Build_${{ parameters.dependsOn }}_${{ config.architecture }}_${{ config.configuration }}/bin/linux${{ parameters.osSuffix }}.${{ config.architecture }}.${{ config.configuration }}
- targetFolder: '$(Build.SourcesDirectory)/artifacts/bin/linux.${{ config.architecture }}.${{ config.configuration }}'
+ # Helix variable group (only when useHelix is true, for internal builds)
+ - ${{ if and(eq(parameters.useHelix, true), ne(variables['System.TeamProject'], 'public')) }}:
+ - group: DotNet-HelixApi-Access
+ steps:
- ${{ if eq(parameters.isCodeQLRun, 'true') }}:
- task: CodeQL3000Init@0
displayName: CodeQL Initialize
@@ -185,22 +162,25 @@ jobs:
-binaryLog
-configuration ${{ config.configuration }}
-architecture ${{ config.architecture }}
- $(_TestArgs)
$(_Cross)
$(_InternalInstallArgs)
/p:OfficialBuildId=$(BUILD.BUILDNUMBER)
- ${{ if eq(parameters.testOnly, 'true') }}:
- displayName: Test
- ${{ elseif eq(parameters.buildOnly, 'true') }}:
- displayName: Build
- ${{ else }}:
- displayName: Build / Test
+ displayName: Build
condition: succeeded()
- ${{ if eq(parameters.isCodeQLRun, 'true') }}:
- task: CodeQL3000Finalize@0
displayName: CodeQL Finalize
+ # Send tests to Helix (when useHelix is true and not buildOnly)
+ - ${{ if and(eq(parameters.useHelix, true), ne(parameters.buildOnly, true)) }}:
+ - template: /eng/pipelines/send-to-helix.yml@self
+ parameters:
+ configuration: ${{ config.configuration }}
+ architecture: ${{ config.architecture }}
+ osGroup: ${{ parameters.osGroup }}
+ helixQueues: ${{ parameters.helixQueues }}
+
- ${{ if ne(config.artifactUploadPath, '') }}:
- task: CopyFiles@2
displayName: Gather binaries for publish
@@ -258,18 +238,3 @@ jobs:
sbomEnabled: false # we don't need SBOM for logs
continueOnError: true
condition: always()
-
- - ${{ if and(ne(parameters.buildOnly, 'true'), ne(parameters.isCodeQLRun, 'true')) }}:
- # Publish test results to Azure Pipelines
- - task: PublishTestResults@2
- inputs:
- testResultsFormat: xUnit
- testResultsFiles: '**/*.xml'
- searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults'
- testRunTitle: 'Tests $(_PhaseName)'
- failTaskOnFailedTests: true
- publishRunAttachments: true
- mergeTestResults: true
- buildConfiguration: ${{ config.configuration }}
- continueOnError: true
- condition: always()
diff --git a/eng/pipelines/global-variables.yml b/eng/pipelines/global-variables.yml
index 53522d8c02..439515f083 100644
--- a/eng/pipelines/global-variables.yml
+++ b/eng/pipelines/global-variables.yml
@@ -71,12 +71,14 @@ variables:
value: Ubuntu.2204.Amd64.Open
- name: HelixQueuesLinux_arm64
value: Ubuntu.2204.Arm64.Open
+ - name: HelixQueuesLinux_musl_x64
+ value: Ubuntu.2204.Amd64.Open
+ - name: HelixQueuesLinux_musl_arm64
+ value: Ubuntu.2204.Arm64.Open
- name: HelixQueuesMacOS_x64
value: OSX.1200.Amd64.Open
- name: HelixQueuesMacOS_arm64
value: OSX.1200.Arm64.Open
- - name: HelixQueuesFreeBSD
- value: ''
# Internal queues for official builds
- ${{ if ne(variables['System.TeamProject'], 'public') }}:
@@ -90,9 +92,11 @@ variables:
value: Ubuntu.2204.Amd64
- name: HelixQueuesLinux_arm64
value: Ubuntu.2204.Arm64
+ - name: HelixQueuesLinux_musl_x64
+ value: Ubuntu.2204.Amd64
+ - name: HelixQueuesLinux_musl_arm64
+ value: Ubuntu.2204.Arm64
- name: HelixQueuesMacOS_x64
value: OSX.1200.Amd64
- name: HelixQueuesMacOS_arm64
value: OSX.1200.Arm64
- - name: HelixQueuesFreeBSD
- value: ''
diff --git a/eng/pipelines/helix.yml b/eng/pipelines/helix.yml
deleted file mode 100644
index 1166f95d2c..0000000000
--- a/eng/pipelines/helix.yml
+++ /dev/null
@@ -1,222 +0,0 @@
-# Pipeline template for running tests on Helix
-# This template downloads build artifacts and sends test workloads to Helix
-# machines for distributed execution.
-
-parameters:
- # Job name suffix
-- name: name
- type: string
- default: 'Helix'
-
-- name: jobTemplate
- type: string
- default: /eng/common/templates/job/job.yml@self
- values:
- - /eng/common/templates-official/job/job.yml@self
- - /eng/common/templates/job/job.yml@self
-
-- name: osGroup
- type: string
- default: Windows_NT
- values:
- - Windows_NT
- - Linux
- - MacOS
-
- # Build configuration
-- name: configuration
- type: string
- default: Debug
-
- # Target architecture
-- name: architecture
- type: string
- default: x64
-
- # Helix queue to target (semicolon-delimited list supported)
-- name: helixQueues
- type: string
- default: ''
-
- # Whether this is an internal (authenticated) build
-- name: isInternal
- type: boolean
- default: false
-
- # Job timeout
-- name: timeoutInMinutes
- type: number
- default: 120
-
- # Job dependency name for artifact download (e.g. Windows_x64_Release)
-- name: dependsOn
- type: string
- default: ''
-
- # Template context for 1ES pipeline
-- name: templateContext
- type: object
- default: {}
-
-jobs:
-- template: ${{ parameters.jobTemplate }}
- parameters:
- name: ${{ parameters.name }}_${{ parameters.architecture }}_${{ parameters.configuration }}
- timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
- templateContext: ${{ parameters.templateContext }}
-
- pool:
- ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
- name: $(BuildPool)
- demands: ImageOverride -equals $(WindowsImage)
- os: windows
-
- ${{ if eq(parameters.osGroup, 'Linux') }}:
- name: $(BuildPool)
- demands: ImageOverride -equals $(LinuxImage)
- os: linux
-
- ${{ if eq(parameters.osGroup, 'MacOS') }}:
- name: Azure Pipelines
- vmImage: $(macOSImage)
- os: macOS
-
- workspace:
- clean: all
-
- variables:
- - _BuildConfig: ${{ parameters.configuration }}
- - _HelixType: test/${{ parameters.configuration }}/${{ parameters.architecture }}/
-
- # Determine target OS for helix.proj
- - ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
- - _TargetOS: Windows_NT
- - ${{ if eq(parameters.osGroup, 'Linux') }}:
- - _TargetOS: linux
- - ${{ if eq(parameters.osGroup, 'MacOS') }}:
- - _TargetOS: osx
-
- # Build script
- - ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
- - _buildScript: $(Build.SourcesDirectory)\build.cmd
- - ${{ if ne(parameters.osGroup, 'Windows_NT') }}:
- - _buildScript: $(Build.SourcesDirectory)/build.sh
-
- # Helix queue configuration
- - _HelixQueues: ${{ parameters.helixQueues }}
-
- # For internal builds, use the Helix access token
- - ${{ if eq(parameters.isInternal, true) }}:
- - group: DotNet-HelixApi-Access
- - _HelixAccessToken: $(HelixApiAccessToken)
- - _HelixSource: official/diagnostics/$(Build.SourceBranch)
- - ${{ else }}:
- - _HelixAccessToken: ''
- - _HelixSource: pr/diagnostics/$(Build.SourceBranch)
- - _Creator: $(Build.RequestedFor)
-
- steps:
- # Build locally (build-only, no tests) to produce test assemblies and artifacts
- - script: $(_buildScript)
- -ci
- -binaryLog
- -configuration ${{ parameters.configuration }}
- -architecture ${{ parameters.architecture }}
- /p:OfficialBuildId=$(BUILD.BUILDNUMBER)
- displayName: Build
- condition: succeeded()
-
- # Send tests to Helix
- - ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
- - script: >
- $(Build.SourcesDirectory)\eng\common\msbuild.cmd
- $(Build.SourcesDirectory)\eng\helix.proj
- /restore
- /t:Test
- /p:Configuration=${{ parameters.configuration }}
- /p:TargetArchitecture=${{ parameters.architecture }}
- /p:TargetOS=$(_TargetOS)
- /p:HelixTargetQueues=$(_HelixQueues)
- /p:HelixSource=$(_HelixSource)
- /p:HelixType=$(_HelixType)
- /p:HelixAccessToken=$(_HelixAccessToken)
- /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
- displayName: Send Tests to Helix (internal)
- condition: and(succeeded(), eq('${{ parameters.isInternal }}', 'True'))
- env:
- SYSTEM_ACCESSTOKEN: $(System.AccessToken)
-
- - script: >
- $(Build.SourcesDirectory)\eng\common\msbuild.cmd
- $(Build.SourcesDirectory)\eng\helix.proj
- /restore
- /t:Test
- /p:Configuration=${{ parameters.configuration }}
- /p:TargetArchitecture=${{ parameters.architecture }}
- /p:TargetOS=$(_TargetOS)
- /p:HelixTargetQueues=$(_HelixQueues)
- /p:HelixSource=$(_HelixSource)
- /p:HelixType=$(_HelixType)
- /p:Creator=$(_Creator)
- /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
- displayName: Send Tests to Helix (public)
- condition: and(succeeded(), ne('${{ parameters.isInternal }}', 'True'))
- env:
- SYSTEM_ACCESSTOKEN: $(System.AccessToken)
-
- - ${{ if ne(parameters.osGroup, 'Windows_NT') }}:
- - script: >
- $(Build.SourcesDirectory)/eng/common/msbuild.sh
- $(Build.SourcesDirectory)/eng/helix.proj
- /restore
- /t:Test
- /p:Configuration=${{ parameters.configuration }}
- /p:TargetArchitecture=${{ parameters.architecture }}
- /p:TargetOS=$(_TargetOS)
- /p:HelixTargetQueues=$(_HelixQueues)
- /p:HelixSource=$(_HelixSource)
- /p:HelixType=$(_HelixType)
- /p:HelixAccessToken=$(_HelixAccessToken)
- /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
- displayName: Send Tests to Helix (internal)
- condition: and(succeeded(), eq('${{ parameters.isInternal }}', 'True'))
- env:
- SYSTEM_ACCESSTOKEN: $(System.AccessToken)
-
- - script: >
- $(Build.SourcesDirectory)/eng/common/msbuild.sh
- $(Build.SourcesDirectory)/eng/helix.proj
- /restore
- /t:Test
- /p:Configuration=${{ parameters.configuration }}
- /p:TargetArchitecture=${{ parameters.architecture }}
- /p:TargetOS=$(_TargetOS)
- /p:HelixTargetQueues=$(_HelixQueues)
- /p:HelixSource=$(_HelixSource)
- /p:HelixType=$(_HelixType)
- /p:Creator=$(_Creator)
- /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
- displayName: Send Tests to Helix (public)
- condition: and(succeeded(), ne('${{ parameters.isInternal }}', 'True'))
- env:
- SYSTEM_ACCESSTOKEN: $(System.AccessToken)
-
- # Publish Helix logs
- - task: CopyFiles@2
- displayName: Gather Helix Logs
- inputs:
- sourceFolder: '$(Build.SourcesDirectory)/artifacts'
- contents: 'log/**'
- targetFolder: '$(Build.StagingDirectory)/HelixLogs'
- continueOnError: true
- condition: always()
-
- - template: /eng/pipelines/publish-pipeline-artifact-shim.yml@self
- parameters:
- displayName: Publish Helix Logs
- inputs:
- targetPath: '$(Build.StagingDirectory)/HelixLogs'
- artifactName: HelixLogs_${{ parameters.name }}_${{ parameters.osGroup }}_${{ parameters.architecture }}_${{ parameters.configuration }}
- sbomEnabled: false
- continueOnError: true
- condition: always()
diff --git a/eng/pipelines/send-to-helix.yml b/eng/pipelines/send-to-helix.yml
new file mode 100644
index 0000000000..a78ba9b28d
--- /dev/null
+++ b/eng/pipelines/send-to-helix.yml
@@ -0,0 +1,138 @@
+# Step template for sending tests to Helix.
+# This template is included by build.yml to send test workloads to Helix
+# machines for distributed execution.
+#
+# Internal vs public is determined automatically by System.TeamProject:
+# - Internal: uses HelixAccessToken from DotNet-HelixApi-Access variable group
+# - Public: uses Creator for anonymous submission
+#
+# Prerequisites: The DotNet-HelixApi-Access variable group must be included
+# at the job level for internal builds (provides HelixApiAccessToken).
+
+parameters:
+ # Build configuration (e.g. Debug, Release)
+- name: configuration
+ type: string
+
+ # Target architecture (e.g. x64, arm64)
+- name: architecture
+ type: string
+
+ # Target OS group
+- name: osGroup
+ type: string
+ default: Windows_NT
+ values:
+ - Windows_NT
+ - Linux
+ - MacOS
+
+ # Helix queue to target
+- name: helixQueues
+ type: string
+
+steps:
+- ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
+ - script: >
+ $(Build.SourcesDirectory)\eng\common\msbuild.cmd
+ $(Build.SourcesDirectory)\eng\helix.proj
+ /restore
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=Windows_NT
+ /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ /p:HelixSource=official/diagnostics/$(Build.SourceBranch)
+ /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+ /p:HelixAccessToken=$(HelixApiAccessToken)
+ /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
+ displayName: Send Tests to Helix (internal)
+ condition: and(succeeded(), ne(variables['System.TeamProject'], 'public'))
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+
+ - script: >
+ $(Build.SourcesDirectory)\eng\common\msbuild.cmd
+ $(Build.SourcesDirectory)\eng\helix.proj
+ /restore
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=Windows_NT
+ /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ /p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
+ /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+ /p:Creator=$(Build.RequestedFor)
+ /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
+ displayName: Send Tests to Helix (public)
+ condition: and(succeeded(), eq(variables['System.TeamProject'], 'public'))
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+
+- ${{ if eq(parameters.osGroup, 'Linux') }}:
+ - script: >
+ $(Build.SourcesDirectory)/eng/common/msbuild.sh
+ $(Build.SourcesDirectory)/eng/helix.proj
+ /restore
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=linux
+ /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ /p:HelixSource=official/diagnostics/$(Build.SourceBranch)
+ /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+ /p:HelixAccessToken=$(HelixApiAccessToken)
+ /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
+ displayName: Send Tests to Helix (internal)
+ condition: and(succeeded(), ne(variables['System.TeamProject'], 'public'))
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+
+ - script: >
+ $(Build.SourcesDirectory)/eng/common/msbuild.sh
+ $(Build.SourcesDirectory)/eng/helix.proj
+ /restore
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=linux
+ /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ /p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
+ /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+ /p:Creator=$(Build.RequestedFor)
+ /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
+ displayName: Send Tests to Helix (public)
+ condition: and(succeeded(), eq(variables['System.TeamProject'], 'public'))
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+
+- ${{ if eq(parameters.osGroup, 'MacOS') }}:
+ - script: >
+ $(Build.SourcesDirectory)/eng/common/msbuild.sh
+ $(Build.SourcesDirectory)/eng/helix.proj
+ /restore
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=osx
+ /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ /p:HelixSource=official/diagnostics/$(Build.SourceBranch)
+ /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+ /p:HelixAccessToken=$(HelixApiAccessToken)
+ /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
+ displayName: Send Tests to Helix (internal)
+ condition: and(succeeded(), ne(variables['System.TeamProject'], 'public'))
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+
+ - script: >
+ $(Build.SourcesDirectory)/eng/common/msbuild.sh
+ $(Build.SourcesDirectory)/eng/helix.proj
+ /restore
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=osx
+ /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ /p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
+ /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+ /p:Creator=$(Build.RequestedFor)
+ /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
+ displayName: Send Tests to Helix (public)
+ condition: and(succeeded(), eq(variables['System.TeamProject'], 'public'))
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
From 88c490240645833ae9fd696a6fc815564f78023e Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 13:55:18 -0500
Subject: [PATCH 15/48] fix
---
eng/pipelines/send-to-helix.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/eng/pipelines/send-to-helix.yml b/eng/pipelines/send-to-helix.yml
index a78ba9b28d..b44759f0b9 100644
--- a/eng/pipelines/send-to-helix.yml
+++ b/eng/pipelines/send-to-helix.yml
@@ -33,8 +33,8 @@ parameters:
steps:
- ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
- - script: >
- $(Build.SourcesDirectory)\eng\common\msbuild.cmd
+ - powershell: >
+ & $(Build.SourcesDirectory)\eng\common\msbuild.ps1
$(Build.SourcesDirectory)\eng\helix.proj
/restore
/p:Configuration=${{ parameters.configuration }}
@@ -50,8 +50,8 @@ steps:
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- - script: >
- $(Build.SourcesDirectory)\eng\common\msbuild.cmd
+ - powershell: >
+ & $(Build.SourcesDirectory)\eng\common\msbuild.ps1
$(Build.SourcesDirectory)\eng\helix.proj
/restore
/p:Configuration=${{ parameters.configuration }}
From 98dec5210ae3ed1d14e9c8e2e4df85cd3c6beca0 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 14:27:26 -0500
Subject: [PATCH 16/48] update pipelines
---
diagnostics.yml | 7 +
eng/pipelines/build.yml | 6 +
eng/pipelines/global-variables.yml | 8 +-
eng/pipelines/send-to-helix.yml | 212 +++++++++++++++--------------
4 files changed, 126 insertions(+), 107 deletions(-)
diff --git a/diagnostics.yml b/diagnostics.yml
index 1d74c38f4d..00b78f69cc 100644
--- a/diagnostics.yml
+++ b/diagnostics.yml
@@ -85,6 +85,7 @@ extends:
osGroup: Windows_NT
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
+ isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
helixQueues: $(HelixQueuesWindows_x64)
buildConfigs:
- configuration: Debug
@@ -108,6 +109,7 @@ extends:
crossBuild: true
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
+ isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
helixQueues: $(HelixQueuesLinux_x64)
buildConfigs:
- configuration: Release
@@ -128,6 +130,7 @@ extends:
crossBuild: true
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
+ isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
helixQueues: $(HelixQueuesLinux_musl_x64)
buildConfigs:
- configuration: Release
@@ -146,6 +149,7 @@ extends:
osGroup: MacOS
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
+ isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
helixQueues: $(HelixQueuesMacOS_x64)
buildConfigs:
- configuration: Release
@@ -162,6 +166,7 @@ extends:
crossBuild: true
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
+ isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
helixQueues: $(HelixQueuesMacOS_arm64)
buildConfigs:
- configuration: Release
@@ -192,6 +197,7 @@ extends:
crossBuild: true
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
+ isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
helixQueues: $(HelixQueuesLinux_arm64)
buildConfigs:
- configuration: Release
@@ -223,6 +229,7 @@ extends:
crossBuild: true
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
+ isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
helixQueues: $(HelixQueuesLinux_musl_arm64)
buildConfigs:
- configuration: Release
diff --git a/eng/pipelines/build.yml b/eng/pipelines/build.yml
index d144caadd5..fe890c3565 100644
--- a/eng/pipelines/build.yml
+++ b/eng/pipelines/build.yml
@@ -78,6 +78,11 @@ parameters:
type: string
default: ''
+ # Whether this is an official (non-PR, internal) build
+- name: isOfficialBuild
+ type: boolean
+ default: false
+
jobs:
- ${{ each config in parameters.buildConfigs }}:
- template: ${{ parameters.jobTemplate }}
@@ -180,6 +185,7 @@ jobs:
architecture: ${{ config.architecture }}
osGroup: ${{ parameters.osGroup }}
helixQueues: ${{ parameters.helixQueues }}
+ isOfficialBuild: ${{ parameters.isOfficialBuild }}
- ${{ if ne(config.artifactUploadPath, '') }}:
- task: CopyFiles@2
diff --git a/eng/pipelines/global-variables.yml b/eng/pipelines/global-variables.yml
index 439515f083..2cf8ed2a6b 100644
--- a/eng/pipelines/global-variables.yml
+++ b/eng/pipelines/global-variables.yml
@@ -59,8 +59,8 @@ variables:
value: $(dotnetclimsrc-read-sas-token-base64)
# Helix queue configuration
-# Public (open) queues for PR validation
-- ${{ if eq(variables['System.TeamProject'], 'public') }}:
+# Public (open) queues for PR validation and public project builds
+- ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}:
- name: HelixQueuesWindows_x64
value: Windows.10.Amd64.Open
- name: HelixQueuesWindows_x86
@@ -80,8 +80,8 @@ variables:
- name: HelixQueuesMacOS_arm64
value: OSX.1200.Arm64.Open
-# Internal queues for official builds
-- ${{ if ne(variables['System.TeamProject'], 'public') }}:
+# Internal queues for official builds (non-PR, non-public)
+- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- name: HelixQueuesWindows_x64
value: windows.amd64.server2022
- name: HelixQueuesWindows_x86
diff --git a/eng/pipelines/send-to-helix.yml b/eng/pipelines/send-to-helix.yml
index b44759f0b9..d7172ade5a 100644
--- a/eng/pipelines/send-to-helix.yml
+++ b/eng/pipelines/send-to-helix.yml
@@ -2,12 +2,12 @@
# This template is included by build.yml to send test workloads to Helix
# machines for distributed execution.
#
-# Internal vs public is determined automatically by System.TeamProject:
-# - Internal: uses HelixAccessToken from DotNet-HelixApi-Access variable group
-# - Public: uses Creator for anonymous submission
+# Official vs PR builds:
+# - Official (isOfficialBuild=true): uses HelixAccessToken from DotNet-HelixApi-Access variable group
+# - PR/public (isOfficialBuild=false): uses Creator for anonymous submission
#
# Prerequisites: The DotNet-HelixApi-Access variable group must be included
-# at the job level for internal builds (provides HelixApiAccessToken).
+# at the job level for official builds (provides HelixApiAccessToken).
parameters:
# Build configuration (e.g. Debug, Release)
@@ -31,108 +31,114 @@ parameters:
- name: helixQueues
type: string
+ # Whether this is an official (non-PR, internal) build
+- name: isOfficialBuild
+ type: boolean
+ default: false
+
steps:
-- ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
- - powershell: >
- & $(Build.SourcesDirectory)\eng\common\msbuild.ps1
- $(Build.SourcesDirectory)\eng\helix.proj
- /restore
- /p:Configuration=${{ parameters.configuration }}
- /p:TargetArchitecture=${{ parameters.architecture }}
- /p:TargetOS=Windows_NT
- /p:HelixTargetQueues=${{ parameters.helixQueues }}
- /p:HelixSource=official/diagnostics/$(Build.SourceBranch)
- /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
- /p:HelixAccessToken=$(HelixApiAccessToken)
- /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
- displayName: Send Tests to Helix (internal)
- condition: and(succeeded(), ne(variables['System.TeamProject'], 'public'))
- env:
- SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+# Official builds: use HelixAccessToken for internal queues
+- ${{ if eq(parameters.isOfficialBuild, true) }}:
+ - ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
+ - powershell: >
+ & $(Build.SourcesDirectory)\eng\common\msbuild.ps1
+ $(Build.SourcesDirectory)\eng\helix.proj
+ /restore
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=Windows_NT
+ /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ /p:HelixSource=official/diagnostics/$(Build.SourceBranch)
+ /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+ /p:HelixAccessToken=$(HelixApiAccessToken)
+ /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
+ displayName: Send Tests to Helix
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- - powershell: >
- & $(Build.SourcesDirectory)\eng\common\msbuild.ps1
- $(Build.SourcesDirectory)\eng\helix.proj
- /restore
- /p:Configuration=${{ parameters.configuration }}
- /p:TargetArchitecture=${{ parameters.architecture }}
- /p:TargetOS=Windows_NT
- /p:HelixTargetQueues=${{ parameters.helixQueues }}
- /p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
- /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
- /p:Creator=$(Build.RequestedFor)
- /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
- displayName: Send Tests to Helix (public)
- condition: and(succeeded(), eq(variables['System.TeamProject'], 'public'))
- env:
- SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+ - ${{ if eq(parameters.osGroup, 'Linux') }}:
+ - script: >
+ $(Build.SourcesDirectory)/eng/common/msbuild.sh
+ $(Build.SourcesDirectory)/eng/helix.proj
+ /restore
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=linux
+ /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ /p:HelixSource=official/diagnostics/$(Build.SourceBranch)
+ /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+ /p:HelixAccessToken=$(HelixApiAccessToken)
+ /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
+ displayName: Send Tests to Helix
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
-- ${{ if eq(parameters.osGroup, 'Linux') }}:
- - script: >
- $(Build.SourcesDirectory)/eng/common/msbuild.sh
- $(Build.SourcesDirectory)/eng/helix.proj
- /restore
- /p:Configuration=${{ parameters.configuration }}
- /p:TargetArchitecture=${{ parameters.architecture }}
- /p:TargetOS=linux
- /p:HelixTargetQueues=${{ parameters.helixQueues }}
- /p:HelixSource=official/diagnostics/$(Build.SourceBranch)
- /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
- /p:HelixAccessToken=$(HelixApiAccessToken)
- /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
- displayName: Send Tests to Helix (internal)
- condition: and(succeeded(), ne(variables['System.TeamProject'], 'public'))
- env:
- SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+ - ${{ if eq(parameters.osGroup, 'MacOS') }}:
+ - script: >
+ $(Build.SourcesDirectory)/eng/common/msbuild.sh
+ $(Build.SourcesDirectory)/eng/helix.proj
+ /restore
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=osx
+ /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ /p:HelixSource=official/diagnostics/$(Build.SourceBranch)
+ /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+ /p:HelixAccessToken=$(HelixApiAccessToken)
+ /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
+ displayName: Send Tests to Helix
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- - script: >
- $(Build.SourcesDirectory)/eng/common/msbuild.sh
- $(Build.SourcesDirectory)/eng/helix.proj
- /restore
- /p:Configuration=${{ parameters.configuration }}
- /p:TargetArchitecture=${{ parameters.architecture }}
- /p:TargetOS=linux
- /p:HelixTargetQueues=${{ parameters.helixQueues }}
- /p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
- /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
- /p:Creator=$(Build.RequestedFor)
- /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
- displayName: Send Tests to Helix (public)
- condition: and(succeeded(), eq(variables['System.TeamProject'], 'public'))
- env:
- SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+# PR/public builds: use Creator for anonymous submission
+- ${{ else }}:
+ - ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
+ - powershell: >
+ & $(Build.SourcesDirectory)\eng\common\msbuild.ps1
+ $(Build.SourcesDirectory)\eng\helix.proj
+ /restore
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=Windows_NT
+ /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ /p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
+ /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+ /p:Creator=$(Build.RequestedFor)
+ /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
+ displayName: Send Tests to Helix
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
-- ${{ if eq(parameters.osGroup, 'MacOS') }}:
- - script: >
- $(Build.SourcesDirectory)/eng/common/msbuild.sh
- $(Build.SourcesDirectory)/eng/helix.proj
- /restore
- /p:Configuration=${{ parameters.configuration }}
- /p:TargetArchitecture=${{ parameters.architecture }}
- /p:TargetOS=osx
- /p:HelixTargetQueues=${{ parameters.helixQueues }}
- /p:HelixSource=official/diagnostics/$(Build.SourceBranch)
- /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
- /p:HelixAccessToken=$(HelixApiAccessToken)
- /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
- displayName: Send Tests to Helix (internal)
- condition: and(succeeded(), ne(variables['System.TeamProject'], 'public'))
- env:
- SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+ - ${{ if eq(parameters.osGroup, 'Linux') }}:
+ - script: >
+ $(Build.SourcesDirectory)/eng/common/msbuild.sh
+ $(Build.SourcesDirectory)/eng/helix.proj
+ /restore
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=linux
+ /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ /p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
+ /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+ /p:Creator=$(Build.RequestedFor)
+ /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
+ displayName: Send Tests to Helix
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- - script: >
- $(Build.SourcesDirectory)/eng/common/msbuild.sh
- $(Build.SourcesDirectory)/eng/helix.proj
- /restore
- /p:Configuration=${{ parameters.configuration }}
- /p:TargetArchitecture=${{ parameters.architecture }}
- /p:TargetOS=osx
- /p:HelixTargetQueues=${{ parameters.helixQueues }}
- /p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
- /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
- /p:Creator=$(Build.RequestedFor)
- /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
- displayName: Send Tests to Helix (public)
- condition: and(succeeded(), eq(variables['System.TeamProject'], 'public'))
- env:
- SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+ - ${{ if eq(parameters.osGroup, 'MacOS') }}:
+ - script: >
+ $(Build.SourcesDirectory)/eng/common/msbuild.sh
+ $(Build.SourcesDirectory)/eng/helix.proj
+ /restore
+ /p:Configuration=${{ parameters.configuration }}
+ /p:TargetArchitecture=${{ parameters.architecture }}
+ /p:TargetOS=osx
+ /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ /p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
+ /p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
+ /p:Creator=$(Build.RequestedFor)
+ /bl:$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}/SendToHelix.binlog
+ displayName: Send Tests to Helix
+ env:
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
\ No newline at end of file
From b56f0408e338c89ab95614cc7ef65c4c6bced258 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 14:31:18 -0500
Subject: [PATCH 17/48] clean up and fix pipeline
---
eng/Versions.props | 1 -
eng/pipelines/build.yml | 4 ++--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/eng/Versions.props b/eng/Versions.props
index fd526a554a..52988e350d 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -98,7 +98,6 @@
true
-runtimesourcefeed '$(RuntimeSourceFeed)' -runtimesourcefeedkey '$(RuntimeSourceFeedKey)'
-
$(MicrosoftNETCorePlatformsVersion)
diff --git a/eng/pipelines/build.yml b/eng/pipelines/build.yml
index fe890c3565..922bedbcaa 100644
--- a/eng/pipelines/build.yml
+++ b/eng/pipelines/build.yml
@@ -153,8 +153,8 @@ jobs:
- ${{ if eq(parameters.crossBuild, true) }}:
- _Cross: -cross
- # Helix variable group (only when useHelix is true, for internal builds)
- - ${{ if and(eq(parameters.useHelix, true), ne(variables['System.TeamProject'], 'public')) }}:
+ # Helix variable group (only when useHelix is true, for official builds)
+ - ${{ if and(eq(parameters.useHelix, true), eq(parameters.isOfficialBuild, true)) }}:
- group: DotNet-HelixApi-Access
steps:
From a8b13da744240830e01c8fa98503c443cc548e3e Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 14:41:48 -0500
Subject: [PATCH 18/48] fix macos queues
---
eng/pipelines/global-variables.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/eng/pipelines/global-variables.yml b/eng/pipelines/global-variables.yml
index 2cf8ed2a6b..e05e8caf6c 100644
--- a/eng/pipelines/global-variables.yml
+++ b/eng/pipelines/global-variables.yml
@@ -76,9 +76,9 @@ variables:
- name: HelixQueuesLinux_musl_arm64
value: Ubuntu.2204.Arm64.Open
- name: HelixQueuesMacOS_x64
- value: OSX.1200.Amd64.Open
+ value: OSX.15.Amd64.Open
- name: HelixQueuesMacOS_arm64
- value: OSX.1200.Arm64.Open
+ value: OSX.15.Arm64.Open
# Internal queues for official builds (non-PR, non-public)
- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
@@ -97,6 +97,6 @@ variables:
- name: HelixQueuesLinux_musl_arm64
value: Ubuntu.2204.Arm64
- name: HelixQueuesMacOS_x64
- value: OSX.1200.Amd64
+ value: OSX.15.Amd64
- name: HelixQueuesMacOS_arm64
- value: OSX.1200.Arm64
+ value: OSX.15.Arm64
From 4dee5a4947c3244c2c499c49ad3cb10a5fbb2954 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 14:44:11 -0500
Subject: [PATCH 19/48] fix windows queues
---
eng/pipelines/global-variables.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/eng/pipelines/global-variables.yml b/eng/pipelines/global-variables.yml
index e05e8caf6c..df7890b3b1 100644
--- a/eng/pipelines/global-variables.yml
+++ b/eng/pipelines/global-variables.yml
@@ -62,9 +62,9 @@ variables:
# Public (open) queues for PR validation and public project builds
- ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}:
- name: HelixQueuesWindows_x64
- value: Windows.10.Amd64.Open
+ value: windows.amd64.server2022
- name: HelixQueuesWindows_x86
- value: Windows.10.Amd64.Open
+ value: windows.amd64.server2022
- name: HelixQueuesWindows_arm64
value: Windows.11.Arm64.Open
- name: HelixQueuesLinux_x64
From d905cd832ee777303d80f3d18dd143ed2e4374d9 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 15:13:15 -0500
Subject: [PATCH 20/48] update queues
---
eng/pipelines/global-variables.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/eng/pipelines/global-variables.yml b/eng/pipelines/global-variables.yml
index df7890b3b1..b86041d451 100644
--- a/eng/pipelines/global-variables.yml
+++ b/eng/pipelines/global-variables.yml
@@ -62,9 +62,9 @@ variables:
# Public (open) queues for PR validation and public project builds
- ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}:
- name: HelixQueuesWindows_x64
- value: windows.amd64.server2022
+ value: windows.11.amd64.client.Open
- name: HelixQueuesWindows_x86
- value: windows.amd64.server2022
+ value: windows.11.amd64.client.Open
- name: HelixQueuesWindows_arm64
value: Windows.11.Arm64.Open
- name: HelixQueuesLinux_x64
@@ -83,9 +83,9 @@ variables:
# Internal queues for official builds (non-PR, non-public)
- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- name: HelixQueuesWindows_x64
- value: windows.amd64.server2022
+ value: windows.11.amd64.client
- name: HelixQueuesWindows_x86
- value: windows.amd64.server2022
+ value: windows.11.amd64.client
- name: HelixQueuesWindows_arm64
value: windows.11.arm64
- name: HelixQueuesLinux_x64
From c0f048221568274445659946ebc4758d92f29e2c Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 15:24:15 -0500
Subject: [PATCH 21/48] update to match runtime logic
---
diagnostics.yml | 14 +++++++-------
eng/pipelines/global-variables.yml | 26 +++++++++++++-------------
2 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/diagnostics.yml b/diagnostics.yml
index 00b78f69cc..17112808d2 100644
--- a/diagnostics.yml
+++ b/diagnostics.yml
@@ -85,7 +85,7 @@ extends:
osGroup: Windows_NT
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
- isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
+ isOfficialBuild: ${{ eq(variables['System.TeamProject'], 'internal') }}
helixQueues: $(HelixQueuesWindows_x64)
buildConfigs:
- configuration: Debug
@@ -109,7 +109,7 @@ extends:
crossBuild: true
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
- isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
+ isOfficialBuild: ${{ eq(variables['System.TeamProject'], 'internal') }}
helixQueues: $(HelixQueuesLinux_x64)
buildConfigs:
- configuration: Release
@@ -130,7 +130,7 @@ extends:
crossBuild: true
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
- isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
+ isOfficialBuild: ${{ eq(variables['System.TeamProject'], 'internal') }}
helixQueues: $(HelixQueuesLinux_musl_x64)
buildConfigs:
- configuration: Release
@@ -149,7 +149,7 @@ extends:
osGroup: MacOS
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
- isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
+ isOfficialBuild: ${{ eq(variables['System.TeamProject'], 'internal') }}
helixQueues: $(HelixQueuesMacOS_x64)
buildConfigs:
- configuration: Release
@@ -166,7 +166,7 @@ extends:
crossBuild: true
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
- isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
+ isOfficialBuild: ${{ eq(variables['System.TeamProject'], 'internal') }}
helixQueues: $(HelixQueuesMacOS_arm64)
buildConfigs:
- configuration: Release
@@ -197,7 +197,7 @@ extends:
crossBuild: true
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
- isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
+ isOfficialBuild: ${{ eq(variables['System.TeamProject'], 'internal') }}
helixQueues: $(HelixQueuesLinux_arm64)
buildConfigs:
- configuration: Release
@@ -229,7 +229,7 @@ extends:
crossBuild: true
buildOnly: ${{ parameters.buildOnly }}
useHelix: ${{ parameters.useHelix }}
- isOfficialBuild: ${{ and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'dotnet-diagnostics')) }}
+ isOfficialBuild: ${{ eq(variables['System.TeamProject'], 'internal') }}
helixQueues: $(HelixQueuesLinux_musl_arm64)
buildConfigs:
- configuration: Release
diff --git a/eng/pipelines/global-variables.yml b/eng/pipelines/global-variables.yml
index b86041d451..b1cc3b96c3 100644
--- a/eng/pipelines/global-variables.yml
+++ b/eng/pipelines/global-variables.yml
@@ -59,43 +59,43 @@ variables:
value: $(dotnetclimsrc-read-sas-token-base64)
# Helix queue configuration
-# Public (open) queues for PR validation and public project builds
-- ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}:
+# Public (open) queues
+- ${{ if eq(variables['System.TeamProject'], 'public') }}:
- name: HelixQueuesWindows_x64
- value: windows.11.amd64.client.Open
+ value: Windows.Amd64.Server2022.Open
- name: HelixQueuesWindows_x86
- value: windows.11.amd64.client.Open
+ value: Windows.Amd64.Server2022.Open
- name: HelixQueuesWindows_arm64
value: Windows.11.Arm64.Open
- name: HelixQueuesLinux_x64
value: Ubuntu.2204.Amd64.Open
- name: HelixQueuesLinux_arm64
- value: Ubuntu.2204.Arm64.Open
+ value: Ubuntu.2204.ArmArch.Open
- name: HelixQueuesLinux_musl_x64
value: Ubuntu.2204.Amd64.Open
- name: HelixQueuesLinux_musl_arm64
- value: Ubuntu.2204.Arm64.Open
+ value: Ubuntu.2204.ArmArch.Open
- name: HelixQueuesMacOS_x64
value: OSX.15.Amd64.Open
- name: HelixQueuesMacOS_arm64
value: OSX.15.Arm64.Open
-# Internal queues for official builds (non-PR, non-public)
-- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
+# Internal queues
+- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- name: HelixQueuesWindows_x64
- value: windows.11.amd64.client
+ value: Windows.Amd64.Server2022
- name: HelixQueuesWindows_x86
- value: windows.11.amd64.client
+ value: Windows.Amd64.Server2022
- name: HelixQueuesWindows_arm64
- value: windows.11.arm64
+ value: Windows.11.Arm64
- name: HelixQueuesLinux_x64
value: Ubuntu.2204.Amd64
- name: HelixQueuesLinux_arm64
- value: Ubuntu.2204.Arm64
+ value: Ubuntu.2204.ArmArch
- name: HelixQueuesLinux_musl_x64
value: Ubuntu.2204.Amd64
- name: HelixQueuesLinux_musl_arm64
- value: Ubuntu.2204.Arm64
+ value: Ubuntu.2204.ArmArch
- name: HelixQueuesMacOS_x64
value: OSX.15.Amd64
- name: HelixQueuesMacOS_arm64
From 82c4cf8a20c2a41049625fee350ea21645fcc3a3 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 13 Feb 2026 15:45:17 -0500
Subject: [PATCH 22/48] fix trx generation
---
eng/helix.proj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index 2e0356e18a..32304d2ab2 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -211,7 +211,7 @@
$(TestArtifactsDir)bin\%(HelixTestProject.Identity)\$(Configuration)\$(NetCoreAppMinTargetFramework)
- dotnet test %(HelixTestProject.Identity).dll --logger "trx;LogFileName=$(_UploadRoot)\%(HelixTestProject.Identity).trx"
+ dotnet test %(HelixTestProject.Identity).dll --logger "trx;LogFileName=$(_UploadRoot)$(_PathSep)%(HelixTestProject.Identity).trx"
$(TestTimeout)
From 5865aa883f46ce97c775f712f08f9c98b3be4c67 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Tue, 17 Feb 2026 10:41:45 -0500
Subject: [PATCH 23/48] update helix configs
---
eng/helix.proj | 35 +++++++++++++++++++++++++++++------
1 file changed, 29 insertions(+), 6 deletions(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index 32304d2ab2..c39a159676 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -33,6 +33,7 @@
test/$(Configuration)/$(TargetArchitecture)/
$(BUILD_BUILDNUMBER)
0.0.0.0
+ $(TargetOS)-$(Configuration)-$(TargetArchitecture)-
$(ArtifactsDir)
@@ -58,14 +59,36 @@
<_ArtifactsDir>$(_CorrelationPayload)$(_PathSep)artifacts$(_PathSep)
<_VersionsFile>$(_ArtifactsDir)dotnet-test$(_PathSep)Debugger.Tests.Versions.txt
-
- set "DIAGNOSTICS_ARTIFACTS_DIR=$(_ArtifactsDir)" && set "RunningOnHelix=true" && copy /Y "$(_VersionsFile)" "$(_DotNetCliDir)$(_PathSep)Debugger.Tests.Versions.txt"
- export DIAGNOSTICS_ARTIFACTS_DIR="$(_ArtifactsDir)" && export RunningOnHelix=true && cp -f "$(_VersionsFile)" "$(_DotNetCliDir)/Debugger.Tests.Versions.txt"
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<_VersionsStagingDir>$(ArtifactsDir)tmp\helix\dotnet-test\
From 34528ffd5399e612f7ed66509b41d90cacd4eddc Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Tue, 17 Feb 2026 13:16:59 -0500
Subject: [PATCH 24/48] modify precommands
---
eng/helix.proj | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/eng/helix.proj b/eng/helix.proj
index c39a159676..9fa7326580 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -88,6 +88,10 @@
+
+ @(HelixPreCommand)
+
+
<_VersionsStagingDir>$(ArtifactsDir)tmp\helix\dotnet-test\
From 4b80d2a4a91e1bc5cf99b82aeec59e462d4bad45 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Tue, 17 Feb 2026 14:03:40 -0500
Subject: [PATCH 25/48] make sure to target x86 on the x86 arch
---
eng/helix.proj | 2 ++
1 file changed, 2 insertions(+)
diff --git a/eng/helix.proj b/eng/helix.proj
index 9fa7326580..657edc096f 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -47,6 +47,8 @@
true
sdk
$([System.Text.RegularExpressions.Regex]::Match('$(MicrosoftNETSdkVersion)', '^\d+\.\d+\.\d+').Value)
+
+ win-x86
<_CorrelationPayload Condition="'$(TargetOS)' == 'Windows_NT'">%HELIX_CORRELATION_PAYLOAD%
From f54d70fa58c6456358593931162b8e150a736c2a Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Tue, 17 Feb 2026 14:05:56 -0500
Subject: [PATCH 26/48] update name
---
eng/helix.proj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index 657edc096f..27cdcc140b 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -33,7 +33,7 @@
test/$(Configuration)/$(TargetArchitecture)/
$(BUILD_BUILDNUMBER)
0.0.0.0
- $(TargetOS)-$(Configuration)-$(TargetArchitecture)-
+ $(TargetOS) $(TargetArchitecture) $(Configuration) @
$(ArtifactsDir)
From ae3de630c1270d3e9bbdbc14c6189b47b518ec6f Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Tue, 17 Feb 2026 14:10:02 -0500
Subject: [PATCH 27/48] enable DevToolsSecurity on OSX helix queues
---
eng/helix.proj | 3 +++
1 file changed, 3 insertions(+)
diff --git a/eng/helix.proj b/eng/helix.proj
index 27cdcc140b..5b206f0bea 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -78,6 +78,9 @@
+
+
+
From bb29b536ca6b6100ba3fc9cce569ba317591e736 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Tue, 17 Feb 2026 16:34:04 -0500
Subject: [PATCH 28/48] fix TMPDIR and macOS /tmp symlink resolution for Helix
- Linux: Set TMPDIR=/tmp to ensure consistent diagnostic IPC socket paths
(Helix agents may set TMPDIR to non-writable work item temp dirs)
- macOS: Set TMPDIR=/private/tmp (resolved /tmp symlink)
- macOS: Resolve HELIX_CORRELATION_PAYLOAD through /tmp -> /private/tmp
symlink so all derived paths match what the runtime reports
- macOS: Add ResolveMacOSDotNetRoot target to resolve DOTNET_ROOT after
Helix SDK sets it (fixes BasicProcessInfoSuspendTest path mismatch)
---
eng/helix.proj | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/eng/helix.proj b/eng/helix.proj
index 5b206f0bea..0f1825d341 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -74,6 +74,12 @@
+
+
+
+
@@ -87,6 +93,8 @@
+
+
@@ -96,6 +104,15 @@
@(HelixPreCommand)
+
+
+
+
+ $(HelixPreCommands);export DOTNET_ROOT=$(python3 -c "import os; print(os.path.realpath('$DOTNET_ROOT'))")
+
+
From ef54cbcac16a363cd1f23ae2fa847f3c5a6f597b Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Tue, 17 Feb 2026 17:10:47 -0500
Subject: [PATCH 29/48] fix MSBuild escaping for shell command substitution on
macOS
MSBuild was interpreting \ as a property reference,
resolving to empty. Use %24 to escape the dollar sign so MSBuild
emits a literal \ for shell command substitution.
---
eng/helix.proj | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index 0f1825d341..3e7042cd93 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -79,7 +79,7 @@
-
+
@@ -110,7 +110,7 @@
- $(HelixPreCommands);export DOTNET_ROOT=$(python3 -c "import os; print(os.path.realpath('$DOTNET_ROOT'))")
+ $(HelixPreCommands);export DOTNET_ROOT=%24(python3 -c "import os; print(os.path.realpath('$DOTNET_ROOT'))")
From a7974dd24fc13cb2c6b8db6f7bc3368e2823177e Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Tue, 17 Feb 2026 17:14:53 -0500
Subject: [PATCH 30/48] add diagnostics-pr-build-results skill
Copilot CLI skill that looks up CI build results for a PR:
- Finds ADO builds via GitHub PR status or ADO API
- Extracts Helix job IDs from ADO build logs
- Queries Helix API for per-work-item test results
- Includes reference tables for test suites and build configs
---
.../diagnostics-pr-build-results/SKILL.md | 163 ++++++++++++++++++
1 file changed, 163 insertions(+)
create mode 100644 .github/skills/diagnostics-pr-build-results/SKILL.md
diff --git a/.github/skills/diagnostics-pr-build-results/SKILL.md b/.github/skills/diagnostics-pr-build-results/SKILL.md
new file mode 100644
index 0000000000..a4b8d2df93
--- /dev/null
+++ b/.github/skills/diagnostics-pr-build-results/SKILL.md
@@ -0,0 +1,163 @@
+---
+name: diagnostics-pr-build-results
+description: Look up CI build results for a pull request to the diagnostics repository. Use this when asked to check build status, investigate CI failures, or get test results for a PR number. Covers ADO pipeline results and Helix test work items.
+---
+
+# Diagnostics PR Build Results Lookup
+
+Use this skill to find and analyze CI build results for pull requests in the dotnet/diagnostics repository.
+
+## Pipeline Details
+
+- **ADO Organization**: `dnceng-public`
+- **ADO Project**: `public`
+- **Pipeline Definition ID**: `25` (diagnostics-public-ci)
+- **Pipeline URL**: https://dev.azure.com/dnceng-public/public/_build?definitionId=25
+- **Helix API**: https://helix.dot.net/api
+
+## Step 1: Find the ADO Build for a PR
+
+### Option A: From GitHub (preferred)
+
+Use the GitHub MCP server to get check runs for the PR:
+
+1. Use `github-mcp-server-pull_request_read` with `method: "get_status"` on `owner: "dotnet"`, `repo: "diagnostics"`, `pullNumber: ` to get the commit status and check runs.
+2. Look for the check run from Azure Pipelines — it will have a `target_url` pointing to `dev.azure.com/dnceng-public/public/_build/results?buildId=`.
+3. Extract the `buildId` from the URL.
+
+### Option B: From ADO directly
+
+Query ADO for builds triggered by the PR branch:
+
+```
+GET https://dev.azure.com/dnceng-public/public/_apis/build/builds?definitions=25&branchName=refs/pull//merge&$top=5&api-version=7.0
+```
+
+Use the ADO PAT for authentication (Basic auth with `:PAT` base64-encoded).
+
+## Step 2: Get Build Results from ADO
+
+Once you have the `buildId`:
+
+1. **Get the build timeline** to see all jobs and their status:
+ ```
+ GET https://dev.azure.com/dnceng-public/public/_apis/build/builds//timeline?api-version=7.0
+ ```
+
+2. **Find "Send Tests to Helix" tasks** in the timeline records:
+ - Filter for records where `name` contains "Send Tests to Helix"
+ - Check `result` (succeeded/failed) and `state` (completed)
+ - Each has a parent record chain: Stage > Phase > Job > Task
+
+3. **Get Helix Job IDs** from the task logs:
+ - Get the log URL from `record.log.url`
+ - Fetch the log content and search for `Sent Helix Job.*jobs/([a-f0-9-]+)` to extract Helix job IDs
+
+4. **Map jobs to build configurations** by traversing the parent chain in the timeline:
+ - Task → Job → Phase (has config name like `MacOS_arm64_Debug`) → Stage
+
+## Step 3: Query Helix for Test Results
+
+With the Helix job ID and access token:
+
+1. **List work items**:
+ ```
+ GET https://helix.dot.net/api/jobs//workitems?api-version=2019-06-17&access_token=
+ ```
+
+2. **Get work item details** (for failed items):
+ ```
+ GET https://helix.dot.net/api/jobs//workitems/?api-version=2019-06-17&access_token=
+ ```
+ Returns `State` (Failed/Passed), `ExitCode`, `ConsoleOutputUri`, `Files`.
+
+3. **Get console log** for a failed work item:
+ ```
+ GET &access_token=
+ ```
+ Search for `FAIL`, `Error Message:`, `Assert`, `Exception` lines.
+
+## Step 4: Summarize Results
+
+Present results in a table format grouped by platform:
+
+```
+| Platform | Config | Test Suite | Result | Details |
+|-------------------|---------|-------------------|--------|-------------------|
+| Linux_x64 | Debug | EventPipe | PASS | |
+| Linux_x64 | Debug | SOS.UnitTests | FAIL | LLDB 14 broken |
+```
+
+## Authentication
+
+### ADO PAT
+Use Basic authentication with the PAT. The user should provide the PAT, or it may be in the session context.
+```powershell
+$b64 = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat"))
+$hdrs = @{ Authorization = "Basic $b64" }
+Invoke-RestMethod -Uri $url -Headers $hdrs
+```
+
+### Helix Access Token
+Append `&access_token=` to Helix API URLs. The user should provide the token, or it may be in the session context.
+
+## Common Test Suites
+
+These are the Helix work items sent by the diagnostics pipeline:
+
+| Work Item | Description |
+|-----------|-------------|
+| EventPipe.UnitTests | EventPipe functionality |
+| Microsoft.Diagnostics.Monitoring.UnitTests | Monitoring library |
+| Microsoft.FileFormats.UnitTests | File format parsing |
+| Microsoft.SymbolStore.UnitTests | Symbol store |
+| DotnetCounters.UnitTests | dotnet-counters tool |
+| DotnetTrace.UnitTests | dotnet-trace tool |
+| Microsoft.Diagnostics.NETCore.Client.UnitTests | Diagnostics client library |
+| Microsoft.Diagnostics.Monitoring.EventPipe.UnitTests | EventPipe monitoring |
+| SOS.UnitTests | SOS debugger extension (uses LLDB/cdb) |
+| DbgShim.UnitTests | Debug shim (native dependencies) |
+
+## Build Configurations
+
+The pipeline runs these configurations (defined in `diagnostics.yml`):
+
+| OS | Architecture | Config | Helix Queue |
+|----|-------------|--------|-------------|
+| Windows_NT | x64 | Debug/Release | Windows.Amd64.Server2022.Open |
+| Windows_NT | x86 | Release | Windows.Amd64.Server2022.Open |
+| linux | x64 | Debug/Release | Ubuntu.2204.Amd64.Open |
+| linux (musl) | x64 | Debug/Release | Ubuntu.2204.Amd64.Open |
+| osx | x64 | Debug/Release | OSX.15.Amd64.Open |
+| osx | arm64 | Debug/Release | OSX.15.Arm64.Open |
+
+## Quick Reference Script
+
+Here's a PowerShell script to quickly get all Helix results for a build:
+
+```powershell
+$pat = ""
+$helixToken = ""
+$buildId = ""
+
+$b64 = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat"))
+$hdrs = @{ Authorization = "Basic $b64" }
+
+# Get timeline
+$timeline = Invoke-RestMethod -Uri "https://dev.azure.com/dnceng-public/public/_apis/build/builds/$buildId/timeline?api-version=7.0" -Headers $hdrs
+
+# Find Helix tasks and extract job IDs
+$helixTasks = $timeline.records | Where-Object { $_.name -like "*Send Tests to Helix*" -and $_.state -eq 'completed' }
+foreach ($ht in $helixTasks) {
+ $parent = $timeline.records | Where-Object { $_.id -eq $ht.parentId }
+ $grandparent = $timeline.records | Where-Object { $_.id -eq $parent.parentId }
+ $logContent = Invoke-RestMethod -Uri $ht.log.url -Headers $hdrs
+ if ($logContent -match 'jobs/([a-f0-9-]+)') {
+ $jobId = $Matches[1]
+ Write-Host "$($grandparent.name): $($ht.result) | jobId=$jobId"
+ # Get work items
+ $items = Invoke-RestMethod "https://helix.dot.net/api/jobs/$jobId/workitems?api-version=2019-06-17&access_token=$helixToken"
+ # ... process items
+ }
+}
+```
From 6cd02803844deacfd8a533ced3b48020a16240eb Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 18 Feb 2026 09:40:54 -0500
Subject: [PATCH 31/48] try fix lldb on macos
---
eng/helix.proj | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index 3e7042cd93..9305661c88 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -83,7 +83,14 @@
-
+
+
+
+
+
From eb9d9ea869be3157b0d870a2a50d40f6b69ebe99 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 18 Feb 2026 10:19:32 -0500
Subject: [PATCH 32/48] install lldb-16 on Linux Helix and re-sign LLDB on
macOS
---
eng/helix.proj | 3 +++
1 file changed, 3 insertions(+)
diff --git a/eng/helix.proj b/eng/helix.proj
index 9305661c88..8078be8b53 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -103,6 +103,9 @@
+
+
From cb0f185183008a899b4172a995949d713652d1f0 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 18 Feb 2026 10:38:54 -0500
Subject: [PATCH 33/48] fix LLDB rpath: use dirname to get
Contents/SharedFrameworks
---
eng/helix.proj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index 8078be8b53..5835f260af 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -88,7 +88,7 @@
strips the Apple signature, allowing SOS managed commands to initialize the .NET runtime.
See documentation/FAQ.md for the same workaround. -->
-
+
From 822c583a6005a9d1cb744340c5ac7f0a259b7215 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 18 Feb 2026 11:44:32 -0500
Subject: [PATCH 34/48] fix: add dpkg lock timeout for LLDB 16 install on Linux
Helix
apt-get was failing with 'Could not get lock /var/lib/dpkg/lock-frontend'
because another process held it. Add -o DPkg::Lock::Timeout=120 to both
apt-get update and install to wait for the lock instead of failing.
---
eng/helix.proj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index 5835f260af..31c517392b 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -105,7 +105,7 @@
-
+
From 0c44a20376fd39756a30d6d4913b99edf70bf2ff Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 18 Feb 2026 13:42:04 -0500
Subject: [PATCH 35/48] fix: unset PYTHONPATH and ensure /usr/bin/python for
LLDBPluginTests
SOS.LLDBPluginTests uses PYTHONPATH as the Python binary path, but Helix
sets PYTHONPATH to a colon-delimited import path string. Unset it so the
test falls back to /usr/bin/python, and create a symlink if needed.
---
eng/helix.proj | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/eng/helix.proj b/eng/helix.proj
index 31c517392b..0304addfd0 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -109,6 +109,11 @@
+
+
+
From 90285c452724080feaeab5beb0f8025d823d6d06 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 18 Feb 2026 14:48:17 -0500
Subject: [PATCH 36/48] fix: include musl suffix in Helix TestRunNamePrefix
Thread osSuffix parameter from diagnostics.yml through build.yml and
send-to-helix.yml to helix.proj so that linux-musl runs display as
'linux-musl x64 Debug' instead of 'linux x64 Debug'.
---
eng/helix.proj | 2 +-
eng/pipelines/build.yml | 1 +
eng/pipelines/send-to-helix.yml | 7 +++++++
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index 0304addfd0..ee3407ac56 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -33,7 +33,7 @@
test/$(Configuration)/$(TargetArchitecture)/
$(BUILD_BUILDNUMBER)
0.0.0.0
- $(TargetOS) $(TargetArchitecture) $(Configuration) @
+ $(TargetOS)$(OSSuffix) $(TargetArchitecture) $(Configuration) @
$(ArtifactsDir)
diff --git a/eng/pipelines/build.yml b/eng/pipelines/build.yml
index 922bedbcaa..9028093d69 100644
--- a/eng/pipelines/build.yml
+++ b/eng/pipelines/build.yml
@@ -184,6 +184,7 @@ jobs:
configuration: ${{ config.configuration }}
architecture: ${{ config.architecture }}
osGroup: ${{ parameters.osGroup }}
+ osSuffix: ${{ parameters.osSuffix }}
helixQueues: ${{ parameters.helixQueues }}
isOfficialBuild: ${{ parameters.isOfficialBuild }}
diff --git a/eng/pipelines/send-to-helix.yml b/eng/pipelines/send-to-helix.yml
index d7172ade5a..ce97117898 100644
--- a/eng/pipelines/send-to-helix.yml
+++ b/eng/pipelines/send-to-helix.yml
@@ -27,6 +27,11 @@ parameters:
- Linux
- MacOS
+ # OS suffix (e.g. -musl for Alpine Linux)
+- name: osSuffix
+ type: string
+ default: ''
+
# Helix queue to target
- name: helixQueues
type: string
@@ -64,6 +69,7 @@ steps:
/p:Configuration=${{ parameters.configuration }}
/p:TargetArchitecture=${{ parameters.architecture }}
/p:TargetOS=linux
+ /p:OSSuffix=${{ parameters.osSuffix }}
/p:HelixTargetQueues=${{ parameters.helixQueues }}
/p:HelixSource=official/diagnostics/$(Build.SourceBranch)
/p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
@@ -117,6 +123,7 @@ steps:
/p:Configuration=${{ parameters.configuration }}
/p:TargetArchitecture=${{ parameters.architecture }}
/p:TargetOS=linux
+ /p:OSSuffix=${{ parameters.osSuffix }}
/p:HelixTargetQueues=${{ parameters.helixQueues }}
/p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
/p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
From 98aa801dddcc708d85c46f4445d09776bb43d5ce Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 18 Feb 2026 14:53:21 -0500
Subject: [PATCH 37/48] Use Alpine container queues for linux-musl Helix tests
Switch musl Helix queues from Ubuntu.2204 (glibc) to Alpine 3.23
containers so musl-linked native binaries (libdbgshim.so,
libsosplugin.so) can load correctly. Split Linux pre-commands:
- Non-musl: apt-get based LLDB 16 install (Ubuntu)
- Musl: apk based LLDB/Python install (Alpine)
---
eng/helix.proj | 18 ++++++++++++++----
eng/pipelines/global-variables.yml | 8 ++++----
2 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index ee3407ac56..a91fa0392e 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -96,16 +96,13 @@
-
+
-
-
@@ -113,9 +110,22 @@
SOS.LLDBPluginTests misuses it as the path to the Python binary. Also ensure
/usr/bin/python exists since the test falls back to it. -->
+
+
+
+
+
+
+
+
+
+
+
+
@(HelixPreCommand)
diff --git a/eng/pipelines/global-variables.yml b/eng/pipelines/global-variables.yml
index b1cc3b96c3..30c83a0b46 100644
--- a/eng/pipelines/global-variables.yml
+++ b/eng/pipelines/global-variables.yml
@@ -72,9 +72,9 @@ variables:
- name: HelixQueuesLinux_arm64
value: Ubuntu.2204.ArmArch.Open
- name: HelixQueuesLinux_musl_x64
- value: Ubuntu.2204.Amd64.Open
+ value: (Alpine.323.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.23-helix-amd64
- name: HelixQueuesLinux_musl_arm64
- value: Ubuntu.2204.ArmArch.Open
+ value: (Alpine.323.ArmArch.Open)Ubuntu.2204.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.23-helix-arm64v8
- name: HelixQueuesMacOS_x64
value: OSX.15.Amd64.Open
- name: HelixQueuesMacOS_arm64
@@ -93,9 +93,9 @@ variables:
- name: HelixQueuesLinux_arm64
value: Ubuntu.2204.ArmArch
- name: HelixQueuesLinux_musl_x64
- value: Ubuntu.2204.Amd64
+ value: (Alpine.323.Amd64)Ubuntu.2204.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.23-helix-amd64
- name: HelixQueuesLinux_musl_arm64
- value: Ubuntu.2204.ArmArch
+ value: (Alpine.323.ArmArch)Ubuntu.2204.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.23-helix-arm64v8
- name: HelixQueuesMacOS_x64
value: OSX.15.Amd64
- name: HelixQueuesMacOS_arm64
From 6e187e9f91fd9b290c07a093f741b8a389e44f9c Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 18 Feb 2026 15:28:38 -0500
Subject: [PATCH 38/48] Quote HelixTargetQueues for container queue syntax
Alpine container queue names contain () and @ characters that bash
interprets as subshell/special chars. Quote the /p:HelixTargetQueues
parameter in all send-to-helix.yml steps to prevent shell errors.
---
eng/pipelines/send-to-helix.yml | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/eng/pipelines/send-to-helix.yml b/eng/pipelines/send-to-helix.yml
index ce97117898..448a2b9395 100644
--- a/eng/pipelines/send-to-helix.yml
+++ b/eng/pipelines/send-to-helix.yml
@@ -52,7 +52,7 @@ steps:
/p:Configuration=${{ parameters.configuration }}
/p:TargetArchitecture=${{ parameters.architecture }}
/p:TargetOS=Windows_NT
- /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ "/p:HelixTargetQueues=${{ parameters.helixQueues }}"
/p:HelixSource=official/diagnostics/$(Build.SourceBranch)
/p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
/p:HelixAccessToken=$(HelixApiAccessToken)
@@ -70,7 +70,7 @@ steps:
/p:TargetArchitecture=${{ parameters.architecture }}
/p:TargetOS=linux
/p:OSSuffix=${{ parameters.osSuffix }}
- /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ "/p:HelixTargetQueues=${{ parameters.helixQueues }}"
/p:HelixSource=official/diagnostics/$(Build.SourceBranch)
/p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
/p:HelixAccessToken=$(HelixApiAccessToken)
@@ -87,7 +87,7 @@ steps:
/p:Configuration=${{ parameters.configuration }}
/p:TargetArchitecture=${{ parameters.architecture }}
/p:TargetOS=osx
- /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ "/p:HelixTargetQueues=${{ parameters.helixQueues }}"
/p:HelixSource=official/diagnostics/$(Build.SourceBranch)
/p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
/p:HelixAccessToken=$(HelixApiAccessToken)
@@ -106,7 +106,7 @@ steps:
/p:Configuration=${{ parameters.configuration }}
/p:TargetArchitecture=${{ parameters.architecture }}
/p:TargetOS=Windows_NT
- /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ "/p:HelixTargetQueues=${{ parameters.helixQueues }}"
/p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
/p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
/p:Creator=$(Build.RequestedFor)
@@ -124,7 +124,7 @@ steps:
/p:TargetArchitecture=${{ parameters.architecture }}
/p:TargetOS=linux
/p:OSSuffix=${{ parameters.osSuffix }}
- /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ "/p:HelixTargetQueues=${{ parameters.helixQueues }}"
/p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
/p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
/p:Creator=$(Build.RequestedFor)
@@ -141,7 +141,7 @@ steps:
/p:Configuration=${{ parameters.configuration }}
/p:TargetArchitecture=${{ parameters.architecture }}
/p:TargetOS=osx
- /p:HelixTargetQueues=${{ parameters.helixQueues }}
+ "/p:HelixTargetQueues=${{ parameters.helixQueues }}"
/p:HelixSource=pr/diagnostics/$(Build.SourceBranch)
/p:HelixType=test/${{ parameters.configuration }}/${{ parameters.architecture }}/
/p:Creator=$(Build.RequestedFor)
From 3b5419f080be6810f92723c9f603fe792ec00f04 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 18 Feb 2026 16:54:16 -0500
Subject: [PATCH 39/48] Quote Alpine container queue values in YAML
The @ character is reserved in YAML and must be quoted in plain
scalars. Add single quotes around the container queue values to
prevent YAML parsing failures.
---
eng/pipelines/global-variables.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/eng/pipelines/global-variables.yml b/eng/pipelines/global-variables.yml
index 30c83a0b46..0818636278 100644
--- a/eng/pipelines/global-variables.yml
+++ b/eng/pipelines/global-variables.yml
@@ -72,9 +72,9 @@ variables:
- name: HelixQueuesLinux_arm64
value: Ubuntu.2204.ArmArch.Open
- name: HelixQueuesLinux_musl_x64
- value: (Alpine.323.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.23-helix-amd64
+ value: '(Alpine.323.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.23-helix-amd64'
- name: HelixQueuesLinux_musl_arm64
- value: (Alpine.323.ArmArch.Open)Ubuntu.2204.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.23-helix-arm64v8
+ value: '(Alpine.323.ArmArch.Open)Ubuntu.2204.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.23-helix-arm64v8'
- name: HelixQueuesMacOS_x64
value: OSX.15.Amd64.Open
- name: HelixQueuesMacOS_arm64
@@ -93,9 +93,9 @@ variables:
- name: HelixQueuesLinux_arm64
value: Ubuntu.2204.ArmArch
- name: HelixQueuesLinux_musl_x64
- value: (Alpine.323.Amd64)Ubuntu.2204.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.23-helix-amd64
+ value: '(Alpine.323.Amd64)Ubuntu.2204.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.23-helix-amd64'
- name: HelixQueuesLinux_musl_arm64
- value: (Alpine.323.ArmArch)Ubuntu.2204.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.23-helix-arm64v8
+ value: '(Alpine.323.ArmArch)Ubuntu.2204.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.23-helix-arm64v8'
- name: HelixQueuesMacOS_x64
value: OSX.15.Amd64
- name: HelixQueuesMacOS_arm64
From 7fb1fa34cfb47c91047bda71718f32784f0996ad Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Thu, 19 Feb 2026 11:47:03 -0500
Subject: [PATCH 40/48] Fix Linux reporter crash and musl read-only filesystem
1. Remove 'unset PYTHONPATH' from common Linux pre-commands. This was
breaking the Helix result reporter (ModuleNotFoundError: No module
named 'helix'), causing ALL Linux x64 tests to be marked as failed
even though the tests themselves pass.
2. Fix musl container read-only filesystem: correlation payload is
mounted read-only in Docker containers, so cp into dotnet-cli/
fails. Create a writable DOTNET_ROOT overlay using symlinks and
copy Versions.txt there instead.
3. Move Versions.txt cp into platform-specific sections since the
approach differs between Ubuntu (direct cp) and Alpine (overlay).
---
eng/helix.proj | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index a91fa0392e..95f4a9f779 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -102,26 +102,28 @@
-
-
-
+
-
+
+
+
+
+
+
From 1f64ad546b2c182b3c77182baf3dd8afb578539d Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Thu, 19 Feb 2026 13:02:08 -0500
Subject: [PATCH 41/48] Fix musl DOTNET_ROOT override and symlink glob
Two issues fixed:
1. DOTNET_ROOT/PATH overrides were being clobbered by Helix SDK's
AddDotNetSdk target which runs after our pre-commands. Move the
overrides to a FixMuslDotNetRoot Target (AfterTargets=AddDotNetSdk)
so they take effect after the SDK sets its values.
2. The * glob in 'ln -sf .../dotnet-cli/*' was treated as an MSBuild
file wildcard, causing the item to silently produce no output.
Escape as %2A so MSBuild passes it through as a literal *. Also
use a for loop with %3B-escaped semicolons for proper bash syntax.
---
eng/helix.proj | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index 95f4a9f779..4be6964ee7 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -117,13 +117,12 @@
+ so create a writable DOTNET_ROOT overlay using symlinks and copy Versions.txt there.
+ The DOTNET_ROOT/PATH overrides happen in FixMuslDotNetRoot target (after AddDotNetSdk). -->
-
+
-
-
@@ -140,6 +139,16 @@
$(HelixPreCommands);export DOTNET_ROOT=%24(python3 -c "import os; print(os.path.realpath('$DOTNET_ROOT'))")
+
+
+
+
+ $(HelixPreCommands);export DOTNET_ROOT=/tmp/dotnet-writable;export PATH=/tmp/dotnet-writable:$PATH
+
+
From f26143ff20cdf89a6f35ca2ce10994e6b84aae9a Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Thu, 19 Feb 2026 14:09:20 -0500
Subject: [PATCH 42/48] try fix
---
eng/helix.proj | 21 +------------------
.../Unix/Debugger.Tests.Config.txt | 2 +-
.../Windows/Debugger.Tests.Config.txt | 2 +-
.../Unix/Debugger.Tests.Config.txt | 2 +-
.../Windows/Debugger.Tests.Config.txt | 2 +-
.../Unix/Debugger.Tests.Config.txt | 2 +-
.../Windows/Debugger.Tests.Config.txt | 2 +-
7 files changed, 7 insertions(+), 26 deletions(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index 4be6964ee7..eca707e955 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -59,7 +59,6 @@
<_PathSep Condition="'$(TargetOS)' != 'Windows_NT'">/
<_DotNetCliDir>$(_CorrelationPayload)$(_PathSep)dotnet-cli
<_ArtifactsDir>$(_CorrelationPayload)$(_PathSep)artifacts$(_PathSep)
- <_VersionsFile>$(_ArtifactsDir)dotnet-test$(_PathSep)Debugger.Tests.Versions.txt
@@ -69,7 +68,6 @@
-
@@ -82,7 +80,6 @@
-
-
-
+
-
-
-
@@ -140,16 +131,6 @@
-
-
-
- $(HelixPreCommands);export DOTNET_ROOT=/tmp/dotnet-writable;export PATH=/tmp/dotnet-writable:$PATH
-
-
-
<_VersionsStagingDir>$(ArtifactsDir)tmp\helix\dotnet-test\
diff --git a/src/tests/CommonTestRunner/ConfigFiles/Unix/Debugger.Tests.Config.txt b/src/tests/CommonTestRunner/ConfigFiles/Unix/Debugger.Tests.Config.txt
index b102146da0..e2f22b01b9 100644
--- a/src/tests/CommonTestRunner/ConfigFiles/Unix/Debugger.Tests.Config.txt
+++ b/src/tests/CommonTestRunner/ConfigFiles/Unix/Debugger.Tests.Config.txt
@@ -1,7 +1,7 @@
$(ArtifactsDir)/dotnet-test
-
+
$(ArtifactsDir)/bin/$(OS).$(TargetArchitecture).$(TargetConfiguration)
$(ArtifactsDir)/TestResults/$(TargetConfiguration)/common.unittests_$(Timestamp)
diff --git a/src/tests/CommonTestRunner/ConfigFiles/Windows/Debugger.Tests.Config.txt b/src/tests/CommonTestRunner/ConfigFiles/Windows/Debugger.Tests.Config.txt
index 2e49e7dc21..f651aa0010 100644
--- a/src/tests/CommonTestRunner/ConfigFiles/Windows/Debugger.Tests.Config.txt
+++ b/src/tests/CommonTestRunner/ConfigFiles/Windows/Debugger.Tests.Config.txt
@@ -1,7 +1,7 @@
$(ArtifactsDir)\dotnet-test
-
+
$(ArtifactsDir)\bin\Windows_NT.$(TargetArchitecture).$(TargetConfiguration)
$(ArtifactsDir)\TestResults\$(TargetConfiguration)\common.unittests_$(Timestamp)
diff --git a/src/tests/DbgShim.UnitTests/ConfigFiles/Unix/Debugger.Tests.Config.txt b/src/tests/DbgShim.UnitTests/ConfigFiles/Unix/Debugger.Tests.Config.txt
index 0100eff6a7..3e39f6a4c5 100644
--- a/src/tests/DbgShim.UnitTests/ConfigFiles/Unix/Debugger.Tests.Config.txt
+++ b/src/tests/DbgShim.UnitTests/ConfigFiles/Unix/Debugger.Tests.Config.txt
@@ -1,7 +1,7 @@
$(ArtifactsDir)/dotnet-test
-
+
$(ArtifactsDir)/bin/$(OS).$(TargetArchitecture).$(TargetConfiguration)
$(ArtifactsDir)/TestResults/$(TargetConfiguration)/dbgshim.unittests_$(Timestamp)
diff --git a/src/tests/DbgShim.UnitTests/ConfigFiles/Windows/Debugger.Tests.Config.txt b/src/tests/DbgShim.UnitTests/ConfigFiles/Windows/Debugger.Tests.Config.txt
index 4687626e3f..ae82bb14a2 100644
--- a/src/tests/DbgShim.UnitTests/ConfigFiles/Windows/Debugger.Tests.Config.txt
+++ b/src/tests/DbgShim.UnitTests/ConfigFiles/Windows/Debugger.Tests.Config.txt
@@ -1,7 +1,7 @@
$(ArtifactsDir)\dotnet-test
-
+
$(ArtifactsDir)\bin\Windows_NT.$(TargetArchitecture).$(TargetConfiguration)
$(ArtifactsDir)\TestResults\$(TargetConfiguration)\dbgshim.unittests_$(Timestamp)
diff --git a/src/tests/SOS.UnitTests/ConfigFiles/Unix/Debugger.Tests.Config.txt b/src/tests/SOS.UnitTests/ConfigFiles/Unix/Debugger.Tests.Config.txt
index 2d0c1d3e75..73f496669a 100644
--- a/src/tests/SOS.UnitTests/ConfigFiles/Unix/Debugger.Tests.Config.txt
+++ b/src/tests/SOS.UnitTests/ConfigFiles/Unix/Debugger.Tests.Config.txt
@@ -10,7 +10,7 @@
$(ArtifactsDir)/dotnet-test
-
+
ProjectK
$(ArtifactsDir)/bin/SOS.UnitTests/Scripts
diff --git a/src/tests/SOS.UnitTests/ConfigFiles/Windows/Debugger.Tests.Config.txt b/src/tests/SOS.UnitTests/ConfigFiles/Windows/Debugger.Tests.Config.txt
index c99d4f2daf..efe29c2de1 100644
--- a/src/tests/SOS.UnitTests/ConfigFiles/Windows/Debugger.Tests.Config.txt
+++ b/src/tests/SOS.UnitTests/ConfigFiles/Windows/Debugger.Tests.Config.txt
@@ -10,7 +10,7 @@
$(ArtifactsDir)\dotnet-test
-
+
$(ArtifactsDir)\bin\SOS.UnitTests\Scripts
$(ArtifactsDir)\bin\Windows_NT.$(TargetArchitecture).$(TargetConfiguration)
From 1bb42e63cb5e849de8cdac48f011447f0484efdb Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Thu, 19 Feb 2026 16:26:43 -0500
Subject: [PATCH 43/48] try updating musl configuration
---
eng/helix.proj | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index eca707e955..92ddca6559 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -112,8 +112,15 @@
-
+
+
+
+
+
+
From 7dea34a49ab3006bc552c0b223d53929604ad69d Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Thu, 19 Feb 2026 16:33:56 -0500
Subject: [PATCH 44/48] update python lookup
---
src/tests/SOS.UnitTests/SOS.cs | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/src/tests/SOS.UnitTests/SOS.cs b/src/tests/SOS.UnitTests/SOS.cs
index 6f652276ff..3da9c380e6 100644
--- a/src/tests/SOS.UnitTests/SOS.cs
+++ b/src/tests/SOS.UnitTests/SOS.cs
@@ -715,16 +715,19 @@ public async Task LLDBPluginTests(TestConfiguration config)
}
else
{
- program = Environment.GetEnvironmentVariable("PYTHONPATH");
- if (program == null)
+ string pythonPath = Environment.GetEnvironmentVariable("PYTHONPATH");
+ if (pythonPath != null)
+ {
+ // PYTHONPATH is a colon-separated search path; the first entry may be the python binary.
+ program = pythonPath.Split(':')[0];
+ }
+ else
{
- // We should verify what python version this is. 2.7 is out of
- // support for a while now, but we have old OS's.
program = "/usr/bin/python";
}
if (!File.Exists(program))
{
- throw new ArgumentException($"{program} does not exists");
+ throw new ArgumentException($"Cannot find python at {program}");
}
}
string artifactsDir = TestConfiguration.MakeCanonicalPath(config.AllSettings["ArtifactsDir"]);
From bf18862091d30075bdb4ad805839b189efc4f5d3 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Thu, 19 Feb 2026 17:32:05 -0500
Subject: [PATCH 45/48] try fixing linux lldb
---
eng/helix.proj | 2 ++
1 file changed, 2 insertions(+)
diff --git a/eng/helix.proj b/eng/helix.proj
index 92ddca6559..87ae1e1f44 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -109,6 +109,8 @@
+
+
From afe36a01c71fc4228ddd3f69cba848c71af60cca Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 20 Feb 2026 10:42:11 -0500
Subject: [PATCH 46/48] change on musl to copy to writable directory
---
eng/helix.proj | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index 87ae1e1f44..07ac1e7b23 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -115,13 +115,9 @@
+ containers, so copy the artifacts directory to a writable location. -->
-
-
-
-
+
From 2184e3770e0f773c9f6729d6bf7b715d96bed854 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Fri, 20 Feb 2026 15:19:56 -0500
Subject: [PATCH 47/48] try fix issues
---
eng/helix.proj | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index 07ac1e7b23..c1f28514fa 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -37,7 +37,7 @@
$(ArtifactsDir)
- 00:30:00
+ 01:00:00
true
@@ -119,7 +119,7 @@
-
+
From 52d3fb6bbc4ef3cbf3428fd411430cd2783b7a39 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Mon, 23 Feb 2026 11:07:19 -0500
Subject: [PATCH 48/48] increase SOS timeout
---
eng/helix.proj | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/eng/helix.proj b/eng/helix.proj
index c1f28514fa..06986c26c5 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -169,7 +169,9 @@
-
+
+ 01:30:00
+
@@ -283,7 +285,8 @@
Condition="Exists('$(TestArtifactsDir)bin\%(HelixTestProject.Identity)\$(Configuration)\$(NetCoreAppMinTargetFramework)')">
$(TestArtifactsDir)bin\%(HelixTestProject.Identity)\$(Configuration)\$(NetCoreAppMinTargetFramework)
dotnet test %(HelixTestProject.Identity).dll --logger "trx;LogFileName=$(_UploadRoot)$(_PathSep)%(HelixTestProject.Identity).trx"
- $(TestTimeout)
+ %(HelixTestProject.CustomTimeout)
+ $(TestTimeout)