Skip to content

Proposal: Allow Extensions to Define Local Preflight Checks #7832

Description

@vhvb1989

Proposal: Allow Extensions to Define Local Preflight Checks

Summary

This proposal introduces a mechanism for azd extensions to register local preflight checks that azd core runs alongside its own checks before Bicep provisioning. Extension check results are merged into the unified PreflightReport, giving extensions access to the same warning/error/abort UX flow and the rich validation context (Bicep snapshot, resource properties) that core checks use.

This is a continuation of #7053, which established the local preflight validation infrastructure.

Problem

Today, extensions that need to validate deployment preconditions before provisioning have limited options:

  1. preprovision event handler — Can only return an error (blocking failure) or succeed silently. There is no way to produce warnings that let the user decide whether to proceed.

  2. Init-time validation — Extensions like azure.ai.agents validate manifests during azd agent init, but this happens long before provisioning and cannot inspect the deployment's predicted resource graph.

  3. Mimicking the warning UX — Extensions can try to replicate the preflight warning-then-prompt pattern, but the result is inconsistent with core's UX, duplicates logic, and doesn't integrate with telemetry.

None of these approaches give extensions access to the validation context that azd core generates during preflight — the Bicep snapshot (fully resolved resource graph), deployment scope, resource properties, or the consolidated PreflightReport.

Benefits

Benefit Description
Unified UX Extension warnings and errors appear in the same PreflightReport as core checks — consistent user experience
Rich context access Extensions can inspect the full predicted resource graph (Bicep snapshot), deployment scope, and derived resource properties
User control Warnings prompt the user for continuation; errors block — same behavior as core checks
Concurrent execution Core runs extension checks alongside its own checks — no sequential bottleneck
Extension composability Multiple extensions can independently contribute checks without coordinating
Telemetry integration Extension diagnostic IDs flow through the same telemetry pipeline as core diagnostics
Delegation to core Extensions don't need to implement their own warning/prompt/abort logic — they declare findings and core handles the UX

Proposed Design

Scope

This proposal targets Bicep-based deployments exclusively. All current core extensions use Bicep, and the preflight infrastructure from #7053 is Bicep-specific.

New Extension Capability: preflight-checks

Extensions declare the capability in extension.yaml:

capabilities:
  - preflight-checks

Extension-Side API

Extensions register preflight checks through the extension host, similar to how they register service targets or event handlers:

host := azdext.NewExtensionHost(azdClient).
    WithPreflightCheck("agent-manifest-validation", func(ctx context.Context, args *azdext.PreflightCheckArgs) (*azdext.PreflightCheckResult, error) {
        // Access the Bicep snapshot resources
        for _, res := range args.SnapshotResources {
            if strings.EqualFold(res.Type, "Microsoft.MachineLearningServices/workspaces") {
                // Validate extension-specific requirements
                if !hasRequiredConfig(res) {
                    return &azdext.PreflightCheckResult{
                        Severity:     azdext.PreflightWarning,
                        DiagnosticID: "azure.ai.agents/missing-workspace-config",
                        Message:      "AI workspace is missing required identity configuration.",
                    }, nil
                }
            }
        }
        return nil, nil // all good
    })

gRPC Contract

New proto messages for the preflight request/response:

message PreflightCheckRequest {
  // Deployment scope information
  string subscription_id = 1;
  string resource_group = 2;
  string location = 3;

  // Bicep snapshot: fully resolved predicted resources
  bytes snapshot_resources_json = 4;

  // Derived resource properties
  ResourceProperties properties = 5;
}

message PreflightCheckResponse {
  // nil/empty = check passed
  repeated PreflightCheckResultItem results = 1;
}

message PreflightCheckResultItem {
  string diagnostic_id = 1;     // e.g. "azure.ai.agents/missing-config"
  PreflightSeverity severity = 2; // WARNING or ERROR
  string message = 3;
}

enum PreflightSeverity {
  PREFLIGHT_WARNING = 0;
  PREFLIGHT_ERROR = 1;
}

message ResourceProperties {
  bool has_role_assignments = 1;
  // Extensible for future derived properties
}

Core-Side Integration

In BicepProvider.validatePreflight():

  1. Discover extensions that declare the preflight-checks capability
  2. Send the PreflightCheckRequest with snapshot resources and deployment scope to each extension
  3. Run extension checks concurrently with core checks (with a timeout)
  4. Merge extension PreflightCheckResultItems into the PreflightReport alongside core results
  5. Apply the same UX flow: warnings prompt, errors block
azd provision
  ├── Compile Bicep module → ARM template + parameters
  ├── ► Local preflight validation
  │     ├── Generate Bicep snapshot
  │     ├── Analyze resources (derive properties)
  │     ├── Run core checks (e.g., role_assignment_permissions)
  │     ├── Run extension checks (concurrent, gRPC)    ← NEW
  │     │     ├── Extension A: preflight check results
  │     │     └── Extension B: preflight check results
  │     └── Merge all results into PreflightReport
  │           ├── Warnings → prompt user
  │           └── Errors → abort
  ├── Server-side preflight (Azure ValidatePreflight API)
  └── Deploy

Example: AI Agents Extension

The azure.ai.agents extension could use this to validate:

  • Agent manifest references match predicted resources in the Bicep snapshot
  • Required identity/RBAC configuration is present for AI workspaces
  • Required dependent services (e.g., Azure OpenAI, Bing Search) are included in the deployment

Instead of failing during deploy or relying on init-time checks, these validations would surface as warnings before the user commits to a potentially long provisioning operation.

Relationship to #7053

This proposal builds directly on the preflight infrastructure established in #7053:

  • The PreflightCheck / PreflightCheckFn / validationContext pattern is the foundation
  • The PreflightReport UX component handles the merged output
  • The warning/error/abort flow and exit code behavior remain unchanged
  • No breaking changes to existing preflight behavior — this is purely additive

The key change is extending the check registration from internal-only (localPreflight.AddCheck()) to include extension-contributed checks via gRPC.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or improvement

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions