Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3346ce8
Show waiting dependency details in dashboard
adamint May 14, 2026
3ac6f77
Add state description actions
adamint May 14, 2026
cec54b4
Use localized strings in state detail tests
adamint May 14, 2026
e9a8191
Refine state description start action
adamint May 14, 2026
f5e6cbb
Add waiting dependency coverage for all wait types
adamint May 14, 2026
3e277f1
Normalize state description punctuation
adamint May 14, 2026
cc42763
Align state description start action
adamint May 14, 2026
0dac353
Make state action fully inline
adamint May 14, 2026
bdbc841
Align inline state action icon
adamint May 14, 2026
0fae2e2
Allow BasketService HTTP health checks
adamint May 14, 2026
3818870
Rename state action to Start anyway
adamint May 14, 2026
39547d0
Include waiting dependencies in wait cancellation
adamint May 14, 2026
86751b5
Address waiting dependency dashboard feedback
adamint May 15, 2026
a1238ec
Address waiting dependency review feedback
adamint May 15, 2026
9c20407
Address waiting dependency review feedback
adamint May 18, 2026
23d6f2a
Merge main into waiting dependency details
adamint May 18, 2026
12452eb
Fix TestShop build after waiting dependency updates
adamint May 18, 2026
00dcf27
Remove manual TestShop start gate
adamint May 18, 2026
3126b2b
Fix waiting dependency property export
adamint May 18, 2026
d05e4da
Preserve structured resource properties in JSON
adamint May 18, 2026
8d13578
Merge remote-tracking branch 'microsoft/main' into dev/adamint/waitin…
adamint May 18, 2026
0679b59
Fix backchannel property test for JSON values
adamint May 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
5 changes: 0 additions & 5 deletions playground/TestShop/BasketService/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@
}
},
"AllowedHosts": "*",
"Kestrel": {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

????

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The removed Kestrel HTTP/2-only default was blocking the new HTTP health check on BasketService. This playground change needs WithHttpHealthCheck("/health", endpointName: "http") so the dashboard can show healthy/starting dependency details for the waiting-state demo.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, but this breaks the basket service. It needs HTTP/2

Image

"EndpointDefaults": {
"Protocols": "Http2"
}
},
"Aspire": {
"RabbitMQ": {
"Client": {
Expand Down
58 changes: 42 additions & 16 deletions playground/TestShop/TestShop.AppHost/AppHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
#endif

var catalogDbApp = builder.AddProject<Projects.CatalogDb>("catalogdbapp")
.WithReference(catalogDb);
.WithReference(catalogDb)
.WaitFor(catalogDb)
.WithHttpHealthCheck("/health");

if (builder.Environment.IsDevelopment() && builder.ExecutionContext.IsRunMode)
{
Expand All @@ -51,6 +53,8 @@

var catalogService = builder.AddProject<Projects.CatalogService>("catalogservice")
.WithReference(catalogDb)
.WaitFor(catalogDb)
.WaitFor(catalogDbApp)
Comment thread
adamint marked this conversation as resolved.
// Modify the endpoint URL
.WithUrlForEndpoint("https", u =>
{
Expand All @@ -65,6 +69,7 @@
})
// Hide the http URL
.WithUrlForEndpoint("http", u => u.DisplayLocation = UrlDisplayLocation.DetailsOnly)
.WithHttpHealthCheck("/health")
.WithReplicas(2);

var messaging = builder.AddRabbitMQ("messaging")
Expand All @@ -73,32 +78,53 @@
.WithManagementPlugin()
.PublishAsContainer();

// Test-only manual gate for dashboard waiting-state UX. It never starts automatically,
// so dependents stay in Waiting until the resource is explicitly started from the dashboard.
var manualStartGate = builder.AddContainer("manualstartgate", "alpine")
.WithEntrypoint("sleep")
.WithArgs("3600")
.WithExplicitStart();

var basketService = builder.AddProject("basketservice", @"..\BasketService\BasketService.csproj")
.WithReference(basketCache)
.WithReference(messaging).WaitFor(messaging);
.WaitFor(basketCache)
.WithReference(messaging)
.WaitFor(messaging)
.WithHttpHealthCheck("/health", endpointName: "http");

var frontend = builder.AddProject<Projects.MyFrontend>("frontend")
.WithExternalHttpEndpoints()
.WithReference(basketService)
.WithReference(catalogService)
// Modify the display text of the URLs
.WithUrls(c => c.Urls.ForEach(u => u.DisplayText = $"Online store ({u.Endpoint?.EndpointName})"))
// Don't show the non-HTTPS link on the resources page (details only)
.WithUrlForEndpoint("http", url => url.DisplayLocation = UrlDisplayLocation.DetailsOnly)
// Add health relative URL (show in details only)
.WithUrlForEndpoint("https", ep => new() { Url = "/health", DisplayText = "Health", DisplayLocation = UrlDisplayLocation.DetailsOnly })
.WithHttpHealthCheck("/health");
.WithExternalHttpEndpoints()
.WaitForStart(manualStartGate)
.WithReference(basketService)
.WaitFor(basketService)
.WithReference(catalogService)
.WaitFor(catalogService)
// Modify the display text of the URLs
.WithUrls(c => c.Urls.ForEach(u => u.DisplayText = $"Online store ({u.Endpoint?.EndpointName})"))
// Don't show the non-HTTPS link on the resources page (details only)
.WithUrlForEndpoint("http", url => url.DisplayLocation = UrlDisplayLocation.DetailsOnly)
// Add health relative URL (show in details only)
.WithUrlForEndpoint("https", ep => new() { Url = "/health", DisplayText = "Health", DisplayLocation = UrlDisplayLocation.DetailsOnly })
.WithHttpHealthCheck("/health");

builder.AddProject<Projects.OrderProcessor>("orderprocessor", launchProfileName: "OrderProcessor")
.WithReference(messaging).WaitFor(messaging);
.WithReference(messaging)
.WaitFor(messaging);

#if YARP_USE_CONFIG_FILE
builder.AddYarp("apigateway")
.WithConfigFile("yarp.json")
.WithReference(basketService)
.WithReference(catalogService);
.WithConfigFile("yarp.json")
.WithReference(basketService)
.WaitFor(basketService)
.WithReference(catalogService)
.WaitFor(catalogService);
#else
var yarp = builder.AddYarp("apigateway");
yarp.WithReference(basketService)
.WaitFor(basketService)
.WithReference(catalogService)
.WaitFor(catalogService);

yarp.WithConfiguration(builder =>
{
// catalog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ protected override void OnParametersSet()
{
Type = typeof(ResourceHealthStateValue),
Parameters = { ["Resource"] = _resource }
},
}
};

// For parameter resources whose value is unset, render the same "Value not set" affordance
Expand All @@ -225,7 +225,7 @@ protected override void OnParametersSet()
Parameters =
{
["Resource"] = _resource,
["OnExecuteCommandAsync"] = (Func<ResourceViewModel, CommandViewModel, Task>)ExecuteParameterCommandAsync,
["OnExecuteCommandAsync"] = (Func<ResourceViewModel, CommandViewModel, Task>)ExecuteResourceCommandAsync,
["IsCommandExecuting"] = IsCommandExecuting,
}
};
Expand Down Expand Up @@ -307,10 +307,11 @@ private void UpdateResourceActionsMenu()
IsCommandExecuting,
showViewDetails: false,
showConsoleLogsItem: true,
showUrls: true);
showUrls: true,
showStartCommand: false);
}

