Skip to content

Conversation

@kristremblay
Copy link
Contributor

Closes #1073

  • Adds WaitAnnotation propagation to both Dapr sidecar and CLI

PR Checklist

  • Created a feature/dev branch in your fork (vs. submitting directly from a commit on main)
  • Based off latest main branch of toolkit
  • PR doesn't include merge commits (always rebase on top of our main, if needed)
  • Tests for the changes have been added (for bug fixes / features) (if applicable)
  • Contains NO breaking changes
  • Code follows all style conventions

@kristremblay
Copy link
Contributor Author

@dotnet-policy-service agree

@kristremblay kristremblay marked this pull request as ready for review December 30, 2025 04:03
Copilot AI review requested due to automatic review settings December 30, 2025 04:03
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds WaitAnnotation propagation from resources to their Dapr sidecars and CLI components, ensuring that dependencies specified with .WaitFor() are properly respected by Dapr infrastructure. This addresses issue #1073.

Key Changes

  • Lifecycle hook now propagates WaitAnnotations from parent resources to Dapr sidecar resources
  • Lifecycle hook now propagates WaitAnnotations from parent resources to Dapr CLI executable resources
  • Added comprehensive unit tests covering scenarios with no WaitAnnotations, single WaitAnnotation, and multiple WaitAnnotations

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/CommunityToolkit.Aspire.Hosting.Dapr/DaprDistributedApplicationLifecycleHook.cs Added WaitAnnotation propagation logic at lines 64-71 (sidecar) and 216-223 (CLI) to copy wait dependencies from parent resources
tests/CommunityToolkit.Aspire.Hosting.Dapr.Tests/WithDaprSidecarTests.cs Removed unused import and added three unit tests to verify WaitAnnotation handling in different scenarios

Comment on lines +114 to +180
[Fact]
public void ResourceWithDaprSidecarAndNoWaitAnnotations_CreatesBasicSidecar()
{
var builder = DistributedApplication.CreateBuilder();

var app = builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceA>("test")
.WithDaprSidecar();

// Verify no wait annotations on the main resource
Assert.Empty(app.Resource.Annotations.OfType<WaitAnnotation>());

// Verify the sidecar resource exists
var sidecarResource = Assert.Single(builder.Resources.OfType<DaprSidecarResource>());

// Verify the sidecar is properly linked
var sidecarAnnotation = Assert.Single(app.Resource.Annotations.OfType<DaprSidecarAnnotation>());
Assert.Equal(sidecarResource, sidecarAnnotation.Sidecar);
}

[Fact]
public void ResourceWithWaitAnnotationAndDaprSidecar_SetsUpCorrectDependencies()
{
var builder = DistributedApplication.CreateBuilder();

var database = builder.AddContainer("db", "postgres");

var app = builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceA>("test")
.WaitFor(database)
.WithDaprSidecar();

// Verify the main resource has the wait annotation
var waitAnnotation = Assert.Single(app.Resource.Annotations.OfType<WaitAnnotation>());
Assert.Equal("db", waitAnnotation.Resource.Name);

// Verify the sidecar resource exists
var sidecarResource = Assert.Single(builder.Resources.OfType<DaprSidecarResource>());
Assert.NotNull(sidecarResource);

// The actual propagation happens in the lifecycle hook, but we can verify the setup is correct
var sidecarAnnotation = Assert.Single(app.Resource.Annotations.OfType<DaprSidecarAnnotation>());
Assert.Equal(sidecarResource, sidecarAnnotation.Sidecar);
}

[Fact]
public void ResourceWithMultipleWaitAnnotationsAndDaprSidecar_HasAllWaitDependencies()
{
var builder = DistributedApplication.CreateBuilder();

var database = builder.AddContainer("db", "postgres");
var redis = builder.AddContainer("cache", "redis");

var app = builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceA>("test")
.WaitFor(database)
.WaitFor(redis)
.WithDaprSidecar();

// Verify the main resource has both wait annotations
var waitAnnotations = app.Resource.Annotations.OfType<WaitAnnotation>().ToList();
Assert.Equal(2, waitAnnotations.Count);
Assert.Contains(waitAnnotations, w => w.Resource.Name == "db");
Assert.Contains(waitAnnotations, w => w.Resource.Name == "cache");

// Verify the sidecar resource exists and is properly linked
var sidecarResource = Assert.Single(builder.Resources.OfType<DaprSidecarResource>());
var sidecarAnnotation = Assert.Single(app.Resource.Annotations.OfType<DaprSidecarAnnotation>());
Assert.Equal(sidecarResource, sidecarAnnotation.Sidecar);
}
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

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

The tests verify the setup of WaitAnnotations on the main resource but do not verify that these annotations are actually propagated to the Dapr sidecar and CLI resources during lifecycle hook execution. Consider adding an integration test that calls app.Build() and app.StartAsync() to verify that the lifecycle hook properly propagates WaitAnnotations to the sidecar and CLI resources. This would ensure the propagation logic works as expected at runtime.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@FullStackChef FullStackChef left a comment

Choose a reason for hiding this comment

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

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WithDaprSidecar doesn't mimic WaitFor on its parent resource

2 participants