From 4e9036e36fd43764d8955cf801ba29b2ab4fb746 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 6 Nov 2025 05:00:55 +0000
Subject: [PATCH 01/41] Initial plan
From 7236d3812934756d0efa87222e7a8e2b8f1a2801 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 6 Nov 2025 05:12:04 +0000
Subject: [PATCH 02/41] Add .NET 10 (preview) as a TFM for multi-targeting
builds
Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
---
Directory.Build.props | 2 +-
Directory.Packages.props | 4 ++++
...CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.csproj | 2 +-
...ommunityToolkit.Aspire.Hosting.SqlServer.Extensions.csproj | 2 +-
4 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 974adbf17..57f2c17f9 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -5,7 +5,7 @@
net8.0
$(DefaultTargetFramework)
- $(DefaultTargetFramework);net9.0
+ $(DefaultTargetFramework);net9.0;net10.0
latest
enable
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 763e8b6c2..d2352dfa6 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -117,4 +117,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.csproj b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.csproj
index 07512d831..52ffde0ba 100644
--- a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.csproj
+++ b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.csproj
@@ -24,7 +24,7 @@
-
+
diff --git a/src/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.csproj b/src/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.csproj
index 4d6914c83..e4cccaf2e 100644
--- a/src/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.csproj
+++ b/src/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.csproj
@@ -20,7 +20,7 @@
-
+
From 303a76f7145656d12117ce9edf459fa4a07616c1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 6 Nov 2025 05:27:27 +0000
Subject: [PATCH 03/41] Change default TFM to .NET 10 and update GitHub Actions
to install .NET 10
Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
---
.github/workflows/codeql.yml | 1 +
.github/workflows/dotnet-main.yml | 2 +-
.github/workflows/dotnet-release.yml | 2 +-
.github/workflows/generate-api-diffs.yml | 3 ++-
.github/workflows/package.yml | 1 +
Directory.Build.props | 4 ++--
global.json | 2 +-
7 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index fee7c86ce..ab79da1cf 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -69,6 +69,7 @@ jobs:
dotnet-version: |
8.0.x
9.0.x
+ 10.0.x
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
diff --git a/.github/workflows/dotnet-main.yml b/.github/workflows/dotnet-main.yml
index 7339a0d28..8fc4c9dce 100644
--- a/.github/workflows/dotnet-main.yml
+++ b/.github/workflows/dotnet-main.yml
@@ -6,7 +6,7 @@ on:
workflow_dispatch:
env:
- DEFAULT_DOTNET_VERSION: "8.0.x"
+ DEFAULT_DOTNET_VERSION: "10.0.x"
permissions:
contents: read
diff --git a/.github/workflows/dotnet-release.yml b/.github/workflows/dotnet-release.yml
index 2f149c0d8..1f2ec0c5c 100644
--- a/.github/workflows/dotnet-release.yml
+++ b/.github/workflows/dotnet-release.yml
@@ -6,7 +6,7 @@ on:
- "v*"
env:
- DEFAULT_DOTNET_VERSION: "8.0.x"
+ DEFAULT_DOTNET_VERSION: "10.0.x"
jobs:
build:
diff --git a/.github/workflows/generate-api-diffs.yml b/.github/workflows/generate-api-diffs.yml
index 8a165d0aa..47d18e868 100644
--- a/.github/workflows/generate-api-diffs.yml
+++ b/.github/workflows/generate-api-diffs.yml
@@ -21,12 +21,13 @@ jobs:
dotnet-version: |
8.0.x
9.0.x
+ 10.0.x
- name: Restore and build
run: |
find src -type f -name "*.csproj" | while read -r csproj; do
- dotnet build "$csproj" -f net8.0 --configuration Release --no-incremental -t:Build -t:GenAPIGenerateReferenceAssemblySource
+ dotnet build "$csproj" -f net10.0 --configuration Release --no-incremental -t:Build -t:GenAPIGenerateReferenceAssemblySource
done
continue-on-error: true
diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml
index 44ab545f8..3bdf02475 100644
--- a/.github/workflows/package.yml
+++ b/.github/workflows/package.yml
@@ -24,6 +24,7 @@ jobs:
dotnet-version: |
8.0.x
9.0.x
+ 10.0.x
- name: Get git tag
id: git_tag
diff --git a/Directory.Build.props b/Directory.Build.props
index 57f2c17f9..6844bf2a9 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -3,9 +3,9 @@
- net8.0
+ net10.0
$(DefaultTargetFramework)
- $(DefaultTargetFramework);net9.0;net10.0
+ $(DefaultTargetFramework);net8.0;net9.0
latest
enable
diff --git a/global.json b/global.json
index a8ab760dd..20dc84cd1 100644
--- a/global.json
+++ b/global.json
@@ -1,5 +1,5 @@
{
"sdk": {
- "allowPrerelease": false
+ "allowPrerelease": true
}
}
\ No newline at end of file
From c6b19fca7818f9a66b6fc3548093650e864e981f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 6 Nov 2025 05:42:38 +0000
Subject: [PATCH 04/41] Update devcontainer to install .NET 10 as preview
Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
---
.devcontainer/devcontainer.json | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index cc803f382..388762fb9 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -4,8 +4,9 @@
"features": {
"ghcr.io/azure/azure-dev/azd:latest": {},
"ghcr.io/devcontainers/features/dotnet:latest": {
- "version": "8.0",
- "additionalVersions": "9.0"
+ "version": "10.0",
+ "additionalVersions": "8.0,9.0",
+ "installUsingApt": false
},
"ghcr.io/devcontainers/features/github-cli:latest": {},
"ghcr.io/devcontainers/features/java:1": {
From 1e4e20dcdaf9d68c95863303aabd5b21edc89095 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 6 Nov 2025 05:56:31 +0000
Subject: [PATCH 05/41] Add .NET 10 to setup-runtimes-caching action
Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
---
.github/actions/setup-runtimes-caching/action.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/actions/setup-runtimes-caching/action.yml b/.github/actions/setup-runtimes-caching/action.yml
index a92919c74..31fe1a33b 100644
--- a/.github/actions/setup-runtimes-caching/action.yml
+++ b/.github/actions/setup-runtimes-caching/action.yml
@@ -22,6 +22,7 @@ runs:
dotnet-version: |
8.0.x
9.0.x
+ 10.0.x
- name: Set up Python
uses: actions/setup-python@v5
From ac50650b3271e0a07e526b104d4301b75daf37f6 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Thu, 6 Nov 2025 22:55:05 +0000
Subject: [PATCH 06/41] Fixing some versioning
---
Directory.Build.props | 2 +-
Directory.Packages.props | 12 +++---------
2 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 6844bf2a9..42e996108 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -16,7 +16,7 @@
$(AspireVersion)
preview.1.25522.3
9.0.0
- 9.0.10
+ 10.0.0-rc.2.25502.107
1.12.0
4.7.0
9.9.0
diff --git a/Directory.Packages.props b/Directory.Packages.props
index d2352dfa6..ce41a4a4a 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -44,11 +44,12 @@
-
+
+
@@ -73,6 +74,7 @@
+
@@ -113,12 +115,4 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
From 94417949dc1a8d84a1083b196175fd1a0d84c2e1 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Thu, 6 Nov 2025 22:55:56 +0000
Subject: [PATCH 07/41] Hard coding an update to use Apache.NMS.AMQP@2.4.0 as
2.2.0 has a CVE but the MassTransit.ActiveMQ package isn't updated yet
Tracked: https://github.com/MassTransit/MassTransit/issues/6133
---
...ommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit.csproj | 1 +
.../CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests.csproj | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/examples/activemq/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit.csproj b/examples/activemq/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit.csproj
index 815a154dc..a611be36d 100644
--- a/examples/activemq/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit.csproj
+++ b/examples/activemq/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit.csproj
@@ -9,6 +9,7 @@
+
diff --git a/tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests.csproj b/tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests.csproj
index e7c0115f7..a76ecb91d 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests.csproj
+++ b/tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests.csproj
@@ -12,4 +12,8 @@
+
+
+
+
From ef89379b33b8519480fcb6293f83dfc6c7b8f6e7 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Thu, 6 Nov 2025 23:54:58 +0000
Subject: [PATCH 08/41] Fixing some projects that specified their own TFM and
trying to address ambiguous referencing
---
Directory.Packages.props | 7 +++++++
...Toolkit.Aspire.MassTransit.RabbitMQ.MessageTypes.csproj | 3 ---
...ityToolkit.Aspire.MassTransit.RabbitMQ.Publisher.csproj | 3 ---
.../CommunityToolkit.Aspire.PowerShell.AppHost.csproj | 3 ---
.../CommunityToolkit.Aspire.Hosting.KurrentDB.csproj | 7 +++++++
tests-app-hosts/Ollama.AppHost/Ollama.AppHost.csproj | 2 +-
6 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index ce41a4a4a..7f6ab35c8 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -115,4 +115,11 @@
+
+
+
+ all
+
+
+
\ No newline at end of file
diff --git a/examples/masstransit-rabbitmq/CommunityToolkit.Aspire.MassTransit.RabbitMQ.MessageTypes/CommunityToolkit.Aspire.MassTransit.RabbitMQ.MessageTypes.csproj b/examples/masstransit-rabbitmq/CommunityToolkit.Aspire.MassTransit.RabbitMQ.MessageTypes/CommunityToolkit.Aspire.MassTransit.RabbitMQ.MessageTypes.csproj
index abae6f43d..78b3f4709 100644
--- a/examples/masstransit-rabbitmq/CommunityToolkit.Aspire.MassTransit.RabbitMQ.MessageTypes/CommunityToolkit.Aspire.MassTransit.RabbitMQ.MessageTypes.csproj
+++ b/examples/masstransit-rabbitmq/CommunityToolkit.Aspire.MassTransit.RabbitMQ.MessageTypes/CommunityToolkit.Aspire.MassTransit.RabbitMQ.MessageTypes.csproj
@@ -1,9 +1,6 @@
- net8.0
- enable
- enable
Messaging
diff --git a/examples/masstransit-rabbitmq/CommunityToolkit.Aspire.MassTransit.RabbitMQ.Publisher/CommunityToolkit.Aspire.MassTransit.RabbitMQ.Publisher.csproj b/examples/masstransit-rabbitmq/CommunityToolkit.Aspire.MassTransit.RabbitMQ.Publisher/CommunityToolkit.Aspire.MassTransit.RabbitMQ.Publisher.csproj
index 047ceb190..1eaa00f58 100644
--- a/examples/masstransit-rabbitmq/CommunityToolkit.Aspire.MassTransit.RabbitMQ.Publisher/CommunityToolkit.Aspire.MassTransit.RabbitMQ.Publisher.csproj
+++ b/examples/masstransit-rabbitmq/CommunityToolkit.Aspire.MassTransit.RabbitMQ.Publisher/CommunityToolkit.Aspire.MassTransit.RabbitMQ.Publisher.csproj
@@ -2,9 +2,6 @@
Exe
- net8.0
- enable
- enable
diff --git a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/CommunityToolkit.Aspire.PowerShell.AppHost.csproj b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/CommunityToolkit.Aspire.PowerShell.AppHost.csproj
index 63aed919d..780f57a93 100644
--- a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/CommunityToolkit.Aspire.PowerShell.AppHost.csproj
+++ b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/CommunityToolkit.Aspire.PowerShell.AppHost.csproj
@@ -4,9 +4,6 @@
Exe
- net8.0
- enable
- enable
true
bc193f31-c9f7-4e3d-b70a-0dc39ec3047f
diff --git a/src/CommunityToolkit.Aspire.Hosting.KurrentDB/CommunityToolkit.Aspire.Hosting.KurrentDB.csproj b/src/CommunityToolkit.Aspire.Hosting.KurrentDB/CommunityToolkit.Aspire.Hosting.KurrentDB.csproj
index 4480a050d..24cd4a68b 100644
--- a/src/CommunityToolkit.Aspire.Hosting.KurrentDB/CommunityToolkit.Aspire.Hosting.KurrentDB.csproj
+++ b/src/CommunityToolkit.Aspire.Hosting.KurrentDB/CommunityToolkit.Aspire.Hosting.KurrentDB.csproj
@@ -14,4 +14,11 @@
+
+
+ all
+
+
+
+
diff --git a/tests-app-hosts/Ollama.AppHost/Ollama.AppHost.csproj b/tests-app-hosts/Ollama.AppHost/Ollama.AppHost.csproj
index a690e00c6..ca4a2b973 100644
--- a/tests-app-hosts/Ollama.AppHost/Ollama.AppHost.csproj
+++ b/tests-app-hosts/Ollama.AppHost/Ollama.AppHost.csproj
@@ -3,7 +3,7 @@
Exe
- net8.0
+ net10.0
enable
enable
true
From e66de71765399293f314db145b116f57e3d5f78f Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Fri, 7 Nov 2025 03:11:01 +0000
Subject: [PATCH 09/41] Using an improved approach approach to adding
system.linq.asyncenumerable
---
Directory.Packages.props | 6 ++----
.../CommunityToolkit.Aspire.Hosting.KurrentDB.csproj | 4 ++--
.../CommunityToolkit.Aspire.KurrentDB.csproj | 6 ++++++
.../CommunityToolkit.Aspire.KurrentDB.Tests.csproj | 7 +++++++
4 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 7f6ab35c8..92765cc7c 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -116,10 +116,8 @@
-
-
- all
-
+
+
\ No newline at end of file
diff --git a/src/CommunityToolkit.Aspire.Hosting.KurrentDB/CommunityToolkit.Aspire.Hosting.KurrentDB.csproj b/src/CommunityToolkit.Aspire.Hosting.KurrentDB/CommunityToolkit.Aspire.Hosting.KurrentDB.csproj
index 24cd4a68b..2d0d68eb5 100644
--- a/src/CommunityToolkit.Aspire.Hosting.KurrentDB/CommunityToolkit.Aspire.Hosting.KurrentDB.csproj
+++ b/src/CommunityToolkit.Aspire.Hosting.KurrentDB/CommunityToolkit.Aspire.Hosting.KurrentDB.csproj
@@ -14,11 +14,11 @@
-
+
all
-
+
diff --git a/src/CommunityToolkit.Aspire.KurrentDB/CommunityToolkit.Aspire.KurrentDB.csproj b/src/CommunityToolkit.Aspire.KurrentDB/CommunityToolkit.Aspire.KurrentDB.csproj
index 886e876f5..c9164e06f 100644
--- a/src/CommunityToolkit.Aspire.KurrentDB/CommunityToolkit.Aspire.KurrentDB.csproj
+++ b/src/CommunityToolkit.Aspire.KurrentDB/CommunityToolkit.Aspire.KurrentDB.csproj
@@ -16,4 +16,10 @@
+
+
+ all
+
+
+
diff --git a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/CommunityToolkit.Aspire.KurrentDB.Tests.csproj b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/CommunityToolkit.Aspire.KurrentDB.Tests.csproj
index fabc6da45..72ed754f7 100644
--- a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/CommunityToolkit.Aspire.KurrentDB.Tests.csproj
+++ b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/CommunityToolkit.Aspire.KurrentDB.Tests.csproj
@@ -9,4 +9,11 @@
+
+
+
+ all
+
+
+
From 51e57ba867ab691d3fda3f2997624bfc93264a16 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 10 Nov 2025 00:49:38 +0000
Subject: [PATCH 10/41] Updating how dev certs are setup
---
.devcontainer/post-create.sh | 3 +--
.github/actions/setup-runtimes-caching/action.yml | 4 ++--
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh
index 6096ba239..dcd64df77 100755
--- a/.devcontainer/post-create.sh
+++ b/.devcontainer/post-create.sh
@@ -5,8 +5,7 @@ sudo apt-get update && \
sudo rm -rf /var/lib/apt/lists/*
echo Install .NET dev certs
-dotnet tool update -g linux-dev-certs
-dotnet linux-dev-certs install
+dotnet dev-certs https --trust
echo Install JS monorepo tools
npm install -g turbo
diff --git a/.github/actions/setup-runtimes-caching/action.yml b/.github/actions/setup-runtimes-caching/action.yml
index 31fe1a33b..a4d38f6ef 100644
--- a/.github/actions/setup-runtimes-caching/action.yml
+++ b/.github/actions/setup-runtimes-caching/action.yml
@@ -85,8 +85,7 @@ runs:
shell: bash
if: ${{ matrix.os == 'ubuntu-latest' }}
run: |
- dotnet tool update -g linux-dev-certs
- dotnet linux-dev-certs install
+ dotnet dev-certs https --trust
- name: Setup Node globals
shell: bash
@@ -118,3 +117,4 @@ runs:
run: |
dapr init --runtime-version=${{ env.DAPR_VERSION }}
dapr --version
+
From f3ff1ffb9e3ecb81c670ce8ec5d8a06b951f346f Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 10 Nov 2025 01:01:39 +0000
Subject: [PATCH 11/41] Turns out you can't upgrade around the CVE, so we now
suppress it
I feel dirty doing that...
---
Directory.Build.props | 4 ++++
Directory.Packages.props | 1 -
...ommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit.csproj | 1 -
.../CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests.csproj | 4 ----
4 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 42e996108..7d9be405f 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -46,4 +46,8 @@
$(AspireMajorVersion).$(ToolkitMinorVersion).$(ToolkitPatchVersion)
+
+
+
+
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 92765cc7c..30934a6be 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -74,7 +74,6 @@
-
diff --git a/examples/activemq/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit.csproj b/examples/activemq/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit.csproj
index a611be36d..815a154dc 100644
--- a/examples/activemq/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit.csproj
+++ b/examples/activemq/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit/CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit.csproj
@@ -9,7 +9,6 @@
-
diff --git a/tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests.csproj b/tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests.csproj
index a76ecb91d..e7c0115f7 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests.csproj
+++ b/tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests/CommunityToolkit.Aspire.Hosting.ActiveMQ.Tests.csproj
@@ -12,8 +12,4 @@
-
-
-
-
From df16921e24064ecbd5b1d0270997b4f69581b86e Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 10 Nov 2025 05:11:50 +0000
Subject: [PATCH 12/41] Update to xunit v3
---
Directory.Packages.props | 11 +--
nuget.config | 2 +-
...AspireGoFeatureFlagClientExtensionsTest.cs | 1 +
.../ConformanceTests.cs | 1 +
.../GoFeatureFlagContainerFixture.cs | 5 +-
.../AddAdminerTests.cs | 1 +
.../AddDbGateTests.cs | 1 +
.../GoFeatureFlagFunctionalTests.cs | 3 +-
.../KeycloakWithPostgresIntegrationTest.cs | 1 +
.../KurrentDBFunctionalTests.cs | 2 +-
.../AppHostTests.cs | 2 +-
.../MeilisearchFunctionalTests.cs | 1 -
.../MinioFunctionalTests.cs | 2 +-
.../ResourceCreationTests.cs | 2 +-
.../FunctionalTests.cs | 5 +-
.../SqlServerContainerFixture.cs | 4 +-
.../SurrealDbFunctionalTests.cs | 1 -
.../AspireKurrentDBClientExtensionsTest.cs | 1 +
.../ConformanceTests.cs | 1 +
.../KurrentDBContainerFixture.cs | 5 +-
.../AspireMeilisearchClientExtensionsTest.cs | 1 +
.../ConformanceTests.cs | 1 +
.../MeilisearchContainerFixture.cs | 5 +-
.../ConformanceTests.cs | 1 +
.../MinioContainerFeature.cs | 5 +-
.../ConformanceTests.cs | 1 +
.../OllamaContainerFeature.cs | 5 +-
.../RavenDbServerFixture.cs | 6 +-
.../AspireSurrealClientExtensionsTest.cs | 1 +
.../ConformanceTests.cs | 9 +-
.../SurrealDbContainerFixture.cs | 5 +-
.../AspireIntegrationTest.cs | 4 +-
.../CommunityToolkit.Aspire.Testing.csproj | 12 +--
.../ConformanceTests.cs | 86 ++++++++++++-------
...utedApplicationTestingBuilderExtensions.cs | 1 -
.../PlatformDetection.cs | 13 ++-
.../RequiresDockerAttribute.cs | 24 ++++--
.../RequiresDockerDiscoverer.cs | 20 -----
.../RequiresLinuxAttribute.cs | 14 ++-
.../RequiresLinuxDiscoverer.cs | 20 -----
.../RequiresWindowsAttribute.cs | 20 ++++-
.../RequiresWindowsDiscoverer.cs | 15 ----
.../TestDistributedApplicationBuilder.cs | 1 -
tests/Directory.Build.props | 9 +-
44 files changed, 178 insertions(+), 153 deletions(-)
delete mode 100644 tests/CommunityToolkit.Aspire.Testing/RequiresDockerDiscoverer.cs
delete mode 100644 tests/CommunityToolkit.Aspire.Testing/RequiresLinuxDiscoverer.cs
delete mode 100644 tests/CommunityToolkit.Aspire.Testing/RequiresWindowsDiscoverer.cs
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 30934a6be..6ca1758e4 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -100,12 +100,13 @@
-
+
-
-
-
-
+
+
+
+
+
diff --git a/nuget.config b/nuget.config
index 16a6b5139..8d6946030 100644
--- a/nuget.config
+++ b/nuget.config
@@ -14,7 +14,7 @@
-
+
diff --git a/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/AspireGoFeatureFlagClientExtensionsTest.cs b/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/AspireGoFeatureFlagClientExtensionsTest.cs
index 4d07a5cf9..a7e134ba2 100644
--- a/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/AspireGoFeatureFlagClientExtensionsTest.cs
+++ b/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/AspireGoFeatureFlagClientExtensionsTest.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Components.Common.Tests;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
diff --git a/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/ConformanceTests.cs
index e5942de1a..65c5ae4ff 100644
--- a/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/ConformanceTests.cs
@@ -3,6 +3,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using OpenFeature.Contrib.Providers.GOFeatureFlag;
diff --git a/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/GoFeatureFlagContainerFixture.cs b/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/GoFeatureFlagContainerFixture.cs
index 591ece83c..5c5db3936 100644
--- a/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/GoFeatureFlagContainerFixture.cs
+++ b/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/GoFeatureFlagContainerFixture.cs
@@ -6,6 +6,7 @@
using Aspire.Hosting;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Containers;
+using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.GoFeatureFlag.Tests;
@@ -22,7 +23,7 @@ public string GetConnectionString()
return $"Endpoint={endpoint}";
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
if (RequiresDockerAttribute.IsSupported)
{
@@ -38,7 +39,7 @@ public async Task InitializeAsync()
}
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
{
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Adminer.Tests/AddAdminerTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Adminer.Tests/AddAdminerTests.cs
index 963891292..6be67fb81 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Adminer.Tests/AddAdminerTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Adminer.Tests/AddAdminerTests.cs
@@ -3,6 +3,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Hosting.Adminer.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AddDbGateTests.cs b/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AddDbGateTests.cs
index ec0cbd1a1..2b03401ec 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AddDbGateTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AddDbGateTests.cs
@@ -3,6 +3,7 @@
using Aspire.Hosting;
using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Hosting.DbGate.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests/GoFeatureFlagFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests/GoFeatureFlagFunctionalTests.cs
index 0eb202a15..e6a044049 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests/GoFeatureFlagFunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests/GoFeatureFlagFunctionalTests.cs
@@ -1,14 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
-using Xunit.Abstractions;
using Aspire.Hosting.Utils;
using OpenFeature.Contrib.Providers.GOFeatureFlag;
using OpenFeature.Model;
+using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Keycloak.Extensions.Tests/KeycloakWithPostgresIntegrationTest.cs b/tests/CommunityToolkit.Aspire.Hosting.Keycloak.Extensions.Tests/KeycloakWithPostgresIntegrationTest.cs
index a295d9f91..f39c25bd7 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Keycloak.Extensions.Tests/KeycloakWithPostgresIntegrationTest.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Keycloak.Extensions.Tests/KeycloakWithPostgresIntegrationTest.cs
@@ -1,6 +1,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Hosting.Keycloak.Extensions.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.KurrentDB.Tests/KurrentDBFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.KurrentDB.Tests/KurrentDBFunctionalTests.cs
index 3b1b431f8..b4653823e 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.KurrentDB.Tests/KurrentDBFunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.KurrentDB.Tests/KurrentDBFunctionalTests.cs
@@ -1,12 +1,12 @@
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
using KurrentDB.Client;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using System.Text;
using System.Text.Json;
-using Xunit.Abstractions;
namespace CommunityToolkit.Aspire.Hosting.KurrentDB.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/AppHostTests.cs
index 3fdb35c32..3b9a88cb2 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/AppHostTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/AppHostTests.cs
@@ -3,7 +3,7 @@
namespace CommunityToolkit.Aspire.Hosting.McpInspector.Tests;
// Forcing linux only due to: https://github.com/modelcontextprotocol/inspector/issues/893
-[RequiresLinux]
+[RequiresWindows]
public class AppHostTests(AspireIntegrationTestFixture fixture) : IClassFixture>
{
[Fact]
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Meilisearch.Tests/MeilisearchFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Meilisearch.Tests/MeilisearchFunctionalTests.cs
index 01d4e1d4a..e409ce007 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Meilisearch.Tests/MeilisearchFunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Meilisearch.Tests/MeilisearchFunctionalTests.cs
@@ -6,7 +6,6 @@
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using Polly;
-using Xunit.Abstractions;
using Meilisearch;
using Aspire.Hosting.Utils;
using CommunityToolkit.Aspire.Testing;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Minio.Tests/MinioFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Minio.Tests/MinioFunctionalTests.cs
index 1ccdc8641..3a164b54f 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Minio.Tests/MinioFunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Minio.Tests/MinioFunctionalTests.cs
@@ -1,10 +1,10 @@
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Hosting;
using Minio;
using Minio.DataModel.Args;
-using Xunit.Abstractions;
namespace CommunityToolkit.Aspire.Hosting.Minio.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector.Tests/ResourceCreationTests.cs b/tests/CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector.Tests/ResourceCreationTests.cs
index b259b6448..5ea684801 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector.Tests/ResourceCreationTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector.Tests/ResourceCreationTests.cs
@@ -1,7 +1,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
-using Xunit.Abstractions;
+using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/FunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/FunctionalTests.cs
index ca481bfe2..9409da302 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/FunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/FunctionalTests.cs
@@ -1,9 +1,8 @@
-using Aspire.Components.Common.Tests;
-using Aspire.Hosting;
+using Aspire.Hosting;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Diagnostics.HealthChecks;
-using Xunit.Abstractions;
namespace CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/SqlServerContainerFixture.cs b/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/SqlServerContainerFixture.cs
index aa7cce6da..9890da7d7 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/SqlServerContainerFixture.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/SqlServerContainerFixture.cs
@@ -15,9 +15,9 @@ public sealed class SqlServerContainerFixture : IAsyncLifetime
public string GetConnectionString() => Container?.GetConnectionString() ??
throw new InvalidOperationException("The test container was not initialized.");
- public async Task InitializeAsync() => Container = await CreateContainerAsync();
+ public async ValueTask InitializeAsync() => Container = await CreateContainerAsync();
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
await Container.DisposeAsync();
diff --git a/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbFunctionalTests.cs
index 2c3afd26b..4f92c4573 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbFunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbFunctionalTests.cs
@@ -13,7 +13,6 @@
using SurrealDb.Net;
using SurrealDb.Net.Exceptions;
using System.Data;
-using Xunit.Abstractions;
using SurrealRecord = SurrealDb.Net.Models.Record;
namespace CommunityToolkit.Aspire.Hosting.SurrealDb.Tests;
diff --git a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/AspireKurrentDBClientExtensionsTest.cs b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/AspireKurrentDBClientExtensionsTest.cs
index 56509b7d7..94ef94b04 100644
--- a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/AspireKurrentDBClientExtensionsTest.cs
+++ b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/AspireKurrentDBClientExtensionsTest.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Components.Common.Tests;
+using CommunityToolkit.Aspire.Testing;
using KurrentDB.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Diagnostics.HealthChecks;
diff --git a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/ConformanceTests.cs
index db9b5d412..144f2940b 100644
--- a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/ConformanceTests.cs
@@ -3,6 +3,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
+using CommunityToolkit.Aspire.Testing;
using KurrentDB.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
diff --git a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/KurrentDBContainerFixture.cs b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/KurrentDBContainerFixture.cs
index 9dfa41495..8bba0a4b5 100644
--- a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/KurrentDBContainerFixture.cs
+++ b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/KurrentDBContainerFixture.cs
@@ -3,6 +3,7 @@
using Aspire.Components.Common.Tests;
using CommunityToolkit.Aspire.Hosting.KurrentDB;
+using CommunityToolkit.Aspire.Testing;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Containers;
@@ -22,7 +23,7 @@ public string GetConnectionString()
return $"{endpoint}?tls=false";
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
if (RequiresDockerAttribute.IsSupported)
{
@@ -39,7 +40,7 @@ public async Task InitializeAsync()
}
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
{
diff --git a/tests/CommunityToolkit.Aspire.Meilisearch.Tests/AspireMeilisearchClientExtensionsTest.cs b/tests/CommunityToolkit.Aspire.Meilisearch.Tests/AspireMeilisearchClientExtensionsTest.cs
index 7048a0e42..add49d2e9 100644
--- a/tests/CommunityToolkit.Aspire.Meilisearch.Tests/AspireMeilisearchClientExtensionsTest.cs
+++ b/tests/CommunityToolkit.Aspire.Meilisearch.Tests/AspireMeilisearchClientExtensionsTest.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Components.Common.Tests;
+using CommunityToolkit.Aspire.Testing;
using Meilisearch;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
diff --git a/tests/CommunityToolkit.Aspire.Meilisearch.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.Meilisearch.Tests/ConformanceTests.cs
index 684d5e764..b25d5cc9b 100644
--- a/tests/CommunityToolkit.Aspire.Meilisearch.Tests/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.Meilisearch.Tests/ConformanceTests.cs
@@ -3,6 +3,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
+using CommunityToolkit.Aspire.Testing;
using Meilisearch;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
diff --git a/tests/CommunityToolkit.Aspire.Meilisearch.Tests/MeilisearchContainerFixture.cs b/tests/CommunityToolkit.Aspire.Meilisearch.Tests/MeilisearchContainerFixture.cs
index e263b9c52..4d7d13ef9 100644
--- a/tests/CommunityToolkit.Aspire.Meilisearch.Tests/MeilisearchContainerFixture.cs
+++ b/tests/CommunityToolkit.Aspire.Meilisearch.Tests/MeilisearchContainerFixture.cs
@@ -8,6 +8,7 @@
using DotNet.Testcontainers.Containers;
using Xunit;
using System.Linq.Expressions;
+using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Meilisearch.Tests;
@@ -25,7 +26,7 @@ public string GetConnectionString()
return $"Endpoint={endpoint};MasterKey={_masterKey}";
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
if (RequiresDockerAttribute.IsSupported)
{
@@ -55,7 +56,7 @@ public async Task InitializeAsync()
}
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
{
diff --git a/tests/CommunityToolkit.Aspire.Minio.Client.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.Minio.Client.Tests/ConformanceTests.cs
index 5012126fb..442732cf8 100644
--- a/tests/CommunityToolkit.Aspire.Minio.Client.Tests/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.Minio.Client.Tests/ConformanceTests.cs
@@ -1,5 +1,6 @@
using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Minio;
diff --git a/tests/CommunityToolkit.Aspire.Minio.Client.Tests/MinioContainerFeature.cs b/tests/CommunityToolkit.Aspire.Minio.Client.Tests/MinioContainerFeature.cs
index 3feee2c66..01c92b12a 100644
--- a/tests/CommunityToolkit.Aspire.Minio.Client.Tests/MinioContainerFeature.cs
+++ b/tests/CommunityToolkit.Aspire.Minio.Client.Tests/MinioContainerFeature.cs
@@ -1,5 +1,6 @@
using Aspire.Components.Common.Tests;
using CommunityToolkit.Aspire.Hosting.Minio;
+using CommunityToolkit.Aspire.Testing;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Containers;
@@ -19,7 +20,7 @@ public string GetContainerEndpoint()
return endpoint;
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
if (RequiresDockerAttribute.IsSupported)
{
@@ -39,7 +40,7 @@ public async Task InitializeAsync()
}
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
{
diff --git a/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/ConformanceTests.cs
index f6d784e0c..42229f208 100644
--- a/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/ConformanceTests.cs
@@ -1,5 +1,6 @@
using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
diff --git a/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/OllamaContainerFeature.cs b/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/OllamaContainerFeature.cs
index 2df093fad..93fe77692 100644
--- a/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/OllamaContainerFeature.cs
+++ b/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/OllamaContainerFeature.cs
@@ -1,5 +1,6 @@
using Aspire.Components.Common.Tests;
using CommunityToolkit.Aspire.Hosting.Ollama;
+using CommunityToolkit.Aspire.Testing;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Containers;
@@ -18,7 +19,7 @@ public string GetContainerEndpoint()
return endpoint;
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
if (RequiresDockerAttribute.IsSupported)
{
@@ -32,7 +33,7 @@ public async Task InitializeAsync()
}
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
{
diff --git a/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/RavenDbServerFixture.cs b/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/RavenDbServerFixture.cs
index 2df45c921..0e9dda06d 100644
--- a/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/RavenDbServerFixture.cs
+++ b/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/RavenDbServerFixture.cs
@@ -9,7 +9,7 @@ public sealed class RavenDbServerFixture : IAsyncLifetime, IDisposable
public IDocumentStore? Store { get; private set; }
public string? ConnectionString { get; private set; }
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
Server.StartServer();
@@ -28,10 +28,10 @@ public void CreateDatabase(DatabaseOptions options)
Store = Server.GetDocumentStore(options);
}
- public Task DisposeAsync()
+ public ValueTask DisposeAsync()
{
Dispose();
- return Task.CompletedTask;
+ return ValueTask.CompletedTask;
}
public void Dispose()
diff --git a/tests/CommunityToolkit.Aspire.SurrealDb.Tests/AspireSurrealClientExtensionsTest.cs b/tests/CommunityToolkit.Aspire.SurrealDb.Tests/AspireSurrealClientExtensionsTest.cs
index 20ab869b0..bbb8c6e2c 100644
--- a/tests/CommunityToolkit.Aspire.SurrealDb.Tests/AspireSurrealClientExtensionsTest.cs
+++ b/tests/CommunityToolkit.Aspire.SurrealDb.Tests/AspireSurrealClientExtensionsTest.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Components.Common.Tests;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
diff --git a/tests/CommunityToolkit.Aspire.SurrealDb.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.SurrealDb.Tests/ConformanceTests.cs
index c0d49f471..69ad1c2e7 100644
--- a/tests/CommunityToolkit.Aspire.SurrealDb.Tests/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.SurrealDb.Tests/ConformanceTests.cs
@@ -3,18 +3,19 @@
using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using SurrealDb.Net;
namespace CommunityToolkit.Aspire.SurrealDb.Tests;
-public class ConformanceTests :
- ConformanceTests,
+public class ConformanceTests :
+ ConformanceTests,
IClassFixture
{
private readonly SurrealDbContainerFixture _containerFixture;
-
+
protected override ServiceLifetime ServiceLifetime => ServiceLifetime.Singleton;
protected override string ActivitySourceName => string.Empty;
@@ -101,6 +102,6 @@ protected override void TriggerActivity(SurrealDbClient service)
{
using var source = new CancellationTokenSource(100);
- service.Version(source.Token).Wait();
+ Task.Run(() => service.Connect());
}
}
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.SurrealDb.Tests/SurrealDbContainerFixture.cs b/tests/CommunityToolkit.Aspire.SurrealDb.Tests/SurrealDbContainerFixture.cs
index 560d17e75..9be69e084 100644
--- a/tests/CommunityToolkit.Aspire.SurrealDb.Tests/SurrealDbContainerFixture.cs
+++ b/tests/CommunityToolkit.Aspire.SurrealDb.Tests/SurrealDbContainerFixture.cs
@@ -4,6 +4,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Containers;
@@ -28,7 +29,7 @@ public string GetConnectionString()
return $"Endpoint={endpoint};Username={_username};Password={_password}";
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
if (RequiresDockerAttribute.IsSupported)
{
@@ -60,7 +61,7 @@ public async Task InitializeAsync()
}
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
{
diff --git a/tests/CommunityToolkit.Aspire.Testing/AspireIntegrationTest.cs b/tests/CommunityToolkit.Aspire.Testing/AspireIntegrationTest.cs
index 823ab73c0..29f3ab61b 100644
--- a/tests/CommunityToolkit.Aspire.Testing/AspireIntegrationTest.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/AspireIntegrationTest.cs
@@ -71,7 +71,5 @@ public async override ValueTask DisposeAsync()
}
}
- public Task InitializeAsync() => StartAsync().WaitAsync(TimeSpan.FromMinutes(10));
-
- async Task IAsyncLifetime.DisposeAsync() => await DisposeAsync();
+ public async ValueTask InitializeAsync() => await StartAsync().WaitAsync(TimeSpan.FromMinutes(10));
}
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.Testing/CommunityToolkit.Aspire.Testing.csproj b/tests/CommunityToolkit.Aspire.Testing/CommunityToolkit.Aspire.Testing.csproj
index e19371f19..78e05e644 100644
--- a/tests/CommunityToolkit.Aspire.Testing/CommunityToolkit.Aspire.Testing.csproj
+++ b/tests/CommunityToolkit.Aspire.Testing/CommunityToolkit.Aspire.Testing.csproj
@@ -13,19 +13,13 @@
-
-
-
+
+
+
diff --git a/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
index ec0c5ca6b..3e27b2495 100644
--- a/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
@@ -3,9 +3,7 @@
using System.Diagnostics;
using System.Text.Json.Nodes;
-using Microsoft.DotNet.XUnitExtensions;
using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
@@ -13,6 +11,7 @@
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using Xunit;
+using Aspire.Components.Common.Tests;
namespace Aspire.Components.ConformanceTests;
@@ -45,6 +44,8 @@ public abstract class ConformanceTests
protected virtual bool SupportsKeyedRegistrations => false;
+ protected virtual bool IsComponentBuiltBeforeHost => false;
+
protected bool MetricsAreSupported => CheckIfImplemented(SetMetrics);
// every Component has to support health checks, this property is a temporary workaround
@@ -54,6 +55,8 @@ protected virtual void DisableRetries(TOptions options) { }
protected bool TracingIsSupported => CheckIfImplemented(SetTracing);
+ protected virtual bool CheckOptionClassSealed => true;
+
///
/// Calls the actual Component
///
@@ -85,20 +88,26 @@ protected virtual void DisableRetries(TOptions options) { }
///
protected abstract void SetMetrics(TOptions options, bool enabled);
- [ConditionalFact]
+ [Fact]
public void OptionsTypeIsSealed()
{
if (typeof(TOptions) == typeof(object))
{
- throw new SkipTestException("Not implemented yet");
+ Assert.Skip("Not implemented yet");
+ }
+
+ if (!CheckOptionClassSealed)
+ {
+ Assert.Skip("Opt-out of test");
}
Assert.True(typeof(TOptions).IsSealed);
}
- [ConditionalTheory]
+ [Theory]
[InlineData(true)]
[InlineData(false)]
+ [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public void HealthChecksRegistersHealthCheckService(bool enabled)
{
SkipIfHealthChecksAreNotSupported();
@@ -110,7 +119,7 @@ public void HealthChecksRegistersHealthCheckService(bool enabled)
Assert.Equal(enabled, healthCheckService is not null);
}
- [ConditionalFact]
+ [Fact]
public async Task EachKeyedComponentRegistersItsOwnHealthCheck()
{
SkipIfHealthChecksAreNotSupported();
@@ -124,18 +133,21 @@ public async Task EachKeyedComponentRegistersItsOwnHealthCheck()
List registeredNames = new();
await healthCheckService.CheckHealthAsync(healthCheckRegistration =>
+#pragma warning disable xUnit1030 // Do not call ConfigureAwait(false) in test method
{
registeredNames.Add(healthCheckRegistration.Name);
return false;
}).ConfigureAwait(false);
+#pragma warning restore xUnit1030 // Do not call ConfigureAwait(false) in test method
Assert.Equal(2, registeredNames.Count);
Assert.All(registeredNames, name => Assert.True(name.Contains(key1) || name.Contains(key2), $"{name} did not contain the key."));
}
- [ConditionalTheory]
+ [Theory]
[InlineData(true)]
[InlineData(false)]
+ [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public void TracingRegistersTraceProvider(bool enabled)
{
SkipIfTracingIsNotSupported();
@@ -148,9 +160,10 @@ public void TracingRegistersTraceProvider(bool enabled)
Assert.Equal(enabled, tracer is not null);
}
- [ConditionalTheory]
+ [Theory]
[InlineData(true)]
[InlineData(false)]
+ [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public void MetricsRegistersMeterProvider(bool enabled)
{
SkipIfMetricsAreNotSupported();
@@ -162,9 +175,10 @@ public void MetricsRegistersMeterProvider(bool enabled)
Assert.Equal(enabled, meter is not null);
}
- [ConditionalTheory]
+ [Theory]
[InlineData(true)]
[InlineData(false)]
+ [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public void ServiceLifetimeIsAsExpected(bool useKey)
{
SkipIfRequiredServerConnectionCanNotBeEstablished();
@@ -213,7 +227,7 @@ public void ServiceLifetimeIsAsExpected(bool useKey)
: serviceProvider.GetKeyedService(key);
}
- [ConditionalFact]
+ [Fact]
public void CanRegisterMultipleInstancesUsingDifferentKeys()
{
SkipIfKeyedRegistrationIsNotSupported();
@@ -229,7 +243,7 @@ public void CanRegisterMultipleInstancesUsingDifferentKeys()
Assert.NotSame(serviceForKey1, serviceForKey2);
}
- [ConditionalFact]
+ [Fact]
public void WhenKeyedRegistrationIsUsedThenItsImpossibleToResolveWithoutKey()
{
SkipIfKeyedRegistrationIsNotSupported();
@@ -249,11 +263,12 @@ public void WhenKeyedRegistrationIsUsedThenItsImpossibleToResolveWithoutKey()
Assert.Throws(host.Services.GetRequiredService);
}
- [ConditionalTheory]
+ [Theory]
[InlineData(true, true)]
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
+ [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public void LoggerFactoryIsUsedByRegisteredClient(bool registerAfterLoggerFactory, bool useKey)
{
SkipIfRequiredServerConnectionCanNotBeEstablished();
@@ -298,28 +313,29 @@ public void LoggerFactoryIsUsedByRegisteredClient(bool registerAfterLoggerFactor
}
}
- [ConditionalTheory]
+ [Theory]
[InlineData(null)]
[InlineData("key")]
- public async Task HealthCheckReportsExpectedStatus(string? key)
+ [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
+ public virtual async Task HealthCheckReportsExpectedStatus(string? key)
{
SkipIfHealthChecksAreNotSupported();
// DisableRetries so the test doesn't take so long retrying when the server isn't available.
using IHost host = CreateHostWithComponent(configureComponent: DisableRetries, key: key);
- HealthCheckService healthCheckService = host.Services.GetRequiredService();
+ var healthCheckService = host.Services.GetRequiredService();
- HealthReport healthReport = await healthCheckService.CheckHealthAsync().ConfigureAwait(false);
+ var healthReport = await healthCheckService.CheckHealthAsync();
- HealthStatus expected = CanConnectToServer ? HealthStatus.Healthy : HealthStatus.Unhealthy;
+ var expected = CanConnectToServer ? HealthStatus.Healthy : HealthStatus.Unhealthy;
Assert.Equal(expected, healthReport.Status);
Assert.NotEmpty(healthReport.Entries);
Assert.Contains(healthReport.Entries, entry => entry.Value.Status == expected);
}
- [Fact(Skip = "https://github.com/CommunityToolkit/Aspire/issues/112")]
+ [Fact]
public void ConfigurationSchemaValidJsonConfigTest()
{
var schema = JsonSchema.FromFile(JsonSchemaPath);
@@ -330,7 +346,7 @@ public void ConfigurationSchemaValidJsonConfigTest()
Assert.True(results.IsValid);
}
- [Fact(Skip = "https://github.com/CommunityToolkit/Aspire/issues/112")]
+ [Fact]
public void ConfigurationSchemaInvalidJsonConfigTest()
{
var schema = JsonSchema.FromFile(JsonSchemaPath);
@@ -350,13 +366,15 @@ public void ConfigurationSchemaInvalidJsonConfigTest()
/// Ensures that when the connection information is missing, an exception isn't thrown before the host
/// is built, so any exception can be logged with ILogger.
///
- [ConditionalTheory]
+ [Theory]
[InlineData(true)]
[InlineData(false)]
+ [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public void ConnectionInformationIsDelayValidated(bool useKey)
{
+ SkipIfComponentIsBuiltBeforeHost();
+
SetupConnectionInformationIsDelayValidated();
- SkipIfKeyedRegistrationIsNotSupported(useKey);
var builder = Host.CreateEmptyApplicationBuilder(null);
@@ -371,7 +389,7 @@ key is null
: host.Services.GetRequiredKeyedService(key));
}
- [ConditionalFact]
+ [Fact]
public void FavorsNamedConfigurationOverTopLevelConfigurationWhenBothProvided_DisableTracing()
{
SkipIfNamedConfigNotSupported();
@@ -393,7 +411,7 @@ public void FavorsNamedConfigurationOverTopLevelConfigurationWhenBothProvided_Di
Assert.Null(host.Services.GetService());
}
- [ConditionalFact]
+ [Fact]
public void FavorsNamedConfigurationOverTopLevelConfigurationWhenBothProvided_DisableHealthChecks()
{
SkipIfNamedConfigNotSupported();
@@ -481,7 +499,7 @@ protected void SkipIfHealthChecksAreNotSupported()
{
if (!HealthChecksAreSupported)
{
- throw new SkipTestException("Health checks aren't supported.");
+ Assert.Skip("Health checks aren't supported.");
}
}
@@ -489,7 +507,7 @@ protected void SkipIfKeyedRegistrationIsNotSupported(bool useKey = true)
{
if (useKey && !SupportsKeyedRegistrations)
{
- throw new SkipTestException("Does not support Keyed Services");
+ Assert.Skip("Does not support Keyed Services");
}
}
@@ -497,7 +515,7 @@ protected void SkipIfTracingIsNotSupported()
{
if (!TracingIsSupported)
{
- throw new SkipTestException("Tracing is not supported.");
+ Assert.Skip("Tracing is not supported.");
}
}
@@ -505,7 +523,7 @@ protected void SkipIfMetricsAreNotSupported()
{
if (!MetricsAreSupported)
{
- throw new SkipTestException("Metrics are not supported.");
+ Assert.Skip("Metrics are not supported.");
}
}
@@ -513,7 +531,7 @@ protected void SkipIfRequiredServerConnectionCanNotBeEstablished()
{
if (!CanCreateClientWithoutConnectingToServer && !CanConnectToServer)
{
- throw new SkipTestException("Unable to connect to the server.");
+ Assert.Skip("Unable to connect to the server.");
}
}
@@ -521,7 +539,7 @@ protected void SkipIfCanNotConnectToServer()
{
if (!CanConnectToServer)
{
- throw new SkipTestException("Unable to connect to the server.");
+ Assert.Skip("Unable to connect to the server.");
}
}
@@ -529,13 +547,21 @@ protected void SkipIfNamedConfigNotSupported()
{
if (!SupportsNamedConfig || ConfigurationSectionName is null)
{
- throw new SkipTestException("Named configuration is not supported.");
+ Assert.Skip("Named configuration is not supported.");
}
}
public static string CreateConfigKey(string prefix, string? key, string suffix)
=> string.IsNullOrEmpty(key) ? $"{prefix}:{suffix}" : $"{prefix}:{key}:{suffix}";
+ protected void SkipIfComponentIsBuiltBeforeHost()
+ {
+ if (IsComponentBuiltBeforeHost)
+ {
+ Assert.Skip("Component is built before host.");
+ }
+ }
+
protected HostApplicationBuilder CreateHostBuilder(HostApplicationBuilderSettings? hostSettings = null, string? key = null)
{
HostApplicationBuilder builder = Host.CreateEmptyApplicationBuilder(hostSettings);
diff --git a/tests/CommunityToolkit.Aspire.Testing/DistributedApplicationTestingBuilderExtensions.cs b/tests/CommunityToolkit.Aspire.Testing/DistributedApplicationTestingBuilderExtensions.cs
index 1b7d0bb5c..c7d12af9d 100644
--- a/tests/CommunityToolkit.Aspire.Testing/DistributedApplicationTestingBuilderExtensions.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/DistributedApplicationTestingBuilderExtensions.cs
@@ -5,7 +5,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Xunit;
-using Xunit.Abstractions;
namespace Aspire.Hosting.Utils;
diff --git a/tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs b/tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs
index 9f29acb39..05a371a4c 100644
--- a/tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs
@@ -2,5 +2,14 @@ namespace Aspire.Components.Common.Tests;
public static class PlatformDetection
{
- public static bool IsRunningOnCI => Environment.GetEnvironmentVariable("CI") is not null;
-}
\ No newline at end of file
+ public static bool IsRunningOnAzdoBuildMachine => Environment.GetEnvironmentVariable("BUILD_BUILDID") is not null;
+ public static bool IsRunningOnHelix => Environment.GetEnvironmentVariable("HELIX_WORKITEM_ROOT") is not null;
+ public static bool IsRunningOnGithubActions => Environment.GetEnvironmentVariable("GITHUB_JOB") is not null;
+ public static bool IsRunningOnCI => IsRunningOnAzdoBuildMachine || IsRunningOnHelix || IsRunningOnGithubActions;
+ public static bool IsRunningFromAzdo => IsRunningOnAzdoBuildMachine || IsRunningOnHelix;
+ public static bool IsRunningPRValidation => IsRunningOnGithubActions;
+
+ public static bool IsWindows => OperatingSystem.IsWindows();
+ public static bool IsLinux => OperatingSystem.IsLinux();
+ public static bool IsMacOS => OperatingSystem.IsMacOS();
+}
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs
index cbb20ed11..fbecc0bd1 100644
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs
@@ -1,13 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-// Copied from: https://github.com/dotnet/aspire/blob/d31331d6132aeb22940dcd8834344956ba811373/tests/Aspire.Components.Common.Tests/RequiresDockerAttribute.cs
+using Aspire.Components.Common.Tests;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit.v3;
-using Xunit.Sdk;
+namespace CommunityToolkit.Aspire.Testing;
-namespace Aspire.Components.Common.Tests;
-
-[TraitDiscoverer("Aspire.Components.Common.Tests.RequiresDockerDiscoverer", "CommunityToolkit.Aspire.Testing")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class RequiresDockerAttribute : Attribute, ITraitAttribute
{
@@ -23,12 +22,21 @@ public class RequiresDockerAttribute : Attribute, ITraitAttribute
// - https://github.com/dotnet/aspire/issues/4291
// - Linux - Local, or CI: always assume that docker is installed
public static bool IsSupported =>
- !OperatingSystem.IsWindows() ||
- !PlatformDetection.IsRunningOnCI;
+ OperatingSystem.IsLinux() || !PlatformDetection.IsRunningOnCI; // non-linux on CI does not support docker
public string? Reason { get; init; }
public RequiresDockerAttribute(string? reason = null)
{
Reason = reason;
}
-}
+
+ public IReadOnlyCollection> GetTraits()
+ {
+ if (!IsSupported)
+ {
+ return [new KeyValuePair(XunitConstants.Category, "failing")];
+ }
+
+ return [];
+ }
+}
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresDockerDiscoverer.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresDockerDiscoverer.cs
deleted file mode 100644
index 64ef21d97..000000000
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresDockerDiscoverer.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-// Copied from: https://github.com/dotnet/aspire/blob/d31331d6132aeb22940dcd8834344956ba811373/tests/Aspire.Components.Common.Tests/RequiresDockerDiscoverer.cs
-
-using Xunit.Abstractions;
-using Xunit.Sdk;
-
-namespace Aspire.Components.Common.Tests;
-
-public class RequiresDockerDiscoverer : ITraitDiscoverer
-{
- public IEnumerable> GetTraits(IAttributeInfo traitAttribute)
- {
- if (!RequiresDockerAttribute.IsSupported)
- {
- yield return new KeyValuePair("category", "unsupported-platform");
- }
- }
-}
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxAttribute.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxAttribute.cs
index a8c53fdc9..1fca3a5d6 100644
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxAttribute.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxAttribute.cs
@@ -1,4 +1,5 @@
-using Xunit.Sdk;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit.v3;
namespace CommunityToolkit.Aspire.Testing;
@@ -6,7 +7,6 @@ namespace CommunityToolkit.Aspire.Testing;
/// Marks a test or test class as requiring a Linux operating system.
/// Adds a trait so tests can be skipped or filtered when not running on Linux.
///
-[TraitDiscoverer("CommunityToolkit.Aspire.Testing.RequiresLinuxDiscoverer", "CommunityToolkit.Aspire.Testing")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class RequiresLinuxAttribute(string? reason = null) : Attribute, ITraitAttribute
{
@@ -15,4 +15,14 @@ public class RequiresLinuxAttribute(string? reason = null) : Attribute, ITraitAt
/// Gets a value indicating whether the current OS is Linux.
public static bool IsSupported => OperatingSystem.IsLinux();
+
+ public IReadOnlyCollection> GetTraits()
+ {
+ if (!IsSupported)
+ {
+ return [new KeyValuePair(XunitConstants.Category, "failing")];
+ }
+
+ return [];
+ }
}
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxDiscoverer.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxDiscoverer.cs
deleted file mode 100644
index a252d5776..000000000
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxDiscoverer.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Xunit.Abstractions;
-using Xunit.Sdk;
-
-namespace CommunityToolkit.Aspire.Testing;
-
-///
-/// Discovers traits for .
-/// Adds a category trait of unsupported-platform when not running on Linux.
-///
-public class RequiresLinuxDiscoverer : ITraitDiscoverer
-{
- ///
- public IEnumerable> GetTraits(IAttributeInfo traitAttribute)
- {
- if (!RequiresLinuxAttribute.IsSupported)
- {
- yield return new KeyValuePair("category", "unsupported-platform");
- }
- }
-}
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsAttribute.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsAttribute.cs
index 16414031c..860299cc9 100644
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsAttribute.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsAttribute.cs
@@ -1,12 +1,28 @@
-using Xunit.Sdk;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit.v3;
namespace CommunityToolkit.Aspire.Testing;
-[TraitDiscoverer("CommunityToolkit.Aspire.Testing.RequiresWindowsDiscoverer", "CommunityToolkit.Aspire.Testing")]
+///
+/// Marks a test or test class as requiring a Linux operating system.
+/// Adds a trait so tests can be skipped or filtered when not running on Linux.
+///
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class RequiresWindowsAttribute(string? reason = null) : Attribute, ITraitAttribute
{
+ /// Gets the optional reason why Windows is required.
public string? Reason { get; init; } = reason;
+ /// Gets a value indicating whether the current OS is Windows.
public static bool IsSupported => OperatingSystem.IsWindows();
+
+ public IReadOnlyCollection> GetTraits()
+ {
+ if (!IsSupported)
+ {
+ return [new KeyValuePair(XunitConstants.Category, "failing")];
+ }
+
+ return [];
+ }
}
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsDiscoverer.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsDiscoverer.cs
deleted file mode 100644
index ae20e801b..000000000
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsDiscoverer.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using Xunit.Abstractions;
-using Xunit.Sdk;
-
-namespace CommunityToolkit.Aspire.Testing;
-
-public class RequiresWindowsDiscoverer : ITraitDiscoverer
-{
- public IEnumerable> GetTraits(IAttributeInfo traitAttribute)
- {
- if (!RequiresWindowsAttribute.IsSupported)
- {
- yield return new KeyValuePair("category", "unsupported-platform");
- }
- }
-}
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.Testing/TestDistributedApplicationBuilder.cs b/tests/CommunityToolkit.Aspire.Testing/TestDistributedApplicationBuilder.cs
index aba9b5855..12b6fc6dd 100644
--- a/tests/CommunityToolkit.Aspire.Testing/TestDistributedApplicationBuilder.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/TestDistributedApplicationBuilder.cs
@@ -3,7 +3,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Components.Common.TestUtilities;
-using Xunit.Abstractions;
namespace Aspire.Hosting.Utils;
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index 69221f9d8..3d38a4360 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -3,14 +3,19 @@
$(DefaultTargetFramework)
+
+
+
+
+ $(NoWarn);xUnit1051
-
+
-
+
From 1ac2ad3c7ebc37c01868f10f9e9a946ed462afe9 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 10 Nov 2025 05:19:03 +0000
Subject: [PATCH 13/41] Disabling JSON schema tests as we don't generate those
files
---
tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
index 3e27b2495..971471b42 100644
--- a/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
@@ -335,7 +335,7 @@ public virtual async Task HealthCheckReportsExpectedStatus(string? key)
Assert.Contains(healthReport.Entries, entry => entry.Value.Status == expected);
}
- [Fact]
+ [Fact(Skip = "https://github.com/CommunityToolkit/Aspire/issues/112")]
public void ConfigurationSchemaValidJsonConfigTest()
{
var schema = JsonSchema.FromFile(JsonSchemaPath);
@@ -346,7 +346,7 @@ public void ConfigurationSchemaValidJsonConfigTest()
Assert.True(results.IsValid);
}
- [Fact]
+ [Fact(Skip = "https://github.com/CommunityToolkit/Aspire/issues/112")]
public void ConfigurationSchemaInvalidJsonConfigTest()
{
var schema = JsonSchema.FromFile(JsonSchemaPath);
From 5840c2e8e2f5def719c346f6fc20099661d8f62b Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 10 Nov 2025 05:29:59 +0000
Subject: [PATCH 14/41] Some adjustments to not be so aspire configured
---
tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs b/tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs
index 05a371a4c..b342739ec 100644
--- a/tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs
@@ -2,12 +2,8 @@ namespace Aspire.Components.Common.Tests;
public static class PlatformDetection
{
- public static bool IsRunningOnAzdoBuildMachine => Environment.GetEnvironmentVariable("BUILD_BUILDID") is not null;
- public static bool IsRunningOnHelix => Environment.GetEnvironmentVariable("HELIX_WORKITEM_ROOT") is not null;
public static bool IsRunningOnGithubActions => Environment.GetEnvironmentVariable("GITHUB_JOB") is not null;
- public static bool IsRunningOnCI => IsRunningOnAzdoBuildMachine || IsRunningOnHelix || IsRunningOnGithubActions;
- public static bool IsRunningFromAzdo => IsRunningOnAzdoBuildMachine || IsRunningOnHelix;
- public static bool IsRunningPRValidation => IsRunningOnGithubActions;
+ public static bool IsRunningOnCI => IsRunningOnGithubActions || Environment.GetEnvironmentVariable("CI") is not null;
public static bool IsWindows => OperatingSystem.IsWindows();
public static bool IsLinux => OperatingSystem.IsLinux();
From dcfbd732b99cc4a3bc906852320d704cf5602302 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 10 Nov 2025 05:33:08 +0000
Subject: [PATCH 15/41] Oh, some of that was used
---
tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs | 7 -------
1 file changed, 7 deletions(-)
diff --git a/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
index 971471b42..2b47c8042 100644
--- a/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
@@ -107,7 +107,6 @@ public void OptionsTypeIsSealed()
[Theory]
[InlineData(true)]
[InlineData(false)]
- [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public void HealthChecksRegistersHealthCheckService(bool enabled)
{
SkipIfHealthChecksAreNotSupported();
@@ -147,7 +146,6 @@ await healthCheckService.CheckHealthAsync(healthCheckRegistration =>
[Theory]
[InlineData(true)]
[InlineData(false)]
- [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public void TracingRegistersTraceProvider(bool enabled)
{
SkipIfTracingIsNotSupported();
@@ -163,7 +161,6 @@ public void TracingRegistersTraceProvider(bool enabled)
[Theory]
[InlineData(true)]
[InlineData(false)]
- [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public void MetricsRegistersMeterProvider(bool enabled)
{
SkipIfMetricsAreNotSupported();
@@ -178,7 +175,6 @@ public void MetricsRegistersMeterProvider(bool enabled)
[Theory]
[InlineData(true)]
[InlineData(false)]
- [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public void ServiceLifetimeIsAsExpected(bool useKey)
{
SkipIfRequiredServerConnectionCanNotBeEstablished();
@@ -268,7 +264,6 @@ public void WhenKeyedRegistrationIsUsedThenItsImpossibleToResolveWithoutKey()
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
- [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public void LoggerFactoryIsUsedByRegisteredClient(bool registerAfterLoggerFactory, bool useKey)
{
SkipIfRequiredServerConnectionCanNotBeEstablished();
@@ -316,7 +311,6 @@ public void LoggerFactoryIsUsedByRegisteredClient(bool registerAfterLoggerFactor
[Theory]
[InlineData(null)]
[InlineData("key")]
- [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public virtual async Task HealthCheckReportsExpectedStatus(string? key)
{
SkipIfHealthChecksAreNotSupported();
@@ -369,7 +363,6 @@ public void ConfigurationSchemaInvalidJsonConfigTest()
[Theory]
[InlineData(true)]
[InlineData(false)]
- [ActiveIssue("https://github.com/dotnet/aspire/issues/11820", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningFromAzdo))]
public void ConnectionInformationIsDelayValidated(bool useKey)
{
SkipIfComponentIsBuiltBeforeHost();
From 102aaabb0b889862f08ec79089ac111a6665865f Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 10 Nov 2025 05:54:09 +0000
Subject: [PATCH 16/41] Adding filter for failing tests to be skipped
---
.../RequiresDockerAttribute.cs | 2 +-
tests/Directory.Build.props | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs
index fbecc0bd1..2aa29dfaa 100644
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs
@@ -32,7 +32,7 @@ public RequiresDockerAttribute(string? reason = null)
public IReadOnlyCollection> GetTraits()
{
- if (!IsSupported)
+ if (IsSupported)
{
return [new KeyValuePair(XunitConstants.Category, "failing")];
}
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index 3d38a4360..b8d5f25d6 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -34,4 +34,11 @@
$(MSBuildThisFileDirectory).runsettings
+
+ $(TestRunnerAdditionalArguments) --filter-not-trait "category=failing"
+
+ $(TestRunnerAdditionalArguments) --ignore-exit-code 8
+
+
\ No newline at end of file
From 733964bf9384d0adf677d77147d174833798f0c2 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 10 Nov 2025 22:28:43 +0000
Subject: [PATCH 17/41] using dotnet to run tests rather than dotnet
test
---
.github/workflows/tests.yaml | 9 ++++++---
tests/.runsettings | 2 +-
.../RequiresDockerAttribute.cs | 2 +-
3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index e1f125e93..42ce57535 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -8,7 +8,7 @@ jobs:
env:
DOTNET_CONFIGURATION: Release
DAPR_VERSION: "1.15.0"
- TEST_PROJECT_PATH: tests/CommunityToolkit.Aspire.${{ matrix.name }}/CommunityToolkit.Aspire.${{ matrix.name }}.csproj
+ TEST_PROJECT_PATH: tests/CommunityToolkit.Aspire.${{ matrix.name }}/CommunityToolkit.Aspire.${{ matrix.name }}
CI: true
NPM_CONFIG_PACKAGE_LOCK: false
runs-on: "${{ matrix.os }}"
@@ -92,11 +92,11 @@ jobs:
env:
CI: false
run: |
- dotnet build ${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }} /bl --configuration ${{ env.DOTNET_CONFIGURATION }}
+ dotnet build ${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }} /bl --configuration ${{ env.DOTNET_CONFIGURATION }} -o ${{ github.workspace }}/artifacts/${{ matrix.name }}
- name: Run tests
run: >-
- dotnet test ${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }}
+ dotnet ${{ github.workspace }}/artifacts/${{ matrix.name }}/CommunityToolkit.Aspire.${{ matrix.name }}.dll
--configuration ${{ env.DOTNET_CONFIGURATION }}
--logger "console;verbosity=normal"
--logger "trx"
@@ -108,6 +108,9 @@ jobs:
--collect "XPlat Code Coverage"
--no-restore
--no-build -- RunConfiguration.CollectSourceInformation=true
+ --filter-not-trait "category=failing"
+ --report-trx --report-trx-filename "${{ matrix.name }}-${{ matrix.os }}.trx"
+ --ignore-exit-code 8
env:
CUSTOM_CONTAINER_REGISTRY: ${{ secrets.CUSTOM_CONTAINER_REGISTRY }}
diff --git a/tests/.runsettings b/tests/.runsettings
index 1ce761b64..edd22a9eb 100644
--- a/tests/.runsettings
+++ b/tests/.runsettings
@@ -2,6 +2,6 @@
- category!=unsupported-platform
+ category!=failing
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs
index 2aa29dfaa..fbecc0bd1 100644
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs
@@ -32,7 +32,7 @@ public RequiresDockerAttribute(string? reason = null)
public IReadOnlyCollection> GetTraits()
{
- if (IsSupported)
+ if (!IsSupported)
{
return [new KeyValuePair(XunitConstants.Category, "failing")];
}
From f10b449d1ae0f587f247a0add294b99ba780448d Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 10 Nov 2025 22:39:21 +0000
Subject: [PATCH 18/41] forgot I made that change
---
.github/workflows/tests.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 42ce57535..68c1d5dfa 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -8,7 +8,7 @@ jobs:
env:
DOTNET_CONFIGURATION: Release
DAPR_VERSION: "1.15.0"
- TEST_PROJECT_PATH: tests/CommunityToolkit.Aspire.${{ matrix.name }}/CommunityToolkit.Aspire.${{ matrix.name }}
+ TEST_PROJECT_PATH: tests/CommunityToolkit.Aspire.${{ matrix.name }}/CommunityToolkit.Aspire.${{ matrix.name }}.csproj
CI: true
NPM_CONFIG_PACKAGE_LOCK: false
runs-on: "${{ matrix.os }}"
From 425a39eabd4d7dab832e1cf52335945c6af8cd5d Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 10 Nov 2025 23:40:59 +0000
Subject: [PATCH 19/41] updating a few more deps
---
.github/workflows/tests.yaml | 11 +++--
.vscode/tasks.json | 65 ++++++++++++++++-----------
Directory.Packages.props | 9 ++--
eng/clean-bin-obj.sh | 85 ++++++++++++++++++++++++++++++++++++
tests/Directory.Build.props | 3 ++
5 files changed, 140 insertions(+), 33 deletions(-)
create mode 100755 eng/clean-bin-obj.sh
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 68c1d5dfa..0982a34b8 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -96,7 +96,7 @@ jobs:
- name: Run tests
run: >-
- dotnet ${{ github.workspace }}/artifacts/${{ matrix.name }}/CommunityToolkit.Aspire.${{ matrix.name }}.dll
+ dotnet run ${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }}
--configuration ${{ env.DOTNET_CONFIGURATION }}
--logger "console;verbosity=normal"
--logger "trx"
@@ -107,10 +107,15 @@ jobs:
--results-directory testresults
--collect "XPlat Code Coverage"
--no-restore
- --no-build -- RunConfiguration.CollectSourceInformation=true
+ --no-build
--filter-not-trait "category=failing"
- --report-trx --report-trx-filename "${{ matrix.name }}-${{ matrix.os }}.trx"
+ --report-trx
+ --report-trx-filename "${{ matrix.name }}-${{ matrix.os }}.trx"
--ignore-exit-code 8
+ -- RunConfiguration.CollectSourceInformation=true
+ --coverage
+ --coverage-output-format cobertura
+ --coverage-output coverage.cobertura.xml
env:
CUSTOM_CONTAINER_REGISTRY: ${{ secrets.CUSTOM_CONTAINER_REGISTRY }}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index c4fa0024b..4658de2bd 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -2,36 +2,49 @@
"version": "2.0.0",
"tasks": [
{
- "label": "build",
- "command": "dotnet",
- "type": "process",
- "args": [
- "build",
- "/property:GenerateFullPaths=true",
- "/consoleloggerparameters:NoSummary;ForceNoAlign"
- ],
- "problemMatcher": "$msCompile"
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
},
{
- "label": "publish",
- "command": "dotnet",
- "type": "process",
- "args": [
- "publish",
- "/property:GenerateFullPaths=true",
- "/consoleloggerparameters:NoSummary;ForceNoAlign"
- ],
- "problemMatcher": "$msCompile"
+ "label": "publish",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "publish",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
},
{
- "label": "watch",
- "command": "dotnet",
- "type": "process",
- "args": [
- "watch",
- "run"
- ],
- "problemMatcher": "$msCompile"
+ "label": "watch",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "watch",
+ "run"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "cleanup",
+ "type": "shell",
+ "command": "./eng/clean-bin-obj.sh",
+ "problemMatcher": [],
+ "linux": {
+ "options": {
+ "shell": {
+ "executable": "bash"
+ }
+ }
+ }
}
],
"inputs": [
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 6ca1758e4..c720c7e76 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -102,11 +102,12 @@
-
-
-
-
+
+
+
+
+
diff --git a/eng/clean-bin-obj.sh b/eng/clean-bin-obj.sh
new file mode 100755
index 000000000..f9b69649a
--- /dev/null
+++ b/eng/clean-bin-obj.sh
@@ -0,0 +1,85 @@
+#!/usr/bin/env bash
+# Recursively delete all `bin` and `obj` folders from the repository.
+# Usage: ./eng/clean-bin-obj.sh
+# Optional flags:
+# --dry-run Show what would be removed without deleting.
+# --quiet Suppress per-folder output; only show summary.
+# --help Display help.
+#
+# The script resolves the repo root based on its own location so it can be
+# invoked from any working directory.
+
+set -euo pipefail
+
+print_help() {
+ cat <<'EOF'
+Clean bin/obj folders
+
+Deletes ALL directories named `bin` or `obj` under the repository root.
+
+Flags:
+ --dry-run List directories that would be deleted.
+ --quiet Only print summary information.
+ --help Show this help text.
+
+Examples:
+ ./eng/clean-bin-obj.sh
+ ./eng/clean-bin-obj.sh --dry-run
+ ./eng/clean-bin-obj.sh --quiet
+EOF
+}
+
+DRY_RUN=0
+QUIET=0
+for arg in "$@"; do
+ case "$arg" in
+ --dry-run) DRY_RUN=1 ;;
+ --quiet) QUIET=1 ;;
+ --help|-h) print_help; exit 0 ;;
+ *) echo "Unknown argument: $arg" >&2; exit 1 ;;
+ esac
+done
+
+# Determine repo root (parent of this script's directory)
+SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
+REPO_ROOT=$(cd "${SCRIPT_DIR}/.." && pwd)
+
+cd "$REPO_ROOT"
+
+# Collect bin/obj directories excluding anything under .git to be safe.
+# Use -prune to avoid descending into matched directories after they are found.
+mapfile -t TARGETS < <(find . -type d \( -name bin -o -name obj \) -not -path '*/.git/*' -prune -print)
+
+COUNT=${#TARGETS[@]}
+if [[ $COUNT -eq 0 ]]; then
+ [[ $QUIET -eq 0 ]] && echo "No bin/obj directories found under $REPO_ROOT." || true
+ exit 0
+fi
+
+if [[ $DRY_RUN -eq 1 ]]; then
+ [[ $QUIET -eq 0 ]] && printf '%s\n' "Dry run: the following $COUNT directories would be deleted:" || true
+ printf '%s\n' "${TARGETS[@]}"
+ exit 0
+fi
+
+# Delete directories.
+DELETED=0
+for dir in "${TARGETS[@]}"; do
+ if [[ $QUIET -eq 0 ]]; then
+ echo "Removing: $dir"
+ fi
+ rm -rf "$dir" || {
+ echo "Failed to remove: $dir" >&2
+ continue
+ }
+ # Increment without triggering set -e early exit (arithmetic exit status is 1 when result is 0 for post-increment)
+ ((DELETED++)) || true
+done
+
+if [[ $QUIET -eq 0 ]]; then
+ echo "Removed $DELETED bin/obj directories under $REPO_ROOT."
+else
+ echo "Removed $DELETED directories." # Always show a minimal summary in quiet mode.
+fi
+
+exit 0
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index b8d5f25d6..73e0970b8 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -18,6 +18,7 @@
+
@@ -39,6 +40,8 @@
$(TestRunnerAdditionalArguments) --ignore-exit-code 8
+
+
\ No newline at end of file
From 270aa58e1add5b7a03825d9aec6f75d3bb2ec46b Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 24 Nov 2025 05:47:26 +0000
Subject: [PATCH 20/41] Updating based on comments and using the new
GitHubActionsTestLogger with MTP support
---
.github/workflows/tests.yaml | 17 ++++++-----------
Directory.Packages.props | 5 +++--
tests/.runsettings | 7 -------
...tyToolkit.Aspire.RavenDB.Client.Tests.csproj | 2 --
.../ConformanceTests.cs | 1 +
tests/Directory.Build.props | 7 ++++---
6 files changed, 14 insertions(+), 25 deletions(-)
delete mode 100644 tests/.runsettings
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 50879f02b..dbc1dddc3 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -98,24 +98,19 @@ jobs:
run: >-
dotnet run ${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }}
--configuration ${{ env.DOTNET_CONFIGURATION }}
- --logger "console;verbosity=normal"
- --logger "trx"
--logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true"
- --blame
- --blame-hang-timeout 7m
- --blame-crash
- --results-directory testresults
- --collect "XPlat Code Coverage"
+ --crashdump
+ --hangdump
+ --hangdump-timeout 7m
+ --results-directory "${{ github.workspace }}/testresults"
+ --collect
--no-restore
--no-build
--filter-not-trait "category=failing"
--report-trx
--report-trx-filename "${{ matrix.name }}-${{ matrix.os }}.trx"
--ignore-exit-code 8
- -- RunConfiguration.CollectSourceInformation=true
- --coverage
- --coverage-output-format cobertura
- --coverage-output coverage.cobertura.xml
+ --report-github
env:
CUSTOM_CONTAINER_REGISTRY: ${{ secrets.CUSTOM_CONTAINER_REGISTRY }}
diff --git a/Directory.Packages.props b/Directory.Packages.props
index dff6c199e..e118f2905 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -103,13 +103,14 @@
-
+
-
+
+
diff --git a/tests/.runsettings b/tests/.runsettings
deleted file mode 100644
index edd22a9eb..000000000
--- a/tests/.runsettings
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
- category!=failing
-
-
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/CommunityToolkit.Aspire.RavenDB.Client.Tests.csproj b/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/CommunityToolkit.Aspire.RavenDB.Client.Tests.csproj
index b4528f844..55c1a5d46 100644
--- a/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/CommunityToolkit.Aspire.RavenDB.Client.Tests.csproj
+++ b/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/CommunityToolkit.Aspire.RavenDB.Client.Tests.csproj
@@ -2,8 +2,6 @@
Exe
- enable
- enable
diff --git a/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
index 5ac36f30d..df989a3b7 100644
--- a/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
@@ -12,6 +12,7 @@
using OpenTelemetry.Trace;
using Xunit;
using Aspire.Components.Common.Tests;
+using Microsoft.DotNet.XUnitExtensions;
namespace Aspire.Components.ConformanceTests;
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index 73e0970b8..a6cc49957 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -15,10 +15,11 @@
-
+
-
+
+
@@ -41,7 +42,7 @@
https://learn.microsoft.com/dotnet/core/testing/microsoft-testing-platform-exit-codes -->
$(TestRunnerAdditionalArguments) --ignore-exit-code 8
-
+ true
\ No newline at end of file
From cb145d814c4049ba56de55349e92ee8b3b04cd33 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 24 Nov 2025 06:02:22 +0000
Subject: [PATCH 21/41] Missing a few packages
---
.github/workflows/tests.yaml | 4 ++--
Directory.Packages.props | 2 ++
tests/Directory.Build.props | 2 ++
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index dbc1dddc3..1ae625923 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -96,9 +96,9 @@ jobs:
- name: Run tests
run: >-
- dotnet run ${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }}
+ dotnet run
+ --project "${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }}"
--configuration ${{ env.DOTNET_CONFIGURATION }}
- --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true"
--crashdump
--hangdump
--hangdump-timeout 7m
diff --git a/Directory.Packages.props b/Directory.Packages.props
index e118f2905..0a59f0de0 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -110,6 +110,8 @@
+
+
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index a6cc49957..f12bdc86e 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -20,6 +20,8 @@
+
+
From 31b4c7114308e9f2dd2bf8b4abec9621a3eb71ac Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 24 Nov 2025 06:06:18 +0000
Subject: [PATCH 22/41] fixing ignore
---
.gitignore | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index d997c9787..959f23f3f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,7 @@ obj
appsettings.*.json
*.orig
test-results
-TestResults
+[Tt]est[Rr]esults
nuget
.pnpm-store
.DS_Store
From d319e2fa6204ca87e56c8320f62de692f1a3a3ba Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 24 Nov 2025 06:06:26 +0000
Subject: [PATCH 23/41] Fixing coverage arguments
---
.github/workflows/tests.yaml | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 1ae625923..33c14c135 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -99,16 +99,17 @@ jobs:
dotnet run
--project "${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }}"
--configuration ${{ env.DOTNET_CONFIGURATION }}
+ --no-restore
+ --no-build
--crashdump
--hangdump
--hangdump-timeout 7m
--results-directory "${{ github.workspace }}/testresults"
- --collect
- --no-restore
- --no-build
--filter-not-trait "category=failing"
--report-trx
--report-trx-filename "${{ matrix.name }}-${{ matrix.os }}.trx"
+ --coverage
+
--ignore-exit-code 8
--report-github
env:
From 587cacec5c531779c3e5f23dac96e8bb0ecf8cc5 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 24 Nov 2025 07:12:15 +0000
Subject: [PATCH 24/41] Running built binary
---
.github/workflows/tests.yaml | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 33c14c135..415aababf 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -96,11 +96,9 @@ jobs:
- name: Run tests
run: >-
- dotnet run
- --project "${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }}"
+ dotnet
+ ${{ github.workspace }}/artifacts/${{ matrix.name }}/CommunityToolkit.Aspire.${{ matrix.name }}.dll
--configuration ${{ env.DOTNET_CONFIGURATION }}
- --no-restore
- --no-build
--crashdump
--hangdump
--hangdump-timeout 7m
@@ -109,7 +107,7 @@ jobs:
--report-trx
--report-trx-filename "${{ matrix.name }}-${{ matrix.os }}.trx"
--coverage
-
+
--ignore-exit-code 8
--report-github
env:
From 874567a388143d936a82c8d8ffb3565c7430e6cc Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 24 Nov 2025 07:25:02 +0000
Subject: [PATCH 25/41] Don't need configuration on a run
---
.github/workflows/tests.yaml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 415aababf..0f005f01c 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -98,7 +98,6 @@ jobs:
run: >-
dotnet
${{ github.workspace }}/artifacts/${{ matrix.name }}/CommunityToolkit.Aspire.${{ matrix.name }}.dll
- --configuration ${{ env.DOTNET_CONFIGURATION }}
--crashdump
--hangdump
--hangdump-timeout 7m
From 837d9efce834019fda3e358840d0ed8932283516 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 24 Nov 2025 07:28:06 +0000
Subject: [PATCH 26/41] Removing an artificial bail out
---
tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs | 5 -----
1 file changed, 5 deletions(-)
diff --git a/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
index df989a3b7..13e8441a8 100644
--- a/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
@@ -270,11 +270,6 @@ public void LoggerFactoryIsUsedByRegisteredClient(bool registerAfterLoggerFactor
SkipIfRequiredServerConnectionCanNotBeEstablished();
SkipIfKeyedRegistrationIsNotSupported(useKey);
- if (RequiredLogCategories.Length == 0 && NotAcceptableLogCategories.Length == 0)
- {
- throw new SkipTestException("No log categories specified to test against.");
- }
-
string? key = useKey ? "key" : null;
HostApplicationBuilder builder = CreateHostBuilder(key: key);
From db8346874f4201debf472614ea1c33b4752f1927 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 24 Nov 2025 07:36:52 +0000
Subject: [PATCH 27/41] Removing flag
---
.github/workflows/tests.yaml | 2 --
1 file changed, 2 deletions(-)
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 0f005f01c..f703dba32 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -106,8 +106,6 @@ jobs:
--report-trx
--report-trx-filename "${{ matrix.name }}-${{ matrix.os }}.trx"
--coverage
-
- --ignore-exit-code 8
--report-github
env:
CUSTOM_CONTAINER_REGISTRY: ${{ secrets.CUSTOM_CONTAINER_REGISTRY }}
From 6d7a7784dc6fcf5b5a4fbde7d7d7efefeb132c1f Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Mon, 24 Nov 2025 07:40:40 +0000
Subject: [PATCH 28/41] going back to dotnet run
---
.github/workflows/tests.yaml | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index f703dba32..2cec8209e 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -92,12 +92,14 @@ jobs:
env:
CI: false
run: |
- dotnet build ${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }} /bl --configuration ${{ env.DOTNET_CONFIGURATION }} -o ${{ github.workspace }}/artifacts/${{ matrix.name }}
+ dotnet build ${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }} /bl --configuration ${{ env.DOTNET_CONFIGURATION }}
- name: Run tests
run: >-
- dotnet
- ${{ github.workspace }}/artifacts/${{ matrix.name }}/CommunityToolkit.Aspire.${{ matrix.name }}.dll
+ dotnet run
+ --project "${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }}"
+ --no-build
+ --configuration ${{ env.DOTNET_CONFIGURATION }}
--crashdump
--hangdump
--hangdump-timeout 7m
From 239aca3cca7343523acf7fa4e54f5aa2b96b7dcc Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Tue, 25 Nov 2025 12:14:22 +1100
Subject: [PATCH 29/41] Removing reference to runsettings
---
tests/Directory.Build.props | 1 -
1 file changed, 1 deletion(-)
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index f12bdc86e..43584435c 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -35,7 +35,6 @@
false
true
- $(MSBuildThisFileDirectory).runsettings
From 0ab87ce7a56545584fcb589e42e5ff769c14bde9 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Tue, 25 Nov 2025 12:15:16 +1100
Subject: [PATCH 30/41] Performing an earlier eval of the connection string
It seems there are two different paths for resolving the reference expression that _should_ return the same, but in the tests they don't seem to, so we'll force eval
---
.../MongoDBBuilderExtensions.cs | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/MongoDBBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/MongoDBBuilderExtensions.cs
index 30bd7777b..bc3bcb3a6 100644
--- a/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/MongoDBBuilderExtensions.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/MongoDBBuilderExtensions.cs
@@ -42,14 +42,14 @@ public static IResourceBuilder WithDbGate(this IResourceB
var dbGateBuilder = DbGateBuilderExtensions.AddDbGate(builder.ApplicationBuilder, containerName);
dbGateBuilder
- .WithEnvironment(context => ConfigureDbGateContainer(context, builder.ApplicationBuilder));
+ .WithEnvironment(async context => await ConfigureDbGateContainer(context, builder.ApplicationBuilder));
configureContainer?.Invoke(dbGateBuilder);
return builder;
}
- private static void ConfigureDbGateContainer(EnvironmentCallbackContext context, IDistributedApplicationBuilder applicationBuilder)
+ private static async Task ConfigureDbGateContainer(EnvironmentCallbackContext context, IDistributedApplicationBuilder applicationBuilder)
{
var mongoDBInstances = applicationBuilder.Resources.OfType();
@@ -66,7 +66,9 @@ private static void ConfigureDbGateContainer(EnvironmentCallbackContext context,
// DbGate assumes MongoDB is being accessed over a default Aspire container network and hardcodes the resource address
// This will need to be refactored once updated service discovery APIs are available
context.EnvironmentVariables.Add($"LABEL_mongodb{counter}", mongoDBServer.Name);
- context.EnvironmentVariables.Add($"URL_mongodb{counter}", mongoDBServer.ConnectionStringExpression);
+
+ // Forcing evaluation of the connection string here to avoid issues with late binding in DbGate
+ context.EnvironmentVariables.Add($"URL_mongodb{counter}", await mongoDBServer.ConnectionStringExpression.GetValueAsync(context.CancellationToken) ?? throw new InvalidOperationException($"Unable to resolve connection string for {mongoDBServer.Name}."));
context.EnvironmentVariables.Add($"ENGINE_mongodb{counter}", "mongo@dbgate-plugin-mongo");
counter++;
From 82737718e167b85cba27e1ef72cc9a6273f8f92c Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Wed, 3 Dec 2025 05:23:28 +0000
Subject: [PATCH 31/41] Adjusting msbuild props
---
tests/Directory.Build.props | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index 43584435c..c053eb938 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -38,10 +38,9 @@
- $(TestRunnerAdditionalArguments) --filter-not-trait "category=failing"
- $(TestRunnerAdditionalArguments) --ignore-exit-code 8
+ $(TestingPlatformCommandLineArguments) --ignore-exit-code 8 --filter-not-trait "category=failing"
true
From fb3743d6e2ae2e9fc2282fa720dfc7b91174297a Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Tue, 9 Dec 2025 04:51:59 +0000
Subject: [PATCH 32/41] Linux file systems are case sensitive - why has this
ever worked?
---
.../CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs
index 57f4bb348..c2cbb48fa 100644
--- a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs
+++ b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs
@@ -39,7 +39,7 @@ az storage blob upload --connection-string $myblob -c demo --file ./scripts/scri
// outputs "the sum of 2 and 3 is 5"
var script2 = ps.AddScript("script2", """
- & ./scripts/script.ps1 @args
+ & ./Scripts/script.ps1 @args
""")
.WithArgs(2, 3)
.WaitForCompletion(script1);
From 91576a2d5e8e3bbedd408a66305b295763619f5b Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Tue, 9 Dec 2025 05:28:55 +0000
Subject: [PATCH 33/41] The path when the scripts run during tests is different
to just running the app host
---
.../Program.cs | 19 ++++++++++++++++---
.../AppHostTests.cs | 3 +--
2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs
index c2cbb48fa..4814b6059 100644
--- a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs
+++ b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs
@@ -14,6 +14,7 @@
param($name)
write-information "Hello, $name"
+ write-information $pwd
# uncommenting this will hang the script if you don't attach the pwsh debugger
# wait-debugger
@@ -22,15 +23,19 @@
# only run this if Azure CLI is installed
if ((gcm az -ErrorAction SilentlyContinue) -ne $null) {
+ # When in the tests the PWD is wrong so we should test for it and fix it
+ if ($pwd -like "*CommunityToolkit.Aspire.Hosting.PowerShell.Tests*") {
+ write-information "Fixing PWD from $pwd"
+ Set-Location (Join-Path $pwd "../../../../../examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost")
+ write-information "New PWD is $pwd"
+ }
az storage container create --connection-string $myblob -n demo
- az storage blob upload --connection-string $myblob -c demo --file ./scripts/script.ps1
+ az storage blob upload --connection-string $myblob -c demo --file ./Scripts/script.ps1
write-information "Blob uploaded"
} else {
-
write-warning "Azure CLI not found, skipping blob upload"
-
}
write-information $pwd
@@ -39,6 +44,14 @@ az storage blob upload --connection-string $myblob -c demo --file ./scripts/scri
// outputs "the sum of 2 and 3 is 5"
var script2 = ps.AddScript("script2", """
+ write-information 'Getting there...'
+ if ($pwd -like "*CommunityToolkit.Aspire.Hosting.PowerShell.Tests*") {
+ write-information "Fixing PWD from $pwd"
+ Set-Location (Join-Path $pwd "../../../../../examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost")
+ write-information "New PWD is $pwd"
+ }
+ write-information $PWD
+
& ./Scripts/script.ps1 @args
""")
.WithArgs(2, 3)
diff --git a/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs
index 284d5c7bd..6472b383b 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs
@@ -1,4 +1,3 @@
-using Aspire.Components.Common.Tests;
using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Hosting.PowerShell.Tests;
@@ -14,7 +13,7 @@ public async Task PowerShellResourceStarts()
await fixture.ResourceNotificationService
.WaitForResourceAsync(resourceName, KnownResourceStates.Running)
.WaitAsync(TimeSpan.FromSeconds(60));
-
+
Assert.True(true);
}
From 3a0368b3508c3b85eb9c2286d7916a4e51d7caef Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Thu, 11 Dec 2025 22:41:26 +0000
Subject: [PATCH 34/41] Allowing mcp tests to run on all OS's
---
.../AppHostTests.cs | 2 --
1 file changed, 2 deletions(-)
diff --git a/tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/AppHostTests.cs
index 3b9a88cb2..372cc547a 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/AppHostTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/AppHostTests.cs
@@ -2,8 +2,6 @@
namespace CommunityToolkit.Aspire.Hosting.McpInspector.Tests;
-// Forcing linux only due to: https://github.com/modelcontextprotocol/inspector/issues/893
-[RequiresWindows]
public class AppHostTests(AspireIntegrationTestFixture fixture) : IClassFixture>
{
[Fact]
From 0b37f60e84da6506ed7599bab6c0b62d3a67684e Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Thu, 18 Dec 2025 23:29:17 +0000
Subject: [PATCH 35/41] Fixing copiler error
---
.../RequiresAuthenticatedToolAttribute.cs | 14 ++++++--
.../RequiresAuthenticatedToolDiscoverer.cs | 36 -------------------
2 files changed, 12 insertions(+), 38 deletions(-)
delete mode 100644 tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolDiscoverer.cs
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs
index 2a343d15e..4176b3076 100644
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs
@@ -1,5 +1,6 @@
using Aspire.Components.Common.Tests;
-using Xunit.Sdk;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit.v3;
namespace CommunityToolkit.Aspire.Testing;
@@ -7,7 +8,6 @@ namespace CommunityToolkit.Aspire.Testing;
/// Marks a test or test class as requiring an authenticated external tool.
/// Adds a trait to propagate the required tool name to the xUnit pipeline.
///
-[TraitDiscoverer("CommunityToolkit.Aspire.Testing.RequiresAuthenticatedToolDiscoverer", "CommunityToolkit.Aspire.Testing")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public sealed class RequiresAuthenticatedToolAttribute : Attribute, ITraitAttribute
{
@@ -34,4 +34,14 @@ public RequiresAuthenticatedToolAttribute(string toolName, string? reason = null
/// Gets a value indicating whether authenticated tools are supported in the current environment.
public static bool IsSupported => !PlatformDetection.IsRunningOnCI;
+
+ public IReadOnlyCollection> GetTraits()
+ {
+ if (!IsSupported)
+ {
+ return [new KeyValuePair(XunitConstants.Category, "failing")];
+ }
+
+ return [];
+ }
}
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolDiscoverer.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolDiscoverer.cs
deleted file mode 100644
index 9acb5b20b..000000000
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolDiscoverer.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using Xunit.Abstractions;
-using Xunit.Sdk;
-
-namespace CommunityToolkit.Aspire.Testing;
-
-///
-/// Discovers traits for .
-/// Adds a RequiresTools trait with the tool name and
-/// categorizes tests as unsupported-platform when authenticated tools are not supported.
-///
-public sealed class RequiresAuthenticatedToolDiscoverer : ITraitDiscoverer
-{
- ///
- public IEnumerable> GetTraits(IAttributeInfo traitAttribute)
- {
- string? toolName = null;
- foreach (object? argument in traitAttribute.GetConstructorArguments().Where(a => a is string))
- {
- if (argument is string value)
- {
- toolName = value;
- break;
- }
- }
-
- if (!string.IsNullOrWhiteSpace(toolName))
- {
- yield return new KeyValuePair("RequiresTools", toolName);
- }
-
- if (!RequiresAuthenticatedToolAttribute.IsSupported)
- {
- yield return new KeyValuePair("category", "unsupported-platform");
- }
- }
-}
From c3fab495974eff84fd5c75c7675097b305f25b59 Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Thu, 18 Dec 2025 23:34:01 +0000
Subject: [PATCH 36/41] Updated traits
---
.../RequiresAuthenticatedToolAttribute.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs
index 4176b3076..ee697b080 100644
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs
@@ -37,11 +37,13 @@ public RequiresAuthenticatedToolAttribute(string toolName, string? reason = null
public IReadOnlyCollection> GetTraits()
{
+ IReadOnlyCollection> traits = [new("RequiresTools", ToolName)];
+
if (!IsSupported)
{
- return [new KeyValuePair(XunitConstants.Category, "failing")];
+ traits = [.. traits, new KeyValuePair(XunitConstants.Category, "unsupported-platform")];
}
- return [];
+ return traits;
}
}
From 4f896d39bb7af112d7771ea4fc687530ff70368b Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Wed, 14 Jan 2026 23:27:14 +0000
Subject: [PATCH 37/41] Fixing compiler errors
---
.../CommunityToolkit.Aspire.Hosting.Sftp.Tests/AppHostTests.cs | 1 -
.../SftpFunctionalTests.cs | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/AppHostTests.cs
index 7d9f08f99..04f529ca3 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/AppHostTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/AppHostTests.cs
@@ -3,7 +3,6 @@
using Polly;
using Projects;
using Renci.SshNet;
-using Xunit.Abstractions;
namespace CommunityToolkit.Aspire.Hosting.Sftp.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/SftpFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/SftpFunctionalTests.cs
index c9aa4fc1b..d29503c55 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/SftpFunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/SftpFunctionalTests.cs
@@ -1,12 +1,12 @@
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Polly;
using Renci.SshNet;
using Renci.SshNet.Common;
-using Xunit.Abstractions;
namespace CommunityToolkit.Aspire.Hosting.Sftp.Tests;
From 6107c687d99dd1f2c283c4cc2dce192daea4a4fe Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Thu, 15 Jan 2026 11:32:35 +1100
Subject: [PATCH 38/41] Fixing a few failing test suites
---
.../ResourceCreationTests.cs | 2 +-
.../ResourceCreationTests.cs | 2 +-
.../AppHostTests.cs | 1 -
.../RequiresAuthenticatedToolAttribute.cs | 2 +-
4 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/ResourceCreationTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/ResourceCreationTests.cs
index c02a12420..5a5c27842 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/ResourceCreationTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/ResourceCreationTests.cs
@@ -45,7 +45,7 @@ public async Task WithDbGateAddsAnnotations()
{
var redisUrl = redisResource.PasswordParameter is not null ?
$"redis://:{await redisResource.PasswordParameter.GetValueAsync(default)}@{redisResource.Name}:{redisResource.PrimaryEndpoint.TargetPort}" : $"redis://{redisResource.Name}:{redisResource.PrimaryEndpoint.TargetPort}";
- Assert.Equal("URL_redis1", item.Key);
+ Assert.Equal("URL_redis", item.Key);
Assert.Equal(redisUrl, item.Value);
},
item =>
diff --git a/tests/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.Tests/ResourceCreationTests.cs b/tests/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.Tests/ResourceCreationTests.cs
index 6fcd43bfa..fd885a83f 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.Tests/ResourceCreationTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.Tests/ResourceCreationTests.cs
@@ -53,7 +53,7 @@ public async Task WithDbGateAddsAnnotations()
},
async item =>
{
- Assert.Equal("PASSWORD_sqlserver1", item.Key);
+ Assert.Equal("PASSWORD_sqlserver", item.Key);
Assert.Equal(await sqlserverResource.PasswordParameter.GetValueAsync(default), item.Value);
},
item =>
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Stripe.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Stripe.Tests/AppHostTests.cs
index 83901481a..17c8f84ea 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Stripe.Tests/AppHostTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Stripe.Tests/AppHostTests.cs
@@ -1,4 +1,3 @@
-using Aspire.Components.Common.Tests;
using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Hosting.Stripe.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs
index ee697b080..0b53638b3 100644
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs
@@ -41,7 +41,7 @@ public IReadOnlyCollection> GetTraits()
if (!IsSupported)
{
- traits = [.. traits, new KeyValuePair(XunitConstants.Category, "unsupported-platform")];
+ traits = [.. traits, new KeyValuePair(XunitConstants.Category, "failing")];
}
return traits;
From 1d1b7306fc874673f9e9d832f0798718b2c00e0b Mon Sep 17 00:00:00 2001
From: Aaron Powell
Date: Thu, 15 Jan 2026 14:49:43 +1100
Subject: [PATCH 39/41] Ensuring PowerShell terminates properly
The PowerShell Runspace doesn't when the app host does, which I think is the underlying cause as to why the tests hang. This now monitors the script resources so that when they complete we force a dispose on them (thus freeing any process they may have used) and once all are completed the Runspace is disposed, releasing it and **I think** that should allow the test host to terminate
---
.../PowerShellRunspacePoolResource.cs | 5 ++++
...llRunspacePoolResourceBuilderExtensions.cs | 23 +++++++++++++++++++
.../AppHostTests.cs | 3 +++
3 files changed, 31 insertions(+)
diff --git a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs
index a0a90156d..ea8ed8b6f 100644
--- a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs
@@ -37,6 +37,11 @@ public class PowerShellRunspacePoolResource(
///
public RunspacePool? Pool { get; private set; }
+ private Dictionary scriptResourceCompletion = [];
+ internal void AddScriptResource(PowerShellScriptResource scriptResource) => scriptResourceCompletion.Add(scriptResource.Name, false);
+ internal void ScriptResourceCompleted(PowerShellScriptResource scriptResource) => scriptResourceCompletion[scriptResource.Name] = true;
+ internal bool ScriptsCompleted => scriptResourceCompletion.Any(r => r.Value == false);
+
internal Task StartAsync(InitialSessionState sessionState, ResourceNotificationService notificationService, ILogger logger, CancellationToken token = default)
{
logger.LogInformation(
diff --git a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs
index 5ab6437b6..2497dcc4d 100644
--- a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs
@@ -3,6 +3,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
using System.Management.Automation;
namespace CommunityToolkit.Aspire.Hosting.PowerShell;
@@ -49,6 +50,26 @@ await builder.ApplicationBuilder.Eventing.PublishAsync(
scriptLogger.LogInformation("Starting script '{ScriptName}'", scriptName);
_ = scriptResource.StartAsync(scriptLogger, notificationService, ct);
+
+ await notificationService.WaitForResourceAsync(scriptResource.Name, KnownResourceStates.Finished, ct);
+
+ ((IDisposable)scriptResource).Dispose();
+
+ builder.Resource.ScriptResourceCompleted(scriptResource);
+
+ if (builder.Resource.ScriptsCompleted)
+ {
+ await notificationService.PublishUpdateAsync(builder.Resource, state => state with
+ {
+ State = KnownResourceStates.Finished,
+ Properties = [
+ .. state.Properties,
+ ],
+ StopTimeStamp = DateTime.Now,
+ });
+
+ ((IDisposable)builder.Resource).Dispose();
+ }
}
catch (Exception ex)
{
@@ -56,6 +77,8 @@ await builder.ApplicationBuilder.Eventing.PublishAsync(
}
});
+ builder.Resource.AddScriptResource(scriptResource);
+
return builder.ApplicationBuilder
.AddResource(scriptResource)
.WithParentRelationship(builder.Resource)
diff --git a/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs
index 6472b383b..8e52a7f26 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs
@@ -39,6 +39,9 @@ public async Task ScriptsExecuteSuccessfully()
.WaitAsync(TimeSpan.FromSeconds(90));
await Task.WhenAll([ready1, ready2]);
+
+ Assert.True(ready1.IsCompletedSuccessfully);
+ Assert.True(ready2.IsCompletedSuccessfully);
}
}
From b93dc7c23020dba8a5ff88aa9587cc1034cb54f5 Mon Sep 17 00:00:00 2001
From: Oisin Grehan
Date: Thu, 15 Jan 2026 12:20:58 -0500
Subject: [PATCH 40/41] Revert "Ensuring PowerShell terminates properly"
This reverts commit 1d1b7306fc874673f9e9d832f0798718b2c00e0b.
---
.../PowerShellRunspacePoolResource.cs | 5 ----
...llRunspacePoolResourceBuilderExtensions.cs | 23 -------------------
.../AppHostTests.cs | 3 ---
3 files changed, 31 deletions(-)
diff --git a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs
index ea8ed8b6f..a0a90156d 100644
--- a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs
@@ -37,11 +37,6 @@ public class PowerShellRunspacePoolResource(
///
public RunspacePool? Pool { get; private set; }
- private Dictionary scriptResourceCompletion = [];
- internal void AddScriptResource(PowerShellScriptResource scriptResource) => scriptResourceCompletion.Add(scriptResource.Name, false);
- internal void ScriptResourceCompleted(PowerShellScriptResource scriptResource) => scriptResourceCompletion[scriptResource.Name] = true;
- internal bool ScriptsCompleted => scriptResourceCompletion.Any(r => r.Value == false);
-
internal Task StartAsync(InitialSessionState sessionState, ResourceNotificationService notificationService, ILogger logger, CancellationToken token = default)
{
logger.LogInformation(
diff --git a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs
index 2497dcc4d..5ab6437b6 100644
--- a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs
@@ -3,7 +3,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Diagnostics.CodeAnalysis;
-using System.Drawing;
using System.Management.Automation;
namespace CommunityToolkit.Aspire.Hosting.PowerShell;
@@ -50,26 +49,6 @@ await builder.ApplicationBuilder.Eventing.PublishAsync(
scriptLogger.LogInformation("Starting script '{ScriptName}'", scriptName);
_ = scriptResource.StartAsync(scriptLogger, notificationService, ct);
-
- await notificationService.WaitForResourceAsync(scriptResource.Name, KnownResourceStates.Finished, ct);
-
- ((IDisposable)scriptResource).Dispose();
-
- builder.Resource.ScriptResourceCompleted(scriptResource);
-
- if (builder.Resource.ScriptsCompleted)
- {
- await notificationService.PublishUpdateAsync(builder.Resource, state => state with
- {
- State = KnownResourceStates.Finished,
- Properties = [
- .. state.Properties,
- ],
- StopTimeStamp = DateTime.Now,
- });
-
- ((IDisposable)builder.Resource).Dispose();
- }
}
catch (Exception ex)
{
@@ -77,8 +56,6 @@ await notificationService.PublishUpdateAsync(builder.Resource, state => state wi
}
});
- builder.Resource.AddScriptResource(scriptResource);
-
return builder.ApplicationBuilder
.AddResource(scriptResource)
.WithParentRelationship(builder.Resource)
diff --git a/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs
index 8e52a7f26..6472b383b 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs
@@ -39,9 +39,6 @@ public async Task ScriptsExecuteSuccessfully()
.WaitAsync(TimeSpan.FromSeconds(90));
await Task.WhenAll([ready1, ready2]);
-
- Assert.True(ready1.IsCompletedSuccessfully);
- Assert.True(ready2.IsCompletedSuccessfully);
}
}
From 7ed360d5951d03710a3857172c8c6fce15c119ac Mon Sep 17 00:00:00 2001
From: Oisin Grehan
Date: Mon, 19 Jan 2026 13:15:52 -0500
Subject: [PATCH 41/41] hook applicationstopping on host lifecycle to shutdown
RS pool
---
.../Program.cs | 9 +++-
.../Properties/launchSettings.json | 1 +
...DistributedApplicationBuilderExtensions.cs | 44 ++++++++--------
.../PowerShellRunspacePoolResource.cs | 10 +++-
...llRunspacePoolResourceBuilderExtensions.cs | 52 ++++++++++---------
5 files changed, 67 insertions(+), 49 deletions(-)
diff --git a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs
index 4814b6059..dc33823bf 100644
--- a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs
+++ b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs
@@ -2,7 +2,13 @@
var builder = DistributedApplication.CreateBuilder(args);
-var storage = builder.AddAzureStorage("storage").RunAsEmulator();
+var storage = builder.AddAzureStorage("storage")
+ // see: https://github.com/dotnet/aspire/issues/13811
+ .RunAsEmulator(azurite =>
+ {
+ azurite.WithArgs("--disableProductStyleUrl");
+ });
+
var blob = storage.AddBlobs("myblob");
var ps = builder.AddPowerShell("ps")
@@ -57,5 +63,6 @@ az storage blob upload --connection-string $myblob -c demo --file ./Scripts/scri
.WithArgs(2, 3)
.WaitForCompletion(script1);
+
builder.Build().Run();
diff --git a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Properties/launchSettings.json b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Properties/launchSettings.json
index 80e6457ea..64093b07a 100644
--- a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Properties/launchSettings.json
+++ b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Properties/launchSettings.json
@@ -7,6 +7,7 @@
"launchBrowser": true,
"applicationUrl": "https://localhost:17118;http://localhost:15215",
"environmentVariables": {
+ "DCP_DIAGNOSTICS_LOG_LEVEL": "debug",
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21165",
diff --git a/src/CommunityToolkit.Aspire.Hosting.PowerShell/DistributedApplicationBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.PowerShell/DistributedApplicationBuilderExtensions.cs
index baf5ce2b1..f2a3970a2 100644
--- a/src/CommunityToolkit.Aspire.Hosting.PowerShell/DistributedApplicationBuilderExtensions.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.PowerShell/DistributedApplicationBuilderExtensions.cs
@@ -1,6 +1,7 @@
using Aspire.Hosting;
using Aspire.Hosting.ApplicationModel;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using System.Diagnostics;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
@@ -34,23 +35,34 @@ public static IResourceBuilder AddPowerShell(
var pool = new PowerShellRunspacePoolResource(name, languageMode, minRunspaces, maxRunspaces);
+ var poolBuilder = builder.AddResource(pool)
+ .WithInitialState(new()
+ {
+ ResourceType = "PowerShellRunspacePool",
+ State = KnownResourceStates.NotStarted,
+ Properties = [
- builder.Eventing.Subscribe(pool, async (e, ct) =>
- {
- var poolResource = e.Resource as PowerShellRunspacePoolResource;
-
- Debug.Assert(poolResource is not null);
+ new ("LanguageMode", pool.LanguageMode.ToString()),
+ new ("MinRunspaces", pool.MinRunspaces.ToString()),
+ new ("MaxRunspaces", pool.MaxRunspaces.ToString())
+ ]
+ })
+ .ExcludeFromManifest();
+ poolBuilder.OnInitializeResource(async (res, e, ct) =>
+ {
var loggerService = e.Services.GetRequiredService();
var notificationService = e.Services.GetRequiredService();
+ var hostLifetime = e.Services.GetRequiredService();
var sessionState = InitialSessionState.CreateDefault();
+ sessionState.UseFullLanguageModeInDebugger = true;
// This will block until explicit and implied WaitFor calls are completed
await builder.Eventing.PublishAsync(
- new BeforeResourceStartedEvent(poolResource, e.Services), ct);
+ new BeforeResourceStartedEvent(res, e.Services), ct);
- foreach (var annotation in poolResource.Annotations.OfType>())
+ foreach (var annotation in res.Annotations.OfType>())
{
if (annotation is { } reference)
{
@@ -62,24 +74,12 @@ await builder.Eventing.PublishAsync(
}
}
- var poolName = poolResource.Name;
+ var poolName = res.Name;
var poolLogger = loggerService.GetLogger(poolName);
- _ = poolResource.StartAsync(sessionState, notificationService, poolLogger, ct);
+ _ = res.StartAsync(sessionState, notificationService, poolLogger, hostLifetime, ct);
});
- return builder.AddResource(pool)
- .WithInitialState(new()
- {
- ResourceType = "PowerShellRunspacePool",
- State = KnownResourceStates.NotStarted,
- Properties = [
-
- new ("LanguageMode", pool.LanguageMode.ToString()),
- new ("MinRunspaces", pool.MinRunspaces.ToString()),
- new ("MaxRunspaces", pool.MaxRunspaces.ToString())
- ]
- })
- .ExcludeFromManifest();
+ return poolBuilder;
}
}
\ No newline at end of file
diff --git a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs
index a0a90156d..96831fe61 100644
--- a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs
@@ -1,4 +1,5 @@
using Aspire.Hosting.ApplicationModel;
+using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Globalization;
using System.Management.Automation;
@@ -37,7 +38,7 @@ public class PowerShellRunspacePoolResource(
///
public RunspacePool? Pool { get; private set; }
- internal Task StartAsync(InitialSessionState sessionState, ResourceNotificationService notificationService, ILogger logger, CancellationToken token = default)
+ internal Task StartAsync(InitialSessionState sessionState, ResourceNotificationService notificationService, ILogger logger, IHostApplicationLifetime hostLifetime, CancellationToken token = default)
{
logger.LogInformation(
"Starting PowerShell runspace pool '{PoolName}' with {MinRunspaces} to {MaxRunspaces} runspaces",
@@ -48,6 +49,13 @@ internal Task StartAsync(InitialSessionState sessionState, ResourceNotificationS
Pool = RunspaceFactory.CreateRunspacePool(MinRunspaces, MaxRunspaces, sessionState, new AspirePSHost(logger));
ConfigureStateChangeNotifications(notificationService, logger);
+
+ hostLifetime.ApplicationStopping.Register(() =>
+ {
+ // if we don't do this, xunit 3 will hang on exit because of open runspaces (foreground threads)
+ logger.LogInformation("Closing PowerShell runspace pool '{PoolName}'", Name);
+ Pool?.Close();
+ });
return Task.Factory.FromAsync(Pool.BeginOpen, Pool.EndOpen, null);
}
diff --git a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs
index 5ab6437b6..695a8ce97 100644
--- a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs
@@ -32,31 +32,7 @@ public static IResourceBuilder AddScript(
var scriptResource = new PowerShellScriptResource(name, scriptBlock, builder.Resource);
- builder.ApplicationBuilder.Eventing.Subscribe(scriptResource, async (e, ct) =>
- {
- var loggerService = e.Services.GetRequiredService();
- var notificationService = e.Services.GetRequiredService();
-
- var scriptName = scriptResource.Name;
- var scriptLogger = loggerService.GetLogger(scriptName);
-
- try
- {
- // this will block until the runspace pool is started, which is implied by the WaitFor call
- await builder.ApplicationBuilder.Eventing.PublishAsync(
- new BeforeResourceStartedEvent(scriptResource, e.Services), ct);
-
- scriptLogger.LogInformation("Starting script '{ScriptName}'", scriptName);
-
- _ = scriptResource.StartAsync(scriptLogger, notificationService, ct);
- }
- catch (Exception ex)
- {
- scriptLogger.LogError(ex, "Failed to start script '{ScriptName}'", scriptName);
- }
- });
-
- return builder.ApplicationBuilder
+ var scriptBuilder = builder.ApplicationBuilder
.AddResource(scriptResource)
.WithParentRelationship(builder.Resource)
.WaitFor(builder)
@@ -88,6 +64,32 @@ await builder.ApplicationBuilder.Eventing.PublishAsync(
ResourceCommandState.Disabled :
ResourceCommandState.Enabled
});
+
+ scriptBuilder.OnInitializeResource(async (res, e, ct) =>
+ {
+ var loggerService = e.Services.GetRequiredService();
+ var notificationService = e.Services.GetRequiredService();
+
+ var scriptName = res.Name;
+ var scriptLogger = loggerService.GetLogger(scriptName);
+
+ try
+ {
+ // this will block until the runspace pool is started, which is implied by the WaitFor call
+ await builder.ApplicationBuilder.Eventing.PublishAsync(
+ new BeforeResourceStartedEvent(res, e.Services), ct);
+
+ scriptLogger.LogInformation("Starting script '{ScriptName}'", scriptName);
+
+ _ = res.StartAsync(scriptLogger, notificationService, ct);
+ }
+ catch (Exception ex)
+ {
+ scriptLogger.LogError(ex, "Failed to start script '{ScriptName}'", scriptName);
+ }
+ });
+
+ return scriptBuilder;
}
///