diff --git a/.github/workflows/build-cli-native-archives.yml b/.github/workflows/build-cli-native-archives.yml index 746f7138f86..22d2d662069 100644 --- a/.github/workflows/build-cli-native-archives.yml +++ b/.github/workflows/build-cli-native-archives.yml @@ -20,7 +20,7 @@ jobs: matrix: targets: - os: ubuntu-latest - runner: ubuntu-latest + runner: 8-core-ubuntu-latest rids: linux-x64 - os: windows-latest runner: windows-latest diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 2c2b9b8f419..62ad4c43211 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -80,8 +80,8 @@ jobs: # from the repo always use restored dotnet. For tests run from outside # the repo we install system dotnet earlier in the build - - name: Setup vars (Linux) - if: ${{ inputs.os == 'ubuntu-latest' || inputs.os == 'macos-latest' }} + - name: Setup vars (Linux/macOS) + if: ${{ runner.os != 'Windows' }} run: | echo "DOTNET_SCRIPT=./dotnet.sh" >> $GITHUB_ENV echo "BUILD_SCRIPT=./build.sh" >> $GITHUB_ENV @@ -89,7 +89,7 @@ jobs: echo ${{ github.workspace }}/.dotnet >> $GITHUB_PATH - name: Setup vars (Windows) - if: ${{ inputs.os == 'windows-latest' }} + if: ${{ runner.os == 'Windows' }} run: | echo "DOTNET_SCRIPT=.\dotnet.cmd" >> $env:GITHUB_ENV echo "BUILD_SCRIPT=.\build.cmd" >> $env:GITHUB_ENV @@ -112,7 +112,7 @@ jobs: DOTNET_INSTALL_DIR: ${{ env.DOTNET_ROOT }} - name: Trust HTTPS development certificate (Linux) - if: inputs.os == 'ubuntu-latest' + if: runner.os == 'Linux' # Allow the task to succeed on partial trust. # Remove this workaround once https://github.com/dotnet/aspnetcore/pull/65392 has shipped run: | @@ -127,7 +127,7 @@ jobs: - name: Verify Docker is running # nested docker containers not supported on windows - if: inputs.os == 'ubuntu-latest' + if: runner.os == 'Linux' run: docker info - name: Download built nugets @@ -148,12 +148,12 @@ jobs: id: compute_rid shell: pwsh run: | - $os = "${{ inputs.os }}" - switch ($os) { - 'ubuntu-latest' { $rid = 'linux-x64' } - 'macos-latest' { $rid = 'osx-arm64' } - 'windows-latest'{ $rid = 'win-x64' } - Default { Write-Error "Unknown OS '$os' for RID mapping"; exit 1 } + $runnerOs = "${{ runner.os }}" + switch ($runnerOs) { + 'Linux' { $rid = 'linux-x64' } + 'macOS' { $rid = 'osx-arm64' } + 'Windows' { $rid = 'win-x64' } + Default { Write-Error "Unknown runner.os '$runnerOs' for RID mapping"; exit 1 } } Write-Host "Using RID=$rid" "RID=$rid" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append @@ -195,7 +195,7 @@ jobs: /bl:${{ github.workspace }}/artifacts/log/Debug/InstallSdkForTesting.binlog - name: Install Azure Functions Core Tools - if: inputs.os == 'ubuntu-latest' && (inputs.testShortName == 'Playground' || inputs.testShortName == 'Azure') + if: runner.os == 'Linux' && (inputs.testShortName == 'Playground' || inputs.testShortName == 'Azure') run: | npm i -g azure-functions-core-tools@4 --unsafe-perm true @@ -292,7 +292,7 @@ jobs: uses: ./.github/actions/unlock-macos-keychain - name: Run nuget dependent tests (Linux/macOS) - if: ${{ inputs.requiresNugets && (inputs.os == 'ubuntu-latest' || inputs.os == 'macos-latest') }} + if: ${{ inputs.requiresNugets && runner.os != 'Windows' }} working-directory: ${{ github.workspace }}/run-tests/ env: ASPIRE__TEST__DCPLOGBASEPATH: ${{ github.workspace }}/testresults/dcp @@ -333,7 +333,7 @@ jobs: exit $TEST_EXIT_CODE - name: Run nuget dependent tests (Windows) - if: ${{ inputs.requiresNugets && inputs.os == 'windows-latest' }} + if: ${{ inputs.requiresNugets && runner.os == 'Windows' }} working-directory: ${{ github.workspace }}/run-tests/ shell: pwsh env: @@ -378,7 +378,7 @@ jobs: } - name: Run tests (Linux/macOS) - if: ${{ ! inputs.requiresNugets && (inputs.os == 'ubuntu-latest' || inputs.os == 'macos-latest') }} + if: ${{ ! inputs.requiresNugets && runner.os != 'Windows' }} id: run-tests-unix env: ASPIRE__TEST__DCPLOGBASEPATH: ${{ github.workspace }}/testresults/dcp @@ -422,7 +422,7 @@ jobs: exit $TEST_EXIT_CODE - name: Run tests (Windows) - if: ${{ ! inputs.requiresNugets && inputs.os == 'windows-latest' }} + if: ${{ ! inputs.requiresNugets && runner.os == 'Windows' }} id: run-tests-windows shell: pwsh env: @@ -517,7 +517,7 @@ jobs: Write-Host "✓ Test execution completed successfully (found $validFileCount valid .trx file(s))" - name: Dump docker info - if: ${{ always() && inputs.os == 'ubuntu-latest' }} + if: ${{ always() && runner.os == 'Linux' }} run: | docker container ls --all docker container ls --all --format json diff --git a/docs/ci/TestingOnCI.md b/docs/ci/TestingOnCI.md index 6713a9456ed..17435349cee 100644 --- a/docs/ci/TestingOnCI.md +++ b/docs/ci/TestingOnCI.md @@ -61,6 +61,7 @@ This invokes `eng/TestEnumerationRunsheetBuilder/TestEnumerationRunsheetBuilder. - `testSessionTimeout`, `testHangTimeout` values - `uncollectedTestsSessionTimeout`, `uncollectedTestsHangTimeout` values - `splitTests` flag + - `runners` object (optional, only present when custom runners are configured) ### Phase 2: Test Partition Discovery @@ -108,7 +109,8 @@ After all projects build, `eng/AfterSolutionBuild.targets` runs `eng/scripts/bui "supportedOSes": ["linux"], "requiresNugets": false, "testSessionTimeout": "30m", - "extraTestArgs": "--filter-trait \"Partition=Docker\"" + "extraTestArgs": "--filter-trait \"Partition=Docker\"", + "runners": { "macos": "macos-latest-xlarge" } } ] } @@ -247,6 +249,25 @@ For tests that require Playwright browser automation: This flag is tracked in the test metadata and controls whether Playwright browsers are installed during the test build step. +## Custom GitHub Actions Runners + +By default, tests run on `ubuntu-latest`, `windows-latest`, and `macos-latest`. To override the runner for a specific OS (e.g., to use larger runners or specific OS versions), set the corresponding property in the test project's `.csproj`: + +```xml + + + macos-latest-xlarge + + + ubuntu-24.04 + + + windows-2022 + +``` + +Only set the properties you need to override — unset properties use the default runners. The overrides are emitted as a `runners` object in the test metadata JSON and flow through the canonical matrix to the GitHub Actions expansion, where they replace the default `runs-on` value for the corresponding OS. + ## Deployment Tests Deployment end-to-end tests have a separate flow from the standard test matrix: diff --git a/eng/TestEnumerationRunsheetBuilder/TestEnumerationRunsheetBuilder.targets b/eng/TestEnumerationRunsheetBuilder/TestEnumerationRunsheetBuilder.targets index 849b1a73b9f..baf08aee139 100644 --- a/eng/TestEnumerationRunsheetBuilder/TestEnumerationRunsheetBuilder.targets +++ b/eng/TestEnumerationRunsheetBuilder/TestEnumerationRunsheetBuilder.targets @@ -88,6 +88,15 @@ <_UncollectedTestsHangTimeout Condition="'$(UncollectedTestsHangTimeout)' != ''">$(UncollectedTestsHangTimeout) <_UncollectedTestsHangTimeout Condition="'$(UncollectedTestsHangTimeout)' == ''">10m + + <_RunnersJsonParts /> + <_RunnersJsonParts Condition="'$(GithubActionsRunnerWindows)' != ''">$(_RunnersJsonParts)"windows": "$(GithubActionsRunnerWindows)", + <_RunnersJsonParts Condition="'$(GithubActionsRunnerLinux)' != ''">$(_RunnersJsonParts)"linux": "$(GithubActionsRunnerLinux)", + <_RunnersJsonParts Condition="'$(GithubActionsRunnerMacOS)' != ''">$(_RunnersJsonParts)"macos": "$(GithubActionsRunnerMacOS)", + <_RunnersJsonParts Condition="'$(_RunnersJsonParts)' != ''">$(_RunnersJsonParts.TrimEnd(',')) + <_RunnersJsonLine Condition="'$(_RunnersJsonParts)' != ''">, + "runners": {$(_RunnersJsonParts)} + <_MetadataJson>{ "projectName": "$(MSBuildProjectName)", @@ -103,7 +112,7 @@ "testSessionTimeout": "$(_TestSessionTimeout)", "testHangTimeout": "$(_TestHangTimeout)", "uncollectedTestsSessionTimeout": "$(_UncollectedTestsSessionTimeout)", - "uncollectedTestsHangTimeout": "$(_UncollectedTestsHangTimeout)" + "uncollectedTestsHangTimeout": "$(_UncollectedTestsHangTimeout)"$(_RunnersJsonLine) } diff --git a/eng/Testing.targets b/eng/Testing.targets index f9e66d2b601..a24b8dd0bd9 100644 --- a/eng/Testing.targets +++ b/eng/Testing.targets @@ -21,6 +21,11 @@ - RunOnAzdoHelix: indicates whether tests should run on Helix (either Windows or Linux); computed. - RunOnAzdoHelixWindows: indicates whether tests should run on Windows in Helix; default is true; overridable. - RunOnAzdoHelixLinux: indicates whether tests should run on Linux in Helix; default is true; overridable. + + Custom GitHub Actions runners (optional): + - GithubActionsRunnerWindows: custom GitHub Actions runner for Windows tests; default is unset (uses 'windows-latest'); overridable. + - GithubActionsRunnerLinux: custom GitHub Actions runner for Linux tests; default is unset (uses 'ubuntu-latest'); overridable. + - GithubActionsRunnerMacOS: custom GitHub Actions runner for macOS tests; default is unset (uses 'macos-latest'); overridable. --> diff --git a/eng/scripts/build-test-matrix.ps1 b/eng/scripts/build-test-matrix.ps1 index 68f74d29f55..9c6b67a75cb 100644 --- a/eng/scripts/build-test-matrix.ps1 +++ b/eng/scripts/build-test-matrix.ps1 @@ -112,6 +112,11 @@ function New-RegularTestEntry { # Add supported OSes $entry['supportedOSes'] = @($Metadata.supportedOSes) + # Pass through custom runners if specified + if ($Metadata.PSObject.Properties['runners'] -and $Metadata.runners) { + $entry['runners'] = $Metadata.runners + } + return Complete-EntryWithDefaults $entry } @@ -174,6 +179,11 @@ function New-CollectionTestEntry { $entry['supportedOSes'] = @($Metadata.supportedOSes) } + # Pass through custom runners if specified + if ($Metadata.PSObject.Properties['runners'] -and $Metadata.runners) { + $entry['runners'] = $Metadata.runners + } + return Complete-EntryWithDefaults $entry } @@ -215,6 +225,11 @@ function New-ClassTestEntry { $entry['supportedOSes'] = @($Metadata.supportedOSes) } + # Pass through custom runners if specified + if ($Metadata.PSObject.Properties['runners'] -and $Metadata.runners) { + $entry['runners'] = $Metadata.runners + } + return Complete-EntryWithDefaults $entry } diff --git a/eng/scripts/expand-test-matrix-github.ps1 b/eng/scripts/expand-test-matrix-github.ps1 index 936351d613b..867ad52332d 100644 --- a/eng/scripts/expand-test-matrix-github.ps1 +++ b/eng/scripts/expand-test-matrix-github.ps1 @@ -87,8 +87,16 @@ function Expand-MatrixEntriesByOS { } } - # Add GitHub-specific runner - $expandedEntry['runs-on'] = $runnerMap[$osLower] + # Add GitHub-specific runner (use custom runner if specified and non-empty, otherwise default) + $hasRunners = $entry.PSObject.Properties.Name -contains 'runners' + $customRunner = $null + if ($hasRunners -and $entry.runners) { + $runnerProp = $entry.runners.PSObject.Properties[$osLower] + if ($runnerProp -and -not [string]::IsNullOrWhiteSpace([string]$runnerProp.Value)) { + $customRunner = [string]$runnerProp.Value + } + } + $expandedEntry['runs-on'] = if ($customRunner) { $customRunner } else { $runnerMap[$osLower] } $expandedEntries += [PSCustomObject]$expandedEntry } diff --git a/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj b/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj index 3c1e5c44925..b232054dcf2 100644 --- a/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj +++ b/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj @@ -14,6 +14,8 @@ true Aspire.Hosting.Tests + + 8-core-ubuntu-latest diff --git a/tests/Infrastructure.Tests/PowerShellScripts/BuildTestMatrixTests.cs b/tests/Infrastructure.Tests/PowerShellScripts/BuildTestMatrixTests.cs index 09deb05a9f5..cf107e1d20d 100644 --- a/tests/Infrastructure.Tests/PowerShellScripts/BuildTestMatrixTests.cs +++ b/tests/Infrastructure.Tests/PowerShellScripts/BuildTestMatrixTests.cs @@ -441,6 +441,136 @@ public async Task InheritsSupportedOSesToPartitionEntries() } } + [Fact] + [RequiresTools(["pwsh"])] + public async Task PassesThroughRunnersForRegularTests() + { + // Arrange + var artifactsDir = Path.Combine(_tempDir.Path, "artifacts"); + Directory.CreateDirectory(artifactsDir); + + TestDataBuilder.CreateTestsMetadataJson( + Path.Combine(artifactsDir, "CustomRunner.tests-metadata.json"), + projectName: "CustomRunner", + testProjectPath: "tests/CustomRunner/CustomRunner.csproj", + runners: new Dictionary { ["macos"] = "macos-latest-xlarge" }); + + var outputFile = Path.Combine(_tempDir.Path, "matrix.json"); + + // Act + var result = await RunScript(artifactsDir, outputFile); + + // Assert + result.EnsureSuccessful(); + + var matrix = ParseCanonicalMatrix(outputFile); + var entry = Assert.Single(matrix.Tests); + Assert.NotNull(entry.Runners); + Assert.Single(entry.Runners); + Assert.Equal("macos-latest-xlarge", entry.Runners["macos"]); + } + + [Fact] + [RequiresTools(["pwsh"])] + public async Task OmitsRunnersWhenNotSet() + { + // Arrange + var artifactsDir = Path.Combine(_tempDir.Path, "artifacts"); + Directory.CreateDirectory(artifactsDir); + + TestDataBuilder.CreateTestsMetadataJson( + Path.Combine(artifactsDir, "NoRunner.tests-metadata.json"), + projectName: "NoRunner", + testProjectPath: "tests/NoRunner/NoRunner.csproj"); + + var outputFile = Path.Combine(_tempDir.Path, "matrix.json"); + + // Act + var result = await RunScript(artifactsDir, outputFile); + + // Assert + result.EnsureSuccessful(); + + var matrix = ParseCanonicalMatrix(outputFile); + var entry = Assert.Single(matrix.Tests); + Assert.Null(entry.Runners); + } + + [Fact] + [RequiresTools(["pwsh"])] + public async Task PassesThroughRunnersForPartitionEntries() + { + // Arrange + var artifactsDir = Path.Combine(_tempDir.Path, "artifacts"); + Directory.CreateDirectory(artifactsDir); + + TestDataBuilder.CreateSplitTestsMetadataJson( + Path.Combine(artifactsDir, "SplitRunner.tests-metadata.json"), + projectName: "SplitRunner", + testProjectPath: "tests/SplitRunner/SplitRunner.csproj", + shortName: "SplitR", + runners: new Dictionary { ["linux"] = "ubuntu-24.04" }); + + TestDataBuilder.CreateTestsPartitionsJson( + Path.Combine(artifactsDir, "SplitRunner.tests-partitions.json"), + "PartA"); + + var outputFile = Path.Combine(_tempDir.Path, "matrix.json"); + + // Act + var result = await RunScript(artifactsDir, outputFile); + + // Assert + result.EnsureSuccessful(); + + var matrix = ParseCanonicalMatrix(outputFile); + // All entries (partition + uncollected) should inherit the runners + foreach (var entry in matrix.Tests) + { + Assert.NotNull(entry.Runners); + Assert.Equal("ubuntu-24.04", entry.Runners["linux"]); + } + } + + [Fact] + [RequiresTools(["pwsh"])] + public async Task PassesThroughRunnersForClassEntries() + { + // Arrange + var artifactsDir = Path.Combine(_tempDir.Path, "artifacts"); + Directory.CreateDirectory(artifactsDir); + + TestDataBuilder.CreateSplitTestsMetadataJson( + Path.Combine(artifactsDir, "ClassRunner.tests-metadata.json"), + projectName: "ClassRunner", + testProjectPath: "tests/ClassRunner/ClassRunner.csproj", + shortName: "ClassR", + runners: new Dictionary + { + ["windows"] = "windows-2022", + ["macos"] = "macos-latest-xlarge" + }); + + TestDataBuilder.CreateClassBasedPartitionsJson( + Path.Combine(artifactsDir, "ClassRunner.tests-partitions.json"), + "Ns.ClassA"); + + var outputFile = Path.Combine(_tempDir.Path, "matrix.json"); + + // Act + var result = await RunScript(artifactsDir, outputFile); + + // Assert + result.EnsureSuccessful(); + + var matrix = ParseCanonicalMatrix(outputFile); + var entry = Assert.Single(matrix.Tests); + Assert.NotNull(entry.Runners); + Assert.Equal(2, entry.Runners.Count); + Assert.Equal("windows-2022", entry.Runners["windows"]); + Assert.Equal("macos-latest-xlarge", entry.Runners["macos"]); + } + private async Task RunScript(string artifactsDir, string outputFile) { using var cmd = new PowerShellCommand(_scriptPath, _output) diff --git a/tests/Infrastructure.Tests/PowerShellScripts/ExpandTestMatrixGitHubTests.cs b/tests/Infrastructure.Tests/PowerShellScripts/ExpandTestMatrixGitHubTests.cs index 7908c5f9c9f..2bb7b6c0ab1 100644 --- a/tests/Infrastructure.Tests/PowerShellScripts/ExpandTestMatrixGitHubTests.cs +++ b/tests/Infrastructure.Tests/PowerShellScripts/ExpandTestMatrixGitHubTests.cs @@ -399,6 +399,109 @@ public async Task SplitTestsGoToNoNugetsCategory() Assert.Contains(expanded.Include, e => e.ProjectName == "RegularProject"); } + [Fact] + [RequiresTools(["pwsh"])] + public async Task UsesCustomRunnerForSpecificOS() + { + // Arrange: custom runner for macos only + var entry = TestDataBuilder.CreateMatrixEntry( + name: "CustomRunnerProject", + projectName: "CustomRunnerProject", + testProjectPath: "tests/CustomRunnerProject/CustomRunnerProject.csproj", + supportedOSes: ["windows", "linux", "macos"], + runners: new Dictionary { ["macos"] = "macos-latest-xlarge" }); + + var canonicalMatrix = Path.Combine(_tempDir.Path, "canonical.json"); + TestDataBuilder.CreateCanonicalMatrixJson(canonicalMatrix, tests: [entry]); + + var outputFile = Path.Combine(_tempDir.Path, "expanded.json"); + + // Act + var result = await RunScript(canonicalMatrix, outputMatrixFile: outputFile); + + // Assert + result.EnsureSuccessful(); + + var expanded = ParseGitHubMatrix(outputFile); + Assert.Equal(3, expanded.Include.Length); + + // macos should use custom runner + var macEntry = expanded.Include.First(e => e.RunsOn == "macos-latest-xlarge"); + + // windows and linux should use defaults + Assert.Contains(expanded.Include, e => e.RunsOn == "windows-latest"); + Assert.Contains(expanded.Include, e => e.RunsOn == "ubuntu-latest"); + } + + [Fact] + [RequiresTools(["pwsh"])] + public async Task UsesCustomRunnerForMultipleOSes() + { + // Arrange: custom runners for all three OSes + var entry = TestDataBuilder.CreateMatrixEntry( + name: "AllCustomRunners", + projectName: "AllCustomRunners", + testProjectPath: "tests/AllCustomRunners/AllCustomRunners.csproj", + supportedOSes: ["windows", "linux", "macos"], + runners: new Dictionary + { + ["windows"] = "windows-2022", + ["linux"] = "ubuntu-24.04", + ["macos"] = "macos-latest-xlarge" + }); + + var canonicalMatrix = Path.Combine(_tempDir.Path, "canonical.json"); + TestDataBuilder.CreateCanonicalMatrixJson(canonicalMatrix, tests: [entry]); + + var outputFile = Path.Combine(_tempDir.Path, "expanded.json"); + + // Act + var result = await RunScript(canonicalMatrix, outputMatrixFile: outputFile); + + // Assert + result.EnsureSuccessful(); + + var expanded = ParseGitHubMatrix(outputFile); + Assert.Equal(3, expanded.Include.Length); + Assert.Contains(expanded.Include, e => e.RunsOn == "windows-2022"); + Assert.Contains(expanded.Include, e => e.RunsOn == "ubuntu-24.04"); + Assert.Contains(expanded.Include, e => e.RunsOn == "macos-latest-xlarge"); + + // Verify no default runners are used + Assert.DoesNotContain(expanded.Include, e => e.RunsOn == "windows-latest"); + Assert.DoesNotContain(expanded.Include, e => e.RunsOn == "ubuntu-latest"); + Assert.DoesNotContain(expanded.Include, e => e.RunsOn == "macos-latest"); + } + + [Fact] + [RequiresTools(["pwsh"])] + public async Task UsesDefaultRunnersWhenNoCustomRunnersSet() + { + // Arrange: no runners property + var entry = TestDataBuilder.CreateMatrixEntry( + name: "DefaultRunners", + projectName: "DefaultRunners", + testProjectPath: "tests/DefaultRunners/DefaultRunners.csproj", + supportedOSes: ["windows", "linux", "macos"]); + + var canonicalMatrix = Path.Combine(_tempDir.Path, "canonical.json"); + TestDataBuilder.CreateCanonicalMatrixJson(canonicalMatrix, tests: [entry]); + + var outputFile = Path.Combine(_tempDir.Path, "expanded.json"); + + // Act + var result = await RunScript(canonicalMatrix, outputMatrixFile: outputFile); + + // Assert + result.EnsureSuccessful(); + + var expanded = ParseGitHubMatrix(outputFile); + Assert.Equal(3, expanded.Include.Length); + Assert.Contains(expanded.Include, e => e.RunsOn == "windows-latest"); + Assert.Contains(expanded.Include, e => e.RunsOn == "ubuntu-latest"); + Assert.Contains(expanded.Include, e => e.RunsOn == "macos-latest"); + } + [Fact] [RequiresTools(["pwsh"])] public async Task FullPipeline_SplitTestsExpandPerOS() diff --git a/tests/Infrastructure.Tests/Shared/TestDataBuilder.cs b/tests/Infrastructure.Tests/Shared/TestDataBuilder.cs index ad9f4390d94..fdd356d43d6 100644 --- a/tests/Infrastructure.Tests/Shared/TestDataBuilder.cs +++ b/tests/Infrastructure.Tests/Shared/TestDataBuilder.cs @@ -31,7 +31,8 @@ public static string CreateTestsMetadataJson( bool requiresTestSdk = false, bool requiresCliArchive = false, string? extraTestArgs = null, - string[]? supportedOSes = null) + string[]? supportedOSes = null, + Dictionary? runners = null) { var metadata = new TestMetadata { @@ -45,7 +46,8 @@ public static string CreateTestsMetadataJson( RequiresTestSdk = requiresTestSdk ? "true" : null, RequiresCliArchive = requiresCliArchive ? "true" : null, ExtraTestArgs = extraTestArgs, - SupportedOSes = supportedOSes ?? ["windows", "linux", "macos"] + SupportedOSes = supportedOSes ?? ["windows", "linux", "macos"], + Runners = runners }; var json = JsonSerializer.Serialize(metadata, s_jsonOptions); @@ -72,7 +74,8 @@ public static string CreateSplitTestsMetadataJson( string? uncollectedTestsHangTimeout = null, bool requiresNugets = false, bool requiresTestSdk = false, - string[]? supportedOSes = null) + string[]? supportedOSes = null, + Dictionary? runners = null) { var metadata = new TestMetadata { @@ -86,7 +89,8 @@ public static string CreateSplitTestsMetadataJson( UncollectedTestsHangTimeout = uncollectedTestsHangTimeout, RequiresNugets = requiresNugets ? "true" : null, RequiresTestSdk = requiresTestSdk ? "true" : null, - SupportedOSes = supportedOSes ?? ["windows", "linux", "macos"] + SupportedOSes = supportedOSes ?? ["windows", "linux", "macos"], + Runners = runners }; var json = JsonSerializer.Serialize(metadata, s_jsonOptions); @@ -183,7 +187,8 @@ public static CanonicalMatrixEntry CreateMatrixEntry( bool requiresNugets = false, bool requiresTestSdk = false, bool requiresCliArchive = false, - string[]? supportedOSes = null) + string[]? supportedOSes = null, + Dictionary? runners = null) { return new CanonicalMatrixEntry { @@ -201,7 +206,8 @@ public static CanonicalMatrixEntry CreateMatrixEntry( RequiresNugets = requiresNugets, RequiresTestSdk = requiresTestSdk, RequiresCliArchive = requiresCliArchive, - SupportedOSes = supportedOSes ?? ["windows", "linux", "macos"] + SupportedOSes = supportedOSes ?? ["windows", "linux", "macos"], + Runners = runners }; } @@ -245,6 +251,9 @@ private sealed class TestMetadata [JsonPropertyName("supportedOSes")] public string[] SupportedOSes { get; set; } = ["windows", "linux", "macos"]; + + [JsonPropertyName("runners")] + public Dictionary? Runners { get; set; } } private sealed class TestPartitionsJson @@ -315,6 +324,9 @@ public class CanonicalMatrixEntry [JsonPropertyName("supportedOSes")] public string[] SupportedOSes { get; set; } = ["windows", "linux", "macos"]; + + [JsonPropertyName("runners")] + public Dictionary? Runners { get; set; } } ///