microsoft / microsoft/aspire

ExplicitStartupAnnotation added post-hoc to project resources is ignored during StartAsync

Open
#14,518 0 comments 0 reactions 0 assignees View on GitHub
area-app-testing
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.