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; }
}
///