private async Task ExecuteParameterCommandAsync(ResourceViewModel resource, CommandViewModel command)
private async Task ExecuteResourceCommandAsync(ResourceViewModel resource, CommandViewModel command)
{
await CommandSelected.InvokeAsync(command);
}
Expand Down
8 changes: 5 additions & 3 deletions src/Aspire.Dashboard/Model/ResourceMenuBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ public void AddMenuItems(
Func<ResourceViewModel, CommandViewModel, bool> isCommandExecuting,
bool showViewDetails,
bool showConsoleLogsItem,
bool showUrls)
bool showUrls,
bool showStartCommand = true)
{
if (showViewDetails)
{
Expand Down Expand Up @@ -165,7 +166,7 @@ await _aiContextProvider.LaunchAssistantSidebarAsync(

AddTelemetryMenuItems(menuItems, resource, resourceByName);

AddCommandMenuItems(menuItems, resource, commandSelected, isCommandExecuting);
AddCommandMenuItems(menuItems, resource, commandSelected, isCommandExecuting, showStartCommand);

if (showUrls)
{
Expand Down Expand Up @@ -282,9 +283,10 @@ private void AddTelemetryMenuItems(List<MenuButtonItem> menuItems, ResourceViewM
}
}

private void AddCommandMenuItems(List<MenuButtonItem> menuItems, ResourceViewModel resource, EventCallback<CommandViewModel> commandSelected, Func<ResourceViewModel, CommandViewModel, bool> isCommandExecuting)
private void AddCommandMenuItems(List<MenuButtonItem> menuItems, ResourceViewModel resource, EventCallback<CommandViewModel> commandSelected, Func<ResourceViewModel, CommandViewModel, bool> isCommandExecuting, bool showStartCommand)
{
var menuCommands = resource.Commands
.Where(c => showStartCommand || !c.Name.Equals(CommandViewModel.StartCommand, StringComparisons.CommandName))
Comment thread
adamint marked this conversation as resolved.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why is this still here? The start command is not added to the menu:

Image

.Where(c => c.State != CommandViewModelState.Hidden)
.ToList();

Expand Down
5 changes: 5 additions & 0 deletions src/Aspire.Dashboard/Model/ResourceStateViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ internal static string GetResourceStateTooltip(ResourceViewModel resource, IStri
}
else if (resource.IsWaiting())
{
if (resource.TryGetWaitingForDependencies(out var dependencies))
{
return loc.GetString(nameof(Columns.StateColumnResourceWaitingFor), string.Join(", ", dependencies));
}

return loc[nameof(Columns.StateColumnResourceWaiting)];
}
else if (resource.IsNotStarted())
Expand Down
5 changes: 5 additions & 0 deletions src/Aspire.Dashboard/Model/ResourceViewModelExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ public static bool TryGetAppArgsSensitivity(this ResourceViewModel resource, out
return resource.TryGetCustomDataBoolArray(KnownProperties.Resource.AppArgsSensitivity, out argParams);
}

public static bool TryGetWaitingForDependencies(this ResourceViewModel resource, out ImmutableArray<string> dependencies)
{
return resource.TryGetCustomDataStringArray(KnownProperties.Resource.WaitingFor, out dependencies) && dependencies.Length > 0;
}

private static bool TryGetCustomDataString(this ResourceViewModel resource, string key, [NotNullWhen(returnValue: true)] out string? s)
{
if (resource.Properties.TryGetValue(key, out var property) && property.Value.TryConvertToString(out var valueString))
Expand Down
21 changes: 15 additions & 6 deletions src/Aspire.Dashboard/Resources/Columns.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 10 additions & 6 deletions src/Aspire.Dashboard/Resources/Columns.resx
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,15 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="StateColumnResourceExitedUnexpectedly" xml:space="preserve">
<value>{0} exited unexpectedly with exit code {1}</value>
<value>{0} exited unexpectedly with exit code {1}.</value>
<comment>{0} is a resource type, {1} is a number</comment>
</data>
<data name="StateColumnResourceExited" xml:space="preserve">
<value>{0} is no longer running</value>
<value>{0} is no longer running.</value>
<comment>{0} is a resource type</comment>
</data>
<data name="StateColumnResourceFailedToStart" xml:space="preserve">
<value>{0} failed to start</value>
<value>{0} failed to start.</value>
<comment>{0} is a resource type</comment>
</data>
<data name="SourceColumnDisplayCopyCommandToClipboard" xml:space="preserve">
Expand Down Expand Up @@ -155,13 +155,17 @@
</data>
<data name="StateColumnResourceContainerRuntimeUnhealthy" xml:space="preserve">
<value>Container runtime was found but appears to be unhealthy. Ensure that it is running.
For more information, see https://aka.ms/aspire/container-runtime-unhealthy</value>
For more information, see https://aka.ms/aspire/container-runtime-unhealthy.</value>
<comment>Contains a new line</comment>
</data>
<data name="StateColumnResourceNotStarted" xml:space="preserve">
<value>Resource has not started because it's configured to not automatically start.</value>
<value>Resource is not configured to start automatically.</value>
</data>
<data name="StateColumnResourceWaiting" xml:space="preserve">
<value>Resource is waiting for other resources to be in a running and healthy state.</value>
<value>Resource is waiting for dependencies.</value>
</data>
<data name="StateColumnResourceWaitingFor" xml:space="preserve">
<value>Waiting for dependencies: {0}.</value>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Don't put fullstop in messages than end with :

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: The period after {0} reads awkwardly because the interpolated value is a list following a colon (e.g., "Waiting for dependencies: nginx, redis."). Consider removing the trailing period: "Waiting for dependencies: {0}".

<comment>{0} is a comma-separated list of dependency resource names.</comment>
</data>
</root>

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 16 additions & 11 deletions src/Aspire.Dashboard/Resources/xlf/Columns.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading