Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
4e9036e
Initial plan
Copilot Nov 6, 2025
7236d38
Add .NET 10 (preview) as a TFM for multi-targeting builds
Copilot Nov 6, 2025
303a76f
Change default TFM to .NET 10 and update GitHub Actions to install .N…
Copilot Nov 6, 2025
c6b19fc
Update devcontainer to install .NET 10 as preview
Copilot Nov 6, 2025
1e4e20d
Add .NET 10 to setup-runtimes-caching action
Copilot Nov 6, 2025
ac50650
Fixing some versioning
aaronpowell Nov 6, 2025
9441794
Hard coding an update to use Apache.NMS.AMQP@2.4.0 as 2.2.0 has a CVE…
aaronpowell Nov 6, 2025
ef89379
Fixing some projects that specified their own TFM and trying to addre…
aaronpowell Nov 6, 2025
e66de71
Using an improved approach approach to adding system.linq.asyncenumer…
aaronpowell Nov 7, 2025
51e57ba
Updating how dev certs are setup
aaronpowell Nov 10, 2025
f3ff1ff
Turns out you can't upgrade around the CVE, so we now suppress it
aaronpowell Nov 10, 2025
df16921
Update to xunit v3
aaronpowell Nov 10, 2025
1ac2ad3
Disabling JSON schema tests as we don't generate those files
aaronpowell Nov 10, 2025
5840c2e
Some adjustments to not be so aspire configured
aaronpowell Nov 10, 2025
dcfbd73
Oh, some of that was used
aaronpowell Nov 10, 2025
102aaab
Adding filter for failing tests to be skipped
aaronpowell Nov 10, 2025
733964b
using dotnet <assembly> to run tests rather than dotnet test
aaronpowell Nov 10, 2025
f10b449
forgot I made that change
aaronpowell Nov 10, 2025
425a39e
updating a few more deps
aaronpowell Nov 10, 2025
58b4b33
Merge branch 'main' into xunit-3-upgrade
aaronpowell Nov 24, 2025
270aa58
Updating based on comments and using the new GitHubActionsTestLogger …
aaronpowell Nov 24, 2025
cb145d8
Missing a few packages
aaronpowell Nov 24, 2025
31b4c71
fixing ignore
aaronpowell Nov 24, 2025
d319e2f
Fixing coverage arguments
aaronpowell Nov 24, 2025
587cace
Running built binary
aaronpowell Nov 24, 2025
874567a
Don't need configuration on a run
aaronpowell Nov 24, 2025
837d9ef
Removing an artificial bail out
aaronpowell Nov 24, 2025
db83468
Removing flag
aaronpowell Nov 24, 2025
6d7a778
going back to dotnet run
aaronpowell Nov 24, 2025
239aca3
Removing reference to runsettings
aaronpowell Nov 25, 2025
0ab87ce
Performing an earlier eval of the connection string
aaronpowell Nov 25, 2025
70133ad
Merge branch 'main' into xunit-3-upgrade
aaronpowell Nov 26, 2025
f925398
Merge branch 'main' into xunit-3-upgrade
aaronpowell Dec 3, 2025
d7d256d
Merge branch 'xunit-3-upgrade' of https://github.com/CommunityToolkit…
aaronpowell Dec 3, 2025
8273771
Adjusting msbuild props
aaronpowell Dec 3, 2025
fb3743d
Linux file systems are case sensitive - why has this ever worked?
aaronpowell Dec 9, 2025
91576a2
The path when the scripts run during tests is different to just runni…
aaronpowell Dec 9, 2025
3a0368b
Allowing mcp tests to run on all OS's
aaronpowell Dec 11, 2025
51d39e6
Merge branch 'main' into xunit-3-upgrade
aaronpowell Dec 18, 2025
0b37f60
Fixing copiler error
aaronpowell Dec 18, 2025
c3fab49
Updated traits
aaronpowell Dec 18, 2025
7974f67
Merge branch 'main' into xunit-3-upgrade
aaronpowell Jan 13, 2026
ad34cdb
Merge branch 'main' into xunit-3-upgrade
aaronpowell Jan 14, 2026
a099502
Merge branch 'main' into xunit-3-upgrade
aaronpowell Jan 14, 2026
4f896d3
Fixing compiler errors
aaronpowell Jan 14, 2026
f1d373a
Merge branch 'xunit-3-upgrade' of https://github.com/CommunityToolkit…
aaronpowell Jan 14, 2026
6107c68
Fixing a few failing test suites
aaronpowell Jan 15, 2026
1d1b730
Ensuring PowerShell terminates properly
aaronpowell Jan 15, 2026
b93dc7c
Revert "Ensuring PowerShell terminates properly"
Jan 15, 2026
7ed360d
hook applicationstopping on host lifecycle to shutdown RS pool
Jan 19, 2026
15e7108
Merge pull request #1113 from oising/xunit-3-upgrade
aaronpowell Jan 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/setup-runtimes-caching/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,4 @@ runs:
if: ${{ inputs.name == 'Full' || contains(inputs.name, 'Hosting.Ollama') }}
with:
version: 0.11.8

23 changes: 12 additions & 11 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,19 @@ jobs:

- name: Run tests
run: >-
dotnet test ${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }}
dotnet run
--project "${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }}"
--no-build
--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"
--no-restore
--no-build -- RunConfiguration.CollectSourceInformation=true
--crashdump
--hangdump
--hangdump-timeout 7m
--results-directory "${{ github.workspace }}/testresults"
--filter-not-trait "category=failing"
--report-trx
--report-trx-filename "${{ matrix.name }}-${{ matrix.os }}.trx"
--coverage
--report-github
env:
CUSTOM_CONTAINER_REGISTRY: ${{ secrets.CUSTOM_CONTAINER_REGISTRY }}

Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ obj
appsettings.*.json
*.orig
test-results
TestResults
[Tt]est[Rr]esults
nuget
.pnpm-store
.DS_Store
Expand Down
65 changes: 39 additions & 26 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down
17 changes: 11 additions & 6 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,18 @@
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
<PackageVersion Include="OpenFeature.Contrib.Providers.Flagd" Version="0.3.3" />
<PackageVersion Include="OpenFeature.Providers.Ofrep" Version="0.1.2" />
<PackageVersion Include="MartinCostello.Logging.XUnit" Version="0.6.0" />
<PackageVersion Include="MartinCostello.Logging.XUnit.v3" Version="0.6.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageVersion Include="xunit.extensibility.execution" Version="2.9.3" />
<PackageVersion Include="Microsoft.DotNet.XUnitExtensions" Version="9.0.0-beta.24568.1" />
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
<PackageVersion Include="xunit.v3.mtp-v2" Version="3.2.0" />
<PackageVersion Include="xunit.v3.assert" Version="3.2.0" />
<PackageVersion Include="xunit.v3.extensibility.core" Version="3.2.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: no longer needed if you don't care about VSTest support.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />

<PackageVersion Include="Microsoft.DotNet.XUnitV3Extensions" Version="11.0.0-beta.25509.1" />
<PackageVersion Include="Microsoft.Testing.Extensions.CodeCoverage" Version="18.1.0" />
<PackageVersion Include="Microsoft.Testing.Extensions.TrxReport" Version="2.0.2" />
<PackageVersion Include="Microsoft.Testing.Extensions.CrashDump" Version="2.0.2" />
<PackageVersion Include="Microsoft.Testing.Extensions.HangDump" Version="2.0.2" />
<PackageVersion Include="GitHubActionsTestLogger" Version="3.0.0" />
<PackageVersion Include="Moq" Version="$(MoqVersion)" />
<!-- Build dependencies -->
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.4" />
Expand Down
85 changes: 85 additions & 0 deletions eng/clean-bin-obj.sh
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -14,6 +20,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
Expand All @@ -22,15 +29,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

Expand All @@ -39,10 +50,19 @@ 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
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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that Powershell is case sensitive (cc @nohwnd)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is up to the file system not up to powershell. If this needs to run on linux and the filesystem is case sensitive then ./scripts and ./Scripts are two different paths. On windows we typically don't use case sensitive file systems.

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_case-sensitivity?view=powershell-7.5

""")
.WithArgs(2, 3)
.WaitForCompletion(script1);


builder.Build().Run();

Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion nuget.config
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</packageSources>
<packageSourceMapping>
<packageSource key="dotnet-eng">
<package pattern="Microsoft.DotNet.XUnitExtensions" />
<package pattern="Microsoft.DotNet.XUnitV3Extensions" />
</packageSource>
<packageSource key="dotnet9-transport">
<package pattern="Microsoft.DotNet.GenAPI.Task" />
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -34,23 +35,34 @@ public static IResourceBuilder<PowerShellRunspacePoolResource> 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<InitializeResourceEvent>(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<ResourceLoggerService>();
var notificationService = e.Services.GetRequiredService<ResourceNotificationService>();
var hostLifetime = e.Services.GetRequiredService<IHostApplicationLifetime>();

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<PowerShellVariableReferenceAnnotation<ConnectionStringReference>>())
foreach (var annotation in res.Annotations.OfType<PowerShellVariableReferenceAnnotation<ConnectionStringReference>>())
{
if (annotation is { } reference)
{
Expand All @@ -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;
}
}
Loading
Loading