Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 10, 2025

  • Analyze existing RequiredCommandValidator implementation
  • Review annotation system and BeforeResourceStartedEvent usage
  • Understand resource lifecycle and validation patterns
  • Create RequiredCommandAnnotation for declaring required commands on resources
  • Move command resolution logic from RequiredCommandValidator to a reusable utility class (CommandResolver)
  • Create a generic validation service that processes RequiredCommandAnnotation (RequiredCommandValidationLifecycleHook)
  • Hook validation into BeforeResourceStartedEvent via IDistributedApplicationEventingSubscriber
  • Add extension methods for easily adding RequiredCommandAnnotation to resources
  • Write comprehensive tests for the new annotation and validation logic
  • Update DevTunnels to use the new CommandResolver utility
  • Register the lifecycle hook in DistributedApplicationBuilder
  • Verify CommandResolver works correctly via standalone test
  • Verify annotation system works with example application
  • Create comprehensive documentation with examples
  • Build and verify all projects compile successfully
  • Update RequiredCommandValidationLifecycleHook to use IInteractionService for notifications with help links
  • Fix build failures by removing multiple blank lines (IDE2000 violation)
  • Add using statement for cleaner CommandResolver usage

Summary

Successfully implemented a generic required command validation system for Aspire resources using annotations. The solution:

Generic & Reusable: Any resource can declare required commands via RequiredCommandAnnotation
Declarative: Requirements expressed through fluent WithRequiredCommand() API
Extensible: Custom validation callbacks support version checks and other requirements
Non-breaking: Existing RequiredCommandValidator refactored to use new CommandResolver utility
Interactive UI: Uses IInteractionService to show notifications with help links when commands are missing
Well-tested: Comprehensive unit tests for all components
Documented: Full documentation with usage examples
Build clean: No warnings or errors, passes all style checks
Code style: Clean imports and simplified namespace references

The implementation follows Aspire patterns using IResourceAnnotation, IDistributedApplicationEventingSubscriber, and BeforeResourceStartedEvent to validate requirements before resource startup. When a required command is missing or fails validation, the system now shows a user-friendly notification in the UI with installation instructions (if a help link is provided), similar to the existing DevTunnels implementation.

Original prompt

This section details on the original issue you should resolve

<issue_title>Make required command validation generic via resource annotations for orchestrator pre-checks</issue_title>
<issue_description>### Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

Currently, required executable validation is implemented specifically in RequiredCommandValidator, which is closely tied to certain resources that launch processes. However, there are scenarios where a resource (not just an executable resource) may need to declare that certain software is installed and available on the local machine PATH before it can start. There is no generic way for resources to express such requirements, and for the orchestrator to enforce them before starting the resource.

Describe the solution you'd like

Generalize the required command validation logic so that any resource can declare, via annotations, the executables or software it requires to be installed and available on the PATH. The orchestrator should process these annotations in BeforeResourceStart, resolving and checking that the required software is installed before starting the resource. This would involve:

  • Defining a standard annotation format for declaring required commands/software on resources.
  • Refactoring the logic in RequiredCommandValidator to a reusable, generic component.
  • Integrating this validation into the orchestrator's lifecycle, so checks happen before resource start.
  • Ensuring that this is not limited to just executable resources, but can be used by any resource type that needs local software preconditions.

This would make resource requirements more declarative and improve startup reliability for applications with external dependencies.

Additional context

This is a common pattern for executable resources but can apply more broadly. The feature would make Aspire applications more robust and easier to configure, especially for advanced scenarios or custom resources.

https://github.com/dotnet/aspire/blob/6116fd877be6eb20c232cc4b56d925aa212fe822/src/Aspire.Hosting.DevTunnels/RequiredCommandValidator.cs</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #11943


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Make required command validation generic for orchestrator pre-checks Make required command validation generic via resource annotations for orchestrator pre-checks Oct 10, 2025
Copilot AI requested a review from davidfowl October 10, 2025 08:34
Copilot finished work on behalf of davidfowl October 10, 2025 08:34
/// This subscriber processes <see cref="RequiredCommandAnnotation"/> on resources and validates
/// that the specified commands/executables are available on the local machine PATH.
/// </remarks>
internal sealed class RequiredCommandValidationLifecycleHook(
Copy link
Member

Choose a reason for hiding this comment

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

@copilot This should use the interaction service to show the error with the help link etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to use IInteractionService to show notifications with help links, similar to the existing RequiredCommandValidator implementation. The hook now:

  • Injects IInteractionService via constructor
  • Shows a notification with MessageIntent.Warning when a command is missing or fails validation
  • Includes the help link as a clickable "Installation instructions" link in the notification
  • Gracefully handles cases where the interaction service is unavailable

Commit: 7f8aa2a

Copilot AI requested a review from davidfowl October 10, 2025 08:59
Copilot finished work on behalf of davidfowl October 10, 2025 08:59
@github-actions
Copy link
Contributor

github-actions bot commented Oct 11, 2025

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 11944

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 11944"

@DamianEdwards
Copy link
Member

@copilot fix the build failures, I see this error:

/home/runner/work/aspire/aspire/tests/Aspire.Hosting.Tests/CommandResolverTests.cs(3,1): error IDE2000: Avoid multiple blank lines (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2000) [/home/runner/work/aspire/aspire/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj]

}

return null;
return Aspire.Hosting.ApplicationModel.CommandResolver.ResolveCommand(command);
Copy link
Member

Choose a reason for hiding this comment

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

@copilot Add a using statement to import the namespace so you can just do CommandResolver.ResolveCommand(command)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added using Aspire.Hosting.ApplicationModel; statement to simplify the call to CommandResolver.ResolveCommand(command).

Commit: a3b7f91

Copy link
Contributor Author

Copilot AI commented Oct 11, 2025

@copilot fix the build failures, I see this error:

...

Fixed the build failures. Removed the extra blank line in CommandResolverTests.cs that was causing the IDE2000 style violation. Build now succeeds with 0 warnings and 0 errors.

Commit: 5f2c8d9

Copilot finished work on behalf of DamianEdwards October 11, 2025 16:54

private async Task ValidateRequiredCommandsAsync(BeforeResourceStartedEvent @event, CancellationToken cancellationToken)
{
var resource = @event.Resource;
Copy link
Member

Choose a reason for hiding this comment

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

@davidfowl this is currently going to perform this check per required command per resource and will show a separate notification in each case. I think we want to coalesce these the same way it's done in dev tunnels so if multiple resources require the same command you don't get the same notification multiple times. Because resources can start at any time, we can't just do this at a single sync point so we'll likely need to migrate the behavior of CoalescingAsyncOperation and RequiredCommandValidator from dev tunnels too so that you only get a single notification per missing required command at a time, no matter how many starting resources require it.

Copy link
Member

Choose a reason for hiding this comment

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

So you want notificaions based on the command?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I think the command is the logical group by key here? Unless we want to try and do as few concurrent alerts as possible, maybe even just one that shows all required commands and even can be updated while it's still showing?

Copy link
Member

Choose a reason for hiding this comment

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

One might be too much. Information in a single alert and dialog.

Copy link
Member

Choose a reason for hiding this comment

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

Though we do that for parameters …

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.

Make required command validation generic via resource annotations for orchestrator pre-checks

3 participants