ExplicitStartupAnnotation added post-hoc to project resources is ignored during StartAsync
- Dominant language
- C#
- Stars
- 6.3k
- Forks
- 991
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 196
Description
## Description
When using `DistributedApplicationTestingBuilder`, `ExplicitStartupAnnotation` does not work correctly for project resources when `WaitAnnotation`s are also present. Specifically:
1. Adding `ExplicitStartupAnnotation` to project resources **after** `CreateAsync` but **before** `BuildAsync` does not prevent those resources from starting when `StartAsync()` is called.
2. Even when `WithExplicitStart()` is applied **during module configuration**, if the project resource also has `WaitFor` annotations pointing to other resources, the `ExplicitStart` behavior is undermined — the project either starts automatically or hangs.
Container resources (Kafka, Redis, Azurite) respect `ExplicitStartupAnnotation` correctly in all cases.
## Steps to Reproduce
### Scenario 1: Post-hoc ExplicitStart (ignored entirely for projects)
```csharp
var builder = await DistributedApplicationTestingBuilder.CreateAsync();
// Add ExplicitStartupAnnotation to ALL resources post-hoc
foreach (var resource in builder.Resources) {
if (!resource.Annotations.OfType().Any()) {
resource.Annotations.Add(new ExplicitStartupAnnotation());
}
}
var app = await builder.BuildAsync();
await app.StartAsync();
// EXPECTED: No resources start automatically
// ACTUAL: Project resources start anyway; container resources correctly remain stopped
```
### Scenario 2: WithExplicitStart during configuration + WaitFor (conflict)
```csharp
// In module configuration:
var api = builder.AddProject("my-api")
.WaitFor(someInfraResource) // e.g., Redis, Storage, etc.
.WithExplicitStart(); // Applied during configuration
// In test:
var app = await builder.BuildAsync();
await app.StartAsync();
// EXPECTED: "my-api" should NOT start until explicitly commanded
// ACTUAL: Project starts or hangs — WaitFor + ExplicitStart don't compose correctly
```
## Expected Behavior
- `ExplicitStartupAnnotation` added post-hoc (before `BuildAsync`) should be respected for all resource types.
- `WithExplicitStart()` and `WaitFor()` should compose correctly — the resource should remain stopped until explicitly started, regardless of WaitFor dependencies.
## Actual Behavior
- **Container resources**: `ExplicitStart` works correctly in all cases.
- **Project resources with post-hoc annotation**: Annotation is ignored — resources start automatically.
- **Project resources with `WithExplicitStart()` + `WaitFor()`**: Resources start or hang — the two annotations conflict.
## Workaround
Strip `WaitAnnotation`s from project resources in the test host and manage dependency ordering manually:
```csharp
foreach (var resource in builder.Resources) {
// Add ExplicitStart to everything
if (!resource.Annotations.OfType().Any()) {
resource.Annotations.Add(new ExplicitStartupAnnotation());
}
// Strip WaitFor from project resources to prevent conflicts
if (resource is ProjectResource) {
var waits = resource.Annotations.OfType().ToList();
foreach (var wait in waits) {
resource.Annotations.Remove(wait);
}
}
}
```
Then in the test lifecycle manager, start non-project resources (infrastructure) first, then project resources.
## Environment
- .NET 9
- Aspire 9.2
- Windows 11
- Using `DistributedApplicationTestingBuilder` for integration tests
## Additional Context
Discovered while implementing selective resource startup for integration tests. The goal: mark all resources as explicit-start, then selectively start only what each test needs. This pattern works for containers but requires the WaitAnnotation-stripping workaround for project resources.
Contributor guide
Assessment
This issue has not been assessed yet.