### Basic Extension Manifest Example Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md A minimal example of an extension manifest file for getting started. ```yaml ``` -------------------------------- ### Platform-Specific Configuration Example Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Example of providing platform-specific metadata for different operating systems, including executables and install scripts. ```yaml platforms: windows: executable: myext.exe installScript: install.ps1 linux: executable: myext installScript: install.sh darwin: executable: myext installScript: install.sh ``` -------------------------------- ### Complete Container Workflow Example (Go) Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md This example demonstrates a full container workflow: building, packaging, and publishing a service's container image. It shows how to chain these operations and update the service context with artifacts from each step. ```go ctx := azdext.WithAccessToken(cmd.Context()) azdClient, err := azdext.NewAzdClient() if err != nil { return fmt.Errorf("failed to create azd client: %w", err) } def azdClient.Close() serviceName := "web-api" serviceContext := &azdext.ServiceContext{} // Build the container buildResp, err := azdClient.Container().Build(ctx, &azdext.ContainerBuildRequest{ ServiceName: serviceName, ServiceContext: serviceContext, }) if err != nil { return fmt.Errorf("container build failed: %w", err) } // Update context with build artifacts serviceContext.Build = buildResp.Result.Artifacts // Package the container packageResp, err := azdClient.Container().Package(ctx, &azdext.ContainerPackageRequest{ ServiceName: serviceName, ServiceContext: serviceContext, }) if err != nil { return fmt.Errorf("container package failed: %w", err) } // Update context with package artifacts serviceContext.Package = packageResp.Result.Artifacts // Publish the container publishResp, err := azdClient.Container().Publish(ctx, &azdext.ContainerPublishRequest{ ServiceName: serviceName, ServiceContext: serviceContext, }) if err != nil { return fmt.Errorf("container publish failed: %w", err) } fmt.Printf("Container published successfully with %d artifacts\n", len(publishResp.Result.Artifacts)) ``` -------------------------------- ### Complete Extension Host Builder Example Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md This example demonstrates registering various extension capabilities including custom service targets, framework services, and project/service event handlers using the ExtensionHost builder pattern. It's the recommended approach for extension development. ```go func newListenCommand() *cobra.Command { return &cobra.Command{ Use: "listen", Short: "Starts the extension and listens for events.", RunE: func(cmd *cobra.Command, args []string) error { // Create a new context that includes the azd access token. ctx := azdext.WithAccessToken(cmd.Context()) // Create a new azd client. azdClient, err := azdext.NewAzdClient() if err != nil { return fmt.Errorf("failed to create azd client: %w", err) } defer azdClient.Close() // Register all extension capabilities using the builder pattern host := azdext.NewExtensionHost(azdClient). // Register a custom service target for specialized deployments WithServiceTarget("demo", func() azdext.ServiceTargetProvider { return project.NewDemoServiceTargetProvider(azdClient) }). // Register a custom framework service for language support WithFrameworkService("rust", func() azdext.FrameworkServiceProvider { return project.NewDemoFrameworkServiceProvider(azdClient) }). // Register project-level event handlers WithProjectEventHandler("preprovision", func(ctx context.Context, args *azdext.ProjectEventArgs) error { fmt.Printf("Preparing provisioning for project: %s\n", args.Project.Name) // Perform pre-provisioning logic return nil }). WithProjectEventHandler("predeploy", func(ctx context.Context, args *azdext.ProjectEventArgs) error { fmt.Printf("Preparing deployment for project: %s\n", args.Project.Name) // Perform pre-deployment validation return nil }). WithProjectEventHandler("postdeploy", func(ctx context.Context, args *azdext.ProjectEventArgs) error { fmt.Printf("Deployment completed for project: %s\n", args.Project.Name) // Perform post-deployment tasks (e.g., health checks, notifications) return nil }). // Register service-level event handlers with optional filtering WithServiceEventHandler("prepackage", func(ctx context.Context, args *azdext.ServiceEventArgs) error { fmt.Printf("Packaging service: %s\n", args.Service.Name) // Access artifacts from previous phases if len(args.ServiceContext.Build) > 0 { fmt.Printf("Found %d build artifacts\n", len(args.ServiceContext.Build)) } return nil }, nil). // No filtering - applies to all services WithServiceEventHandler("postpackage", func(ctx context.Context, args *azdext.ServiceEventArgs) error { fmt.Printf("Package completed for service: %s\n", args.Service.Name) // Check package artifacts for _, artifact := range args.ServiceContext.Package { fmt.Printf("Package artifact: %s\n", artifact.Path) } return nil }, &azdext.ServiceEventOptions{ // Optional: Filter to only handle specific service types Host: "containerapp", Language: "python", }) // Start the extension host - this blocks until shutdown if err := host.Run(ctx); err != nil { return fmt.Errorf("failed to run extension: %w", err) } return nil }, } } ``` -------------------------------- ### Daily Build Version String Example Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/design/azd-update.md Example of a version string for daily builds, including a monotonically increasing build number for comparison. ```text 1.24.0-beta.1-daily.5935787 ``` -------------------------------- ### Complete Extension Manifest Example Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md A comprehensive example of an extension manifest file, showcasing all possible properties and configurations. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/refs/heads/main/cli/azd/extensions/extension.schema.json id: microsoft.azd.demo namespace: demo displayName: Demo Extension description: This extension provides examples of the azd extension framework. usage: azd demo [options] version: 0.1.0 entryPoint: demo capabilities: - custom-commands - lifecycle-events - service-target-provider - framework-service-provider - mcp-server - metadata examples: - name: context description: Displays the current azd project & environment context. usage: azd demo context - name: prompt description: Display prompt capabilities. usage: azd demo prompt - name: deploy-vm description: Deploy application to virtual machine using custom service target. usage: azd demo deploy-vm tags: - demo - example - development dependencies: - id: microsoft.azd.core version: "^1.0.0" providers: - name: demo-vm type: service-target description: Custom VM deployment target for demonstration purposes - name: rust-framework type: framework-service description: Custom Rust language framework support platforms: windows: executable: demo.exe linux: executable: demo darwin: executable: demo mcp: serve: args: ["mcp", "serve"] env: ["DEMO_CONFIG=production"] ``` -------------------------------- ### Usage Example for NewExtensionRootCommand Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-sdk-reference.md Demonstrates how to create a root command, add subcommands, and run the extension using azdext.Run. ```go rootCmd, extCtx := azdext.NewExtensionRootCommand(azdext.ExtensionCommandOptions{ Name: "my-extension", Version: "1.0.0", Short: "My custom azd extension", }) // Add subcommands rootCmd.AddCommand(newServeCommand(extCtx)) azdext.Run(rootCmd) ``` -------------------------------- ### Extension Manifest Example (YAML) Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md An example of an extension manifest file in YAML format, defining extension metadata, capabilities, and examples. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/refs/heads/main/cli/azd/extensions/extension.schema.json id: microsoft.azd.demo namespace: demo displayName: Demo Extension description: This extension provides examples of the azd extension framework. usage: azd demo [options] version: 0.1.0 capabilities: - custom-commands - lifecycle-events examples: - name: context description: Displays the current `azd` project & environment context. usage: azd demo context - name: prompt description: Display prompt capabilities. usage: azd demo prompt ``` ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/refs/heads/main/cli/azd/extensions/extension.schema.json id: microsoft.azd.demo namespace: demo displayName: Demo Extension description: This extension provides examples of the azd extension framework. usage: azd demo [options] version: 0.6.0 language: go capabilities: - custom-commands - lifecycle-events - mcp-server - service-target-provider - framework-service-provider - metadata providers: - name: demo type: service-target description: Deploys application components to demo examples: - name: context description: Displays the current `azd` project & environment context. usage: azd demo context - name: prompt description: Display prompt capabilities. usage: azd demo prompt ``` -------------------------------- ### Usage Example for NewListenCommand Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-sdk-reference.md Shows how to add a 'listen' command to the root command, configuring service targets and event handlers. ```go rootCmd.AddCommand(azdext.NewListenCommand(func(host *azdext.ExtensionHost) { host.WithServiceTarget("myhost", func() azdext.ServiceTargetProvider { return &MyProvider{} }) host.WithProjectEventHandler("preprovision", myHandler) })) ``` -------------------------------- ### Install Extension from a Specific Source Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-resolution-and-versioning.md When an extension exists in multiple sources, specify the exact source to use during installation. ```bash azd extension install --source ``` -------------------------------- ### Install Extension Without Recording Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/recording-functional-tests-guide.md This Go code demonstrates installing an extension using the azd CLI without enabling recording. This is part of a partial recording strategy where setup steps are not recorded. ```go // Install extension without recording cliNoSession := azdcli.NewCLI(t) _, err := cliNoSession.RunCommand(ctx, "ext", "install", "...") ``` -------------------------------- ### ResourceNotAvailableHandler Implementation Example Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/error-suggestions.md Example implementation of the ResourceNotAvailableHandler. It extracts resource type, queries available regions, and builds a suggestion. ```go func (h *ResourceNotAvailableHandler) Handle(ctx context.Context, err error) *ErrorWithSuggestion { location := os.Getenv("AZURE_LOCATION") subscriptionID := os.Getenv("AZURE_SUBSCRIPTION_ID") resourceType := extractResourceType(err.Error()) // e.g. "Microsoft.Web/staticSites" var availableLocations []string if resourceType != "" && subscriptionID != "" && h.locationResolver != nil { availableLocations, _ = h.locationResolver.GetLocations(ctx, subscriptionID, resourceType) } return h.buildSuggestion(err, location, resourceType, availableLocations) } ``` -------------------------------- ### Provider Registration Example Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Example of registering custom service targets or framework services in the 'providers' section of the manifest. ```yaml providers: - name: azure-vm type: service-target description: Deploy applications to Azure Virtual Machines - name: go-gin type: framework-service description: Support for Go applications using the Gin framework ``` -------------------------------- ### Install azd extensions Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Installs one or more extensions from a configured source. Use --version to specify a semver constraint and --source to specify the extension source. ```bash azd extension install [flags] ``` -------------------------------- ### Extension Dependencies Example Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Example of how to declare dependencies on other extensions within the manifest file. Supports semantic versioning constraints. ```yaml dependencies: - id: microsoft.azd.ai.builder version: "^1.2.0" - id: contoso.custom.tools version: "~2.1.0" ``` -------------------------------- ### Example of azd command structure Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extensions-style-guide.md Illustrates the recommended verb-first structure for new commands in azd extensions. ```shell azd add ``` ```shell azd add ``` -------------------------------- ### Force Fresh Source Fetch and Install Extension Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-resolution-and-versioning.md Force a fresh source fetch by setting AZD_EXTENSION_CACHE_TTL to 0s, then install the extension. This is useful for troubleshooting stale cache issues. ```bash export AZD_EXTENSION_CACHE_TTL=0s azd extension install ``` -------------------------------- ### Example Provisioning Failure Log Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/style-guidelines/azd-style-guide.md Illustrates a failure scenario during Azure resource provisioning, showing composed states with error details. ```text Provisioning Azure resources (azd provision) (✓) Done: Creating App Service Plan: plan-r2w2adrz3rvwxu (✓) Done: Creating Log Analytics workspace: log-r2w2adrz3rvwxu (x) Failed: Creating Cosmos DB: cosmos-r2w2adrz3rvwxu The '{US} West US 2 (westus)' region is currently experiencing high demand and cannot fulfill your request. Failed to create Cosmos DB account. ERROR: Unable to complete provisioning of Azure resources, 'azd up' failed ``` -------------------------------- ### Actionable Suggestion Example Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/error-suggestions.md Provide clear, actionable steps for the user to resolve the issue. ```yaml suggestion: "Run 'azd auth login' to sign in again." ``` -------------------------------- ### Error Log Example Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/style-guidelines/azd-style-guide.md Illustrates the format for error logs, used when a command fails and cannot continue. It should include the reason and a suggested fix. ```text ERROR: Message goes here. ``` -------------------------------- ### CLI Color Helper Function Examples Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/style-guidelines/azd-style-guide.md Demonstrates the usage of standard CLI color helper functions for success, warning, error, hyperlinks, and command highlighting. ```go // Success message fmt.Println(output.WithSuccessFormat("(✓) Done:") + " Creating resource") // Warning message fmt.Println(output.WithWarningFormat("(!) Warning:") + " Configuration may need update") // Error message fmt.Println(output.WithErrorFormat("(x) Failed:") + " Unable to connect") // Hyperlink fmt.Printf("View in portal: %s\n", output.WithLinkFormat(url)) // Command highlight fmt.Printf("Run %s to deploy\n", output.WithHighLightFormat("azd deploy")) ``` -------------------------------- ### List Select Initial State Example Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/style-guidelines/azd-style-guide.md Displays the initial state of a list select prompt with options, including ghost-text for filtering and highlighting for the active selection. ```text ? Select a single option: [Use arrows to move, type to filter] > Option 1 Option 2 Option 3 Option 4 Option 5 Option 6 ... ``` -------------------------------- ### MCP Server Construction (Go) Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-migration-guide.md Illustrates the transition from manual MCP server setup with raw handlers to using `MCPServerBuilder` for streamlined configuration, including rate limiting and tool registration. ```go mcpServer := server.NewMCPServer("my-mcp", "1.0.0") // Manual rate limiter setup limiter := rate.NewLimiter(rate.Limit(2.0), 10) // Manual tool registration with raw handler mcpServer.AddTool( mcp.NewTool("list_items", mcp.WithDescription("List items"), mcp.WithString("query", mcp.Required(), mcp.Description("Search query")), ), func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { // Manual rate limiting check if !limiter.Allow() { return &mcp.CallToolResult{ IsError: true, Content: []mcp.Content{{Type: "text", Text: ptr("rate limited")}}, }, nil } // Manual arg extraction args := req.Params.Arguments query, ok := args["query"].(string) if !ok { return nil, fmt.Errorf("missing required argument: query") } // ... handler logic ... return nil, nil }, ) ``` ```go mcpServer := azdext.NewMCPServerBuilder("my-mcp", "1.0.0"). WithRateLimit(10, 2.0). WithSecurityPolicy(azdext.DefaultMCPSecurityPolicy()). AddTool("list_items", listItemsHandler, azdext.MCPToolOptions{ Description: "List items", }, mcp.WithString("query", mcp.Required(), mcp.Description("Search query")), ). Build() func listItemsHandler(ctx context.Context, args azdext.ToolArgs) (*mcp.CallToolResult, error) { query, err := args.RequireString("query") if err != nil { return azdext.MCPErrorResult("missing argument: %v", err), nil } // ... handler logic ... return azdext.MCPJSONResult(results), nil } ``` -------------------------------- ### Install `azd` on Linux Source: https://github.com/azure/azure-dev/blob/main/README.md Installs `azd` on Linux by downloading and executing an installation script. This method is suitable for most Linux distributions. ```bash curl -fsSL https://aka.ms/install-azd.sh | bash ``` -------------------------------- ### Main Entry Point for Extension (main.go) Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-e2e-walkthrough.md The `main.go` file serves as the entry point for the extension. It uses `azdext.Run` to initialize and execute the extension's root command. ```go package main import ( "github.com/azure/azure-dev/cli/azd/extensions/contoso.azd.tagger/internal/cmd" "github.com/azure/azure-dev/cli/azd/pkg/azdext" ) func main() { azdext.Run(cmd.NewRootCommand()) } ``` -------------------------------- ### Install `azd` on Windows using Winget Source: https://github.com/azure/azure-dev/blob/main/README.md Installs the latest version of `azd` on Windows using the Windows Package Manager (winget). This is the recommended installation method for Windows. ```powershell winget install microsoft.azd ``` -------------------------------- ### Initialize and Use Copilot SDK in Go Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Demonstrates initializing the Copilot client, sending messages, and managing sessions. Ensure you have the necessary authentication context. ```go ctx := azdext.WithAccessToken(cmd.Context()) azdClient, err := azdext.NewAzdClient() if err != nil { return fmt.Errorf("failed to create azd client: %w", err) } dezdClient.Close() copilot := azdClient.Copilot() // Optional: warm up the client and resolve configuration initResp, err := copilot.Initialize(ctx, &azdext.InitializeCopilotRequest{ Model: "gpt-4o", ReasoningEffort: "medium", }) if err != nil { return fmt.Errorf("failed to initialize copilot: %w", err) } fmt.Printf("Model: %s, Reasoning: %s\n", initResp.Model, initResp.ReasoningEffort) // Send the first message — creates a new session sendResp, err := copilot.SendMessage(ctx, &azdext.SendCopilotMessageRequest{ Prompt: "Add a health check endpoint to the API", Mode: "autopilot", Headless: true, SystemMessage: "You are an expert Go developer.", }) if err != nil { return fmt.Errorf("failed to send message: %w", err) } // Capture the session ID for subsequent calls sessionID := sendResp.SessionId // Send a follow-up message in the same session followUp, err := copilot.SendMessage(ctx, &azdext.SendCopilotMessageRequest{ Prompt: "Now add tests for the health check endpoint", SessionId: sessionID, }) if err != nil { return fmt.Errorf("failed to send follow-up: %w", err) } fmt.Printf("Turn usage: %.0f tokens\n", followUp.Usage.TotalTokens) // Retrieve cumulative metrics metricsResp, err := copilot.GetUsageMetrics(ctx, &azdext.GetCopilotUsageMetricsRequest{ SessionId: sessionID, }) if err != nil { return fmt.Errorf("failed to get metrics: %w", err) } fmt.Printf("Total tokens: %.0f, Premium requests: %.0f\n", metricsResp.Usage.TotalTokens, metricsResp.Usage.PremiumRequests) // Retrieve file changes changesResp, err := copilot.GetFileChanges(ctx, &azdext.GetCopilotFileChangesRequest{ SessionId: sessionID, }) if err != nil { return fmt.Errorf("failed to get file changes: %w", err) } for _, change := range changesResp.FileChanges { fmt.Printf(" %s: %s\n", change.ChangeType, change.Path) } // Clean up the session _, err = copilot.StopSession(ctx, &azdext.StopCopilotSessionRequest{ SessionId: sessionID, }) if err != nil { return fmt.Errorf("failed to stop session: %w", err) } ``` -------------------------------- ### Install Specific or Latest Extension Version via CLI Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-resolution-and-versioning.md Install a specific version of an extension using the --version flag, or omit it to install the latest available version. ```bash # Install an exact version azd extension install my.extension --version 1.0.0 ``` ```bash # Install the latest version (default) azd extension install my.extension --version latest azd extension install my.extension ``` -------------------------------- ### Create Listen Command (Go) Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-migration-guide.md Compares legacy command creation with the recommended approach using `azdext.NewListenCommand`. The new method handles client creation, context injection, and cleanup internally. ```go func newListenCommand() *cobra.Command { return &cobra.Command{ Use: "listen", Short: "Starts the extension and listens for events.", RunE: func(cmd *cobra.Command, args []string) error { ctx := azdext.WithAccessToken(cmd.Context()) azdClient, err := azdext.NewAzdClient() if err != nil { return fmt.Errorf("failed to create azd client: %w", err) } defer azdClient.Close() host := azdext.NewExtensionHost(azdClient). WithServiceTarget("myhost", func() azdext.ServiceTargetProvider { return &MyProvider{client: azdClient} }) return host.Run(ctx) }, } } ``` ```go rootCmd.AddCommand(azdext.NewListenCommand(func(host *azdext.ExtensionHost) { host.WithServiceTarget("myhost", func() azdext.ServiceTargetProvider { return &MyProvider{client: host.Client()} }) })) ``` -------------------------------- ### Install `azd` on macOS using Homebrew Source: https://github.com/azure/azure-dev/blob/main/README.md Installs `azd` on macOS using the Homebrew package manager. If upgrading from a non-Homebrew installation, remove the existing `azd` binary first. ```bash brew install --cask azure/azd/azd ``` -------------------------------- ### Recommended CI Setup for Testing with Recordings Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/recording-functional-tests-guide.md A pseudo CI configuration demonstrating the steps to build both azd binaries and run tests in playback mode using the recording binary. ```yaml # Pseudo CI configuration steps: - name: Build standard azd run: ./ci-build.ps1 - name: Build azd-record for tests run: ./ci-build.ps1 -BuildRecordMode - name: Run tests with recordings env: AZURE_RECORD_MODE: playback # Force playback mode CLI_TEST_AZD_PATH: ./azd-record run: ./ci-test.ps1 ``` -------------------------------- ### Install the azd Developer Extension Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Install the `azd` Developer extension using the `azd extension install` command. This extension provides a suite of commands under the `x` namespace for development tasks. ```bash azd extension install microsoft.azd.extensions ``` -------------------------------- ### Initialize New Extension Project Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Use `azd x init` to create a new extension project. This command scaffolds the project, builds initial binaries, packs the extension, publishes it to a local source, and installs it locally for immediate use. ```bash azd x init ``` -------------------------------- ### Install `azd` on Windows using a PowerShell script Source: https://github.com/azure/azure-dev/blob/main/README.md Installs or upgrades `azd` on Windows by downloading and executing an installation script. Ensure PowerShell's execution policy allows script execution. ```powershell powershell -ex AllSigned -c "Invoke-RestMethod 'https://aka.ms/install-azd.ps1' | Invoke-Expression" ``` -------------------------------- ### Initialize Method for Framework Service Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework-services.md Implement the `Initialize` method to perform setup logic when the framework service is first configured for a service. This includes validating configuration and checking toolchain versions. ```go func (p *RustFrameworkServiceProvider) Initialize(ctx context.Context, serviceConfig *azdext.ServiceConfig) error { fmt.Printf("Initializing Rust framework for service: %s\n", serviceConfig.GetName()) p.serviceConfig = serviceConfig // Perform any initialization logic here // - Validate Cargo.toml exists // - Check Rust toolchain version // - Set up configuration return nil } ``` -------------------------------- ### List Installed Extensions Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Lists extensions installed in your azd environment. You can filter by source or tags. ```bash azd extension list --installed ``` -------------------------------- ### Uninstall azd extensions Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Uninstalls one or more previously installed extensions. Use --all to remove all installed extensions. ```bash azd extension uninstall [flags] ``` -------------------------------- ### Migrate Entry Point: NewContext to Run Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-migration-guide.md Replaces manual context creation, error handling, and execution with a single `azdext.Run` call. This simplifies boilerplate and standardizes behavior. ```go func main() { ctx, err := azdext.NewContext() if err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) os.Exit(1) } rootCmd := cmd.NewRootCommand() rootCmd.SetContext(ctx) if err := rootCmd.Execute(); err != nil { os.Exit(1) } } ``` ```go func main() { azdext.Run(cmd.NewRootCommand()) } ``` -------------------------------- ### Copilot SDK - Example Usage (Go) Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Demonstrates various functionalities of the Copilot SDK in Go, including initialization, sending messages, retrieving usage metrics, file changes, and session management. ```Go ctx := azdext.WithAccessToken(cmd.Context()) azdClient, err := azdext.NewAzdClient() if err != nil { return fmt.Errorf("failed to create azd client: %w", err) } azdClient.Close() copilot := azdClient.Copilot() // Optional: warm up the client and resolve configuration initResp, err := copilot.Initialize(ctx, &azdext.InitializeCopilotRequest{ Model: "gpt-4o", ReasoningEffort: "medium", }) if err != nil { return fmt.Errorf("failed to initialize copilot: %w", err) } fmt.Printf("Model: %s, Reasoning: %s\n", initResp.Model, initResp.ReasoningEffort) // Send the first message — creates a new session sendResp, err := copilot.SendMessage(ctx, &azdext.SendCopilotMessageRequest{ Prompt: "Add a health check endpoint to the API", Mode: "autopilot", Headless: true, SystemMessage: "You are an expert Go developer.", }) if err != nil { return fmt.Errorf("failed to send message: %w", err) } // Capture the session ID for subsequent calls sessionID := sendResp.SessionId // Send a follow-up message in the same session followUp, err := copilot.SendMessage(ctx, &azdext.SendCopilotMessageRequest{ Prompt: "Now add tests for the health check endpoint", SessionId: sessionID, }) if err != nil { return fmt.Errorf("failed to send follow-up: %w", err) } fmt.Printf("Turn usage: %.0f tokens\n", followUp.Usage.TotalTokens) // Retrieve cumulative metrics metricsResp, err := copilot.GetUsageMetrics(ctx, &azdext.GetCopilotUsageMetricsRequest{ SessionId: sessionID, }) if err != nil { return fmt.Errorf("failed to get metrics: %w", err) } fmt.Printf("Total tokens: %.0f, Premium requests: %.0f\n", metricsResp.Usage.TotalTokens, metricsResp.Usage.PremiumRequests) // Retrieve file changes changesResp, err := copilot.GetFileChanges(ctx, &azdext.GetCopilotFileChangesRequest{ SessionId: sessionID, }) if err != nil { return fmt.Errorf("failed to get file changes: %w", err) } for _, change := range changesResp.FileChanges { fmt.Printf(" %s: %s\n", change.ChangeType, change.Path) } // Clean up the session _, err = copilot.StopSession(ctx, &azdext.StopCopilotSessionRequest{ SessionId: sessionID, }) if err != nil { return fmt.Errorf("failed to stop session: %w", err) } ``` -------------------------------- ### Start a Span Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/tracing-in-azd.md Use this to start a new span for tracing an event. It returns a Span object that can be used for further operations. ```go tracing.Start(ctx, events.MyEvent) ``` -------------------------------- ### Prompt for Multi-Select Environments (Go) Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Use this snippet to prompt the user to select multiple environments for deployment. Ensure the azdext client is initialized and the context is set with an access token. ```go // Prompt for multiple environment selections ctx := azdext.WithAccessToken(cmd.Context()) azdClient, err := azdext.NewAzdClient() if err != nil { return fmt.Errorf("failed to create azd client: %w", err) } def azdClient.Close() choices := []*azdext.MultiSelectChoice{ {Value: "dev", Display: "Development Environment", Selected: true}, {Value: "staging", Display: "Staging Environment", Selected: false}, {Value: "prod", Display: "Production Environment", Selected: false}, } response, err := azdClient.Prompt().MultiSelect(ctx, &azdext.MultiSelectRequest{ Options: &azdext.MultiSelectOptions{ Message: "Select environments to deploy to:", Choices: choices, HelpMessage: "Choose one or more environments for deployment", Hint: "Use space to select, enter to confirm", }, }) if err != nil { return fmt.Errorf("failed to prompt for environments: %w", err) } for _, choice := range response.Values { fmt.Printf("Selected: %s (%s)\n", choice.Display, choice.Value) } ``` -------------------------------- ### Install `azd` on Windows using Chocolatey Source: https://github.com/azure/azure-dev/blob/main/README.md Installs the latest version of `azd` on Windows using the Chocolatey package manager. ```powershell choco install azd ``` -------------------------------- ### Build and Package Extension Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Use these commands to build the extension for all platforms and then package the extension artifacts. ```bash azd x build --all # Build for all platforms azd x pack # Package the extension ``` -------------------------------- ### Create ConfigHelper Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-sdk-reference.md Initialize a helper for reading and writing azd user and environment configuration. Requires an initialized AzdClient. ```go func NewConfigHelper(client *AzdClient) (*ConfigHelper, error) ``` -------------------------------- ### Install Extension from Specific Source Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-resolution-and-versioning.md Explicitly specify the source to install an extension from, useful for disambiguating extensions with the same ID across multiple sources. ```bash azd extension install --source ``` -------------------------------- ### Register Framework Service Provider (Go) Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework.md Implement a custom framework service provider in Go, including methods for initialization, required tools, requirements, restore, build, and package operations. This example demonstrates registering a Rust framework provider with the Azure Dev extension host. ```go // Custom Rust framework provider type RustFrameworkProvider struct{} func (r *RustFrameworkProvider) Initialize(ctx context.Context, serviceConfig *azdext.ServiceConfig) error { // Initialize Rust-specific settings return nil } func (r *RustFrameworkProvider) RequiredExternalTools(ctx context.Context, serviceConfig *azdext.ServiceConfig) ([]*azdext.ExternalTool, error) { return []*azdext.ExternalTool{ { Name: "cargo", InstallUrl: "https://rustup.rs/", }, }, nil } func (r *RustFrameworkProvider) Requirements() (*azdext.FrameworkRequirements, error) { return &azdext.FrameworkRequirements{ Package: &azdext.FrameworkPackageRequirements{ RequireRestore: true, RequireBuild: true, }, }, nil } func (r *RustFrameworkProvider) Restore(ctx context.Context, serviceConfig *azdext.ServiceConfig, serviceContext *azdext.ServiceContext, progress azdext.ProgressReporter) (*azdext.ServiceRestoreResult, error) { // Run cargo fetch or similar return &azdext.ServiceRestoreResult{ Artifacts: []*azdext.Artifact{ { Kind: azdext.ARTIFACT_KIND_DIRECTORY, Path: "target/deps", }, }, }, nil } func (r *RustFrameworkProvider) Build(ctx context.Context, serviceConfig *azdext.ServiceConfig, serviceContext *azdext.ServiceContext, progress azdext.ProgressReporter) (*azdext.ServiceBuildResult, error) { // Run cargo build return &azdext.ServiceBuildResult{ Artifacts: []*azdext.Artifact{ { Kind: azdext.ARTIFACT_KIND_DIRECTORY, Path: "target/release", }, }, }, nil } func (r *RustFrameworkProvider) Package(ctx context.Context, serviceConfig *azdext.ServiceConfig, serviceContext *azdext.ServiceContext, progress azdext.ProgressReporter) (*azdext.ServicePackageResult, error) { // Package Rust application return &azdext.ServicePackageResult{ Artifacts: []*azdext.Artifact{ { Kind: azdext.ARTIFACT_KIND_ARCHIVE, Path: "dist/app.tar.gz", }, }, }, nil } // Register the framework provider func main() { ctx := azdext.WithAccessToken(azdext.NewContext()) azdClient, err := azdext.NewAzdClient() if err != nil { log.Fatal(err) } defer azdClient.Close() host := azdext.NewExtensionHost(azdClient). WithFrameworkService("rust", func() azdext.FrameworkServiceProvider { return &RustFrameworkProvider{} }) if err := host.Run(ctx); err != nil { log.Fatalf("failed to run extension: %v", err) } } ``` -------------------------------- ### Entry Point & Lifecycle - RunOption / WithPreExecute Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-sdk-reference.md Allows registering a hook that runs after context creation but before command execution, useful for setup tasks like prerequisite validation or directory changes. ```APIDOC ## RunOption / WithPreExecute ### Description `WithPreExecute` registers a hook that runs after context creation but before command execution. If the hook returns a non-nil error, `Run` prints it and exits. This is useful for extensions that need special setup such as dual-mode host detection or working-directory changes. ### Method `func` ### Endpoint N/A (SDK function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go func main() { rootCmd := cmd.NewRootCommand() azdext.Run(rootCmd, azdext.WithPreExecute(func(ctx context.Context, cmd *cobra.Command) error { // Validate prerequisites if _, err := exec.LookPath("docker"); err != nil { return fmt.Errorf("docker is required: %w", err) } return nil })) } ``` ### Response #### Success Response (200) None (function executes or exits) #### Response Example None ``` -------------------------------- ### Create Prompt Server in Go Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/external-prompting.md Sets up an HTTP server to receive prompts from azd subprocesses. It generates a random key for authentication and listens on a random port. The server handles prompt requests and forwards them to a Bubble Tea UI. ```go // prompt_server.go - HTTP server to receive prompts from azd subprocesses type PromptServer struct { listener net.Listener server *http.Server endpoint string key string ui *tea.Program // Bubble Tea program to send prompts to pendingReq *pendingPrompt } func NewPromptServer(ctx context.Context) (*PromptServer, error) { // Generate random key for authentication keyBytes := make([]byte, 32) rand.Read(keyBytes) key := hex.EncodeToString(keyBytes) // Create listener on random port listener, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { return nil, err } endpoint := fmt.Sprintf("http://%s", listener.Addr().String()) ps := &PromptServer{ listener: listener, endpoint: endpoint, key: key, } mux := http.NewServeMux() mux.HandleFunc("/prompt", ps.handlePrompt) ps.server = &http.Server{Handler: mux} return ps, nil } // EnvVars returns environment variables to pass to azd subprocesses func (ps *PromptServer) EnvVars() []string { return []string{ fmt.Sprintf("AZD_UI_PROMPT_ENDPOINT=%s", ps.endpoint), fmt.Sprintf("AZD_UI_PROMPT_KEY=%s", ps.key), // Disable dialog to get individual prompts with full location list "AZD_UI_NO_PROMPT_DIALOG=1", } } func (ps *PromptServer) handlePrompt(w http.ResponseWriter, r *http.Request) { // Validate auth header if r.Header.Get("Authorization") != fmt.Sprintf("Bearer %s", ps.key) { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } // Parse request var req PromptRequest json.NewDecoder(r.Body).Decode(&req) // Create response channel and send to TUI responseChan := make(chan *PromptResponse, 1) ps.pendingReq = &pendingPrompt{request: &req, response: responseChan} // Send to Bubble Tea program ps.ui.Send(promptRequestMsg{request: &req}) // Wait for response from TUI response := <-responseChan // Send response back to azd w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(response) } ``` -------------------------------- ### Implement Restore Logic for Dependencies Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework-services.md Implement the `Restore` method to handle dependency restoration for your language. This is equivalent to commands like `npm install` or `pip install`. ```go func (p *RustFrameworkServiceProvider) Restore( ctx context.Context, serviceConfig *azdext.ServiceConfig, serviceContext *azdext.ServiceContext, progress azdext.ProgressReporter, ) (*azdext.ServiceRestoreResult, error) { progress("Installing Rust dependencies") // Your actual restore logic here: // - Run `cargo fetch` to download dependencies // - Validate Cargo.lock file // - Check for dependency conflicts progress("Cargo dependencies resolved") // Return artifacts instead of Details map restoreArtifacts := []*azdext.Artifact{ { Kind: "lock-file", Location: "Cargo.lock", LocationKind: "local", Metadata: map[string]string{ "timestamp": time.Now().Format(time.RFC3339), "dependencyMgr": "cargo", }, }, } return &azdext.ServiceRestoreResult{ Artifacts: restoreArtifacts, }, nil } ``` -------------------------------- ### YAML Recording File Structure Example Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/recording-functional-tests-guide.md An example of the structure of a YAML file used for storing HTTP interactions during recording. It includes request and response details. ```yaml --- version: 2 interactions: - id: 0 request: method: PUT url: https://management.azure.com/... headers: Authorization: SANITIZED body: '...' response: status: 200 OK headers: {...} body: '...' - id: 1 # ... more interactions --- env_name: azdtest-w4c1619 subscription_id: faa080af-c1d8-40ad-9cce-e1a450ca5b57 time: "1744738873" ``` -------------------------------- ### Run Action with Complex Output Formatting Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/style-guidelines/new-azd-command.md Handles listing items, formatting output as a table or default, and provides user feedback for empty results. Requires a service to fetch items and a formatter for output. ```go func (a *myListAction) Run(ctx context.Context) (*actions.ActionResult, error) { items, err := a.service.List(ctx) if err != nil { return nil, fmt.Errorf("failed to retrieve items: %w", err) } // Handle empty results if len(items) == 0 { a.console.Message(ctx, output.WithWarningFormat("No items found.")) a.console.Message(ctx, fmt.Sprintf( "Create one with %s", output.WithHighLightFormat("azd mycommand create "), )) return nil, nil } // Format output based on format type switch a.formatter.Kind() { case output.TableFormat: columns := []output.Column{ { Heading: "Name", ValueTemplate: "{{.Name}}", }, { Heading: "Status", ValueTemplate: "{{.Status}}", }, { Heading: "Created", ValueTemplate: "{{.CreatedAt | date}}", }, } return nil, a.formatter.Format(items, a.writer, output.TableFormatterOptions{ Columns: columns, }) default: return nil, a.formatter.Format(items, a.writer, nil) } } ``` -------------------------------- ### Example Quota Error Output Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/error-suggestions.md This example shows how a quota error is presented to the user, including a friendly message, suggestion, documentation link, and the original error details. ```text ERROR: Your Azure subscription has reached a resource quota limit. Suggestion: Request a quota increase through the Azure portal, or try deploying to a different region. Learn more: https://learn.microsoft.com/azure/quotas/quickstart-increase-quota-portal Deployment failed: QuotaExceeded for resource type Microsoft.Compute/virtualMachines in location eastus... ``` -------------------------------- ### ExtensionHost Methods Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-sdk-reference.md Methods for configuring and running an ExtensionHost, including registering custom service targets, framework build services, and project/service event handlers. The Run method starts the host and blocks until shutdown. ```go func (h *ExtensionHost) Client() *AzdClient ``` ```go func (h *ExtensionHost) WithServiceTarget(host string, factory ServiceTargetFactory) *ExtensionHost ``` ```go func (h *ExtensionHost) WithFrameworkService(language string, factory FrameworkServiceFactory) *ExtensionHost ``` ```go func (h *ExtensionHost) WithProjectEventHandler(eventName string, handler ProjectEventHandler) *ExtensionHost ``` ```go func (h *ExtensionHost) WithServiceEventHandler(eventName string, handler ServiceEventHandler, options *ServiceEventOptions) *ExtensionHost ``` ```go func (h *ExtensionHost) Run(ctx context.Context) error ``` -------------------------------- ### Standard Go Build Command Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/recording-functional-tests-guide.md Builds the azd binary without recording support. Uses standard HTTP client and real clock. ```bash go build -o azd ``` -------------------------------- ### Implement Rust Package Method Source: https://github.com/azure/azure-dev/blob/main/cli/azd/docs/extensions/extension-framework-services.md Handles the creation of deployable artifacts for a Rust project. This method should copy the binary, include necessary runtime files, create a container image or zip archive, and generate a deployment manifest. Access build artifacts from `serviceContext.Build` if needed. ```go func (p *RustFrameworkServiceProvider) Package( ctx context.Context, serviceConfig *azdext.ServiceConfig, serviceContext *azdext.ServiceContext, progress azdext.ProgressReporter, ) (*azdext.ServicePackageResult, error) { progress("Creating deployment package") // Your actual packaging logic here: // - Copy binary to deployment directory // - Include necessary runtime files // - Create container image or zip archive // - Generate deployment manifest // - Access build artifacts from serviceContext.Build if needed packagePath := fmt.Sprintf("%s-deployment.tar.gz", serviceConfig.GetName()) progress("Package created: " + packagePath) // Return artifacts instead of Details map packageArtifacts := []*azdext.Artifact{ { Kind: "package", Location: packagePath, LocationKind: "local", Metadata: map[string]string{ "timestamp": time.Now().Format(time.RFC3339), "packageType": "tar.gz", "size": "15.2MB", }, }, } return &azdext.ServicePackageResult{ Artifacts: packageArtifacts, }, nil } ```