Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
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
10 changes: 2 additions & 8 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": ".NET Aspire Community Toolkit",
"image": "mcr.microsoft.com/devcontainers/dotnet:8.0-jammy",
"image": "mcr.microsoft.com/devcontainers/dotnet:8.0-noble",
"features": {
"ghcr.io/azure/azure-dev/azd:latest": {},
"ghcr.io/devcontainers/features/dotnet:latest": {
Expand Down Expand Up @@ -43,11 +43,5 @@
"postCreateCommand": "./.devcontainer/post-create.sh > ~/post-create.log",
"hostRequirements": {
"memory": "8gb"
},
"portsAttributes": {
"4280": {
"label": "SWA Emulator",
"onAutoForward": "notify"
}
}
}
}
8 changes: 4 additions & 4 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
<Nullable>enable</Nullable>

<AspireMajorVersion>9</AspireMajorVersion>
<AspireVersion>$(AspireMajorVersion).4.1</AspireVersion>
<AspireVersion>$(AspireMajorVersion).5.0</AspireVersion>
<AspireAppHostSdkVersion>$(AspireVersion)</AspireAppHostSdkVersion>
<AspNetCoreVersion>9.0.0</AspNetCoreVersion>
<DotNetExtensionsVersion>9.0.4</DotNetExtensionsVersion>
<DotNetExtensionsVersion>9.0.9</DotNetExtensionsVersion>
<OpenTelemetryVersion>1.12.0</OpenTelemetryVersion>
<TestContainersVersion>4.4.0</TestContainersVersion>
<MEAIVersion>9.5.0</MEAIVersion>
<TestContainersVersion>4.7.0</TestContainersVersion>
<MEAIVersion>9.9.0</MEAIVersion>
<IsPackable>false</IsPackable>

<RepoRoot>$(MSBuildThisFileDirectory)</RepoRoot>
Expand Down
42 changes: 21 additions & 21 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
<PackageVersion Include="Dapr.AspNetCore" Version="1.15.3" />
<PackageVersion Include="Dapr.Client" Version="1.15.3" />
<PackageVersion Include="Microsoft.AspNetCore.Components.QuickGrid" Version="$(AspNetCoreVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.20" />
<PackageVersion Include="Microsoft.DotNet.PlatformAbstractions" Version="3.1.6" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.4">
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.9">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageVersion>
Expand All @@ -44,8 +44,8 @@
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(DotNetExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.7" />
<!-- .NET packages -->
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.4.0" />
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery" Version="9.1.0" />
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.9.0" />
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery" Version="$(AspireVersion)" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="$(DotNetExtensionsVersion)" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="$(DotNetExtensionsVersion)" />
Expand All @@ -64,20 +64,20 @@
<ItemGroup Label="Integration Packages">
<!-- External packages -->
<PackageVersion Include="Azure.Provisioning.AppContainers" Version="1.1.0" />
<PackageVersion Include="JsonSchema.Net" Version="7.3.4" />
<PackageVersion Include="OllamaSharp" Version="5.1.12" />
<PackageVersion Include="JsonSchema.Net" Version="7.4.0" />
<PackageVersion Include="OllamaSharp" Version="5.4.6" />
<PackageVersion Include="OpenFeature.Contrib.GOFeatureFlag" Version="0.2.1" />
<PackageVersion Include="Minio" Version="6.0.4" />
<PackageVersion Include="MassTransit" Version="8.4.0" />
<PackageVersion Include="MassTransit.ActiveMQ" Version="8.4.0" />
<PackageVersion Include="MassTransit.RabbitMQ" Version="8.4.0" />
<PackageVersion Include="MeiliSearch" Version="0.16.0" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="8.0.13" />
<PackageVersion Include="Minio" Version="6.0.5" />
<PackageVersion Include="MassTransit" Version="8.5.2" />
<PackageVersion Include="MassTransit.ActiveMQ" Version="8.5.2" />
<PackageVersion Include="MassTransit.RabbitMQ" Version="8.5.2" />
<PackageVersion Include="MeiliSearch" Version="0.17.1" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.9" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.9" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="8.0.20" />
<PackageVersion Include="Microsoft.SqlServer.DacFx" Version="170.1.61" />
<PackageVersion Include="Microsoft.Build" Version="17.11.4" />
<PackageVersion Include="Microsoft.Build.Locator" Version="1.7.8" />
<PackageVersion Include="Microsoft.Build" Version="17.11.31" />
<PackageVersion Include="Microsoft.Build.Locator" Version="1.9.1" />
<PackageVersion Include="EventStore.Client.Extensions.OpenTelemetry" Version="23.3.8" />
<PackageVersion Include="EventStore.Client.Grpc.Streams" Version="23.3.8" />
<PackageVersion Include="ErikEJ.Dacpac.Chinook" Version="1.0.0" />
Expand All @@ -94,10 +94,10 @@
<ItemGroup Label="Testing">
<!-- Testing packages -->
<PackageVersion Include="Aspire.Hosting.Testing" Version="$(AspireVersion)" />
<PackageVersion Include="Bogus" Version="35.6.1" />
<PackageVersion Include="Bogus" Version="35.6.3" />
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
<PackageVersion Include="MartinCostello.Logging.XUnit" Version="0.5.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageVersion Include="MartinCostello.Logging.XUnit" 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" />
Expand All @@ -110,7 +110,7 @@
<PackageVersion Include="Testcontainers.MsSql" Version="$(TestContainersVersion)" />
</ItemGroup>
<ItemGroup Label=".NET 9 Overrides" Condition="'$(TargetFramework)' == 'net9.0'">
<PackageVersion Update="Microsoft.Extensions.Logging.Abstractions" Version="9.0.7" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.7" />
<PackageVersion Update="Microsoft.Extensions.Logging.Abstractions" Version="9.0.9" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.9" />
</ItemGroup>
</Project>
13 changes: 6 additions & 7 deletions nuget.config
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
<add key="dotnet9-transport" value="https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet9-transport/nuget/v3/index.json" />
<!-- <add key="dotnet9" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json" /> -->
<add key="aspire9-5-public" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-aspire-48a11dae/nuget/v3/index.json" />
</packageSources>
<packageSourceMapping>
<!-- <packageSource key="dotnet9">
<package pattern="Aspire.*" />
<package pattern="Microsoft.Extensions.ServiceDiscovery*" />
<package pattern="Microsoft.Extensions.Http.Resilience" />
</packageSource> -->
<packageSource key="aspire9-5-public">
<package pattern="Aspire.*" />
<package pattern="Microsoft.Extensions.ServiceDiscovery*" />
</packageSource>
Copy link

Copilot AI Sep 23, 2025

Choose a reason for hiding this comment

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

The line has trailing whitespace that should be removed for consistency with project formatting standards.

See below for a potential fix:

    <add key="aspire9-5-public" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-aspire-48a11dae/nuget/v3/index.json" />
  </packageSources>
  <packageSourceMapping>
    <packageSource key="aspire9-5-public">
      <package pattern="Aspire.*" />
      <package pattern="Microsoft.Extensions.ServiceDiscovery*" />
    </packageSource>

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Sep 23, 2025

Choose a reason for hiding this comment

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

These lines have trailing whitespace that should be removed for consistency with project formatting standards.

Suggested change
</packageSource>
</packageSource>

Copilot uses AI. Check for mistakes.
<packageSource key="dotnet-eng">
<package pattern="Microsoft.DotNet.XUnitExtensions" />
</packageSource>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public static IResourceBuilder<OpenTelemetryCollectorResource> AddOpenTelemetryC
var resourceBuilder = builder.AddResource(resource)
.WithImage(settings.CollectorImage, settings.CollectorTag)
.WithEnvironment("ASPIRE_ENDPOINT", new HostUrl(url))
.WithEnvironment("ASPIRE_API_KEY", builder.Configuration[DashboardOtlpApiKeyVariableName]);
.WithEnvironment("ASPIRE_API_KEY", builder.Configuration[DashboardOtlpApiKeyVariableName])
.WithIconName("DesktopPulse");

if (settings.EnableGrpcEndpoint)
resourceBuilder.WithEndpoint(targetPort: 4317, name: OpenTelemetryCollectorResource.GrpcEndpointName, scheme: isHttpsEnabled ? "https" : "http");
Expand Down
1 change: 1 addition & 0 deletions src/Shared/DevCertHostingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public static IResourceBuilder<TResource> RunWithHttpsDevCertificate<TResource>(
exportExecutable = builder.ApplicationBuilder
.AddExecutable(exportResourceName, "dotnet", tempDir.FullName)
.WithEnvironment("DOTNET_CLI_UI_LANGUAGE", "en") // Ensure consistent output language
.WithIconName("Certificate")
.WithArgs(context =>
{
context.Args.Add("dev-certs");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ public void WithReference_WhenAADDisabled_UsesPasswordSecret()

// First check if there are any resources with the annotation
Assert.NotEmpty(resourcesWithAnnotation);

// Now check for a specific resource
var daprStateStore = Assert.Single(appModel.Resources.OfType<IDaprComponentResource>(),
var daprStateStore = Assert.Single(appModel.Resources.OfType<IDaprComponentResource>(),
r => r.Name == "statestore");

// Check there's an annotation on it
Assert.Contains(daprStateStore.Annotations, a => a is AzureDaprComponentPublishingAnnotation);

Expand Down Expand Up @@ -96,15 +96,15 @@ param redisstate_kv_outputs_name string
// Get the actual bicep template and rearrange the ordering if needed
var actualLines = redisBicep.Split(Environment.NewLine);
var expectedLines = expectedRedisBicep.Split(Environment.NewLine);

// Compare the Redis resource configuration which is what we actually care about
var redisResourceSection = string.Join(Environment.NewLine,
actualLines.Where(line => line.Contains("resource redisState") ||
line.Contains("name:") ||
line.Contains("sku:") ||
line.Contains("family:") ||
var redisResourceSection = string.Join(Environment.NewLine,
actualLines.Where(line => line.Contains("resource redisState") ||
line.Contains("name:") ||
line.Contains("sku:") ||
line.Contains("family:") ||
line.Contains("capacity:")));

Assert.Contains("'Microsoft.Cache/redis@2024-11-01'", redisResourceSection);

// Verify that resources with Dapr publishing annotations exist
Expand Down Expand Up @@ -133,11 +133,11 @@ public void WithReference_WhenAADEnabled_SkipsPasswordSecret()

// First check if there are any resources with the annotation
Assert.NotEmpty(resourcesWithAnnotation);

// Now check for a specific resource
var daprStateStore = Assert.Single(appModel.Resources.OfType<IDaprComponentResource>(),
var daprStateStore = Assert.Single(appModel.Resources.OfType<IDaprComponentResource>(),
r => r.Name == "statestore");

// Check there's an annotation on it
Assert.Contains(daprStateStore.Annotations, a => a is AzureDaprComponentPublishingAnnotation);

Expand Down Expand Up @@ -174,6 +174,8 @@ public void WithReference_WhenAADEnabled_SkipsPasswordSecret()

output name string = redisState.name

output hostName string = redisState.properties.hostName

output daprConnectionString string = '${redisState.properties.hostName}:${redisState.properties.sslPort}'
""";

Expand Down Expand Up @@ -210,11 +212,11 @@ public void WithReference_WhenTLSDisabled_UsesNonSslPort()

// First check if there are any resources with the annotation
Assert.NotEmpty(resourcesWithAnnotation);

// Now check for a specific resource
var daprStateStore = Assert.Single(appModel.Resources.OfType<IDaprComponentResource>(),
var daprStateStore = Assert.Single(appModel.Resources.OfType<IDaprComponentResource>(),
r => r.Name == "statestore");

// Check there's an annotation on it
Assert.Contains(daprStateStore.Annotations, a => a is AzureDaprComponentPublishingAnnotation);

Expand Down Expand Up @@ -252,6 +254,8 @@ public void WithReference_WhenTLSDisabled_UsesNonSslPort()

output name string = redisState.name

output hostName string = redisState.properties.hostName

output daprConnectionString string = '${redisState.properties.hostName}:${redisState.properties.port}'
""";

Expand All @@ -271,32 +275,34 @@ public void WithReference_WhenNonStateType_ThrowsException()
using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish);

var redisState = builder.AddAzureRedis("redisState").RunAsContainer();

// The Redis connection should only be used with state store components
var unknownComponent = builder.AddDaprComponent("unknown","component");
var unknownComponent = builder.AddDaprComponent("unknown", "component");

// Create an app with a sidecar that references the unknown component
var appBuilder = builder.AddContainer("myapp", "image")
.WithDaprSidecar(sidecar => {
.WithDaprSidecar(sidecar =>
{
// Reference the unknown component first
sidecar.WithReference(unknownComponent);
});

// Attempting to create a non-state store reference to Redis should throw
var exception = Assert.Throws<InvalidOperationException>(() => {
var exception = Assert.Throws<InvalidOperationException>(() =>
{
unknownComponent.WithReference(redisState);
});

// Verify the exception message contains information about the unsupported component type
Assert.Contains("Unsupported Dapr component", exception.Message, StringComparison.OrdinalIgnoreCase);

// Demonstrate the correct way to reference Redis
var stateStore = builder.AddDaprStateStore("statestore");
stateStore.WithReference(redisState); // This should work correctly

using var app = builder.Build();
}

[Fact]
public void PreferredPattern_ReferencingRedisStateComponent()
{
Expand All @@ -306,31 +312,32 @@ public void PreferredPattern_ReferencingRedisStateComponent()
// Add the Redis state and Dapr state store
var redisState = builder.AddAzureRedis("redisState").RunAsContainer();
var daprState = builder.AddDaprStateStore("statestore");

// Add an app with a sidecar
builder.AddContainer("myapp", "image")
.WithDaprSidecar(sidecar => {
.WithDaprSidecar(sidecar =>
{
// Reference both components through the sidecar
sidecar.WithReference(daprState);
// We can't directly reference Redis from the sidecar due to interface incompatibilities
// This line would fail with a compile error: sidecar.WithReference(redisState);

// We need to first create a Dapr component that references Redis
var anotherState = builder.AddDaprStateStore("anotherstate");
anotherState.WithReference(redisState);
sidecar.WithReference(anotherState);
});

using var app = builder.Build();

var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
var sidecarResource = Assert.Single(appModel.Resources.OfType<IDaprSidecarResource>());

// Check for component reference annotations
var referenceAnnotations = sidecarResource.Annotations
.OfType<DaprComponentReferenceAnnotation>()
.ToList();

Assert.Equal(2, referenceAnnotations.Count);
}
}
Loading