Skip to content

Add pre-tool-validation lifecycle event for extensions #6424

@spboyer

Description

@spboyer

Extensions cannot provide guidance or suggestions when required tool validation fails because lifecycle events fire after EnsureAllTools() completes successfully. This creates a catch-22 where extensions that want to suggest alternatives (like remote build when Docker is unavailable) never get the opportunity to run.

Current Execution Order

1. Initialize
2. EnsureAllTools() ← Fails if Docker daemon not running
3. [COMMAND EXITS WITH ERROR]
4. Lifecycle events (prepackage, preprovision, predeploy) ← Never reached

Example Use Case

The azd-ext-doctor extension aims to suggest enabling remote build when Docker daemon is unavailable:

func onPrePackage(ctx context.Context, args *azdext.ServiceEventArgs) error {
    // Check if Docker required but not running
    // Suggest: azd doctor configure remote-build
    // But this never executes because EnsureAllTools fails first
}

Current behavior: User runs azd package with Docker daemon stopped → immediate error
Desired behavior: Extension suggests remote build alternative before failing

Proposed Solution

Add a new lifecycle event that fires before tool validation, allowing extensions to:

  • Inspect required tools
  • Provide suggestions for missing/unavailable tools
  • Offer configuration alternatives
  • Guide users through remediation

Suggested Event Names (choose one)

  • pretoolcheck - Fires before EnsureAllTools()
  • preinit - Fires at the very beginning of command execution
  • toolcheck - Fires with tool validation context

Example Extension Usage

host.WithProjectEventHandler("pretoolcheck", func(ctx context.Context, args *azdext.ProjectEventArgs) error {
    // Extension can inspect required tools
    requiredTools := args.RequiredTools
    
    for _, tool := range requiredTools {
        if tool.Name == "docker" && !isDockerDaemonRunning() {
            fmt.Fprintln(os.Stderr, "💡 Tip: Enable remote build to build without local Docker")
            fmt.Fprintln(os.Stderr, "Run: azd doctor configure remote-build")
        }
    }
    
    return nil
})

Modified Execution Order

1. Initialize
2. → NEW: Fire pretoolcheck lifecycle event ← Extensions can provide guidance
3. EnsureAllTools() ← Fails if tools missing/unavailable
4. Lifecycle events (prepackage, preprovision, predeploy)

Benefits

  1. Better UX: Users get actionable suggestions before seeing cryptic tool errors
  2. Extension Capabilities: Extensions can provide domain-specific guidance
  3. Graceful Degradation: Extensions can suggest workarounds (remote build, alternative tools, etc.)
  4. Proactive Help: Catch tool issues early with helpful context

Related Code Locations

Alternative Considered

Extensions could use standalone commands (like azd doctor check), but this:

  • Requires users to know about the extension
  • Adds extra manual steps
  • Doesn't integrate with normal azd up/package/deploy workflows
  • Loses context about which command the user actually wanted to run

Implementation Notes

The event should provide:

  • List of required tools for the operation
  • Service/project context
  • Ability to output to stderr without disrupting normal flow
  • Should NOT block tool validation (run even if extension errors)

Real-World Impact

The azd-ext-doctor extension (https://github.com/spboyer/azd-ext-doctor) would immediately benefit from this feature, providing users with actionable suggestions when tools are unavailable, improving the developer experience significantly.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions