Migrate microsoft.azd.extensions to azdext runtime and refresh Go scaffolding#7956
Migrate microsoft.azd.extensions to azdext runtime and refresh Go scaffolding#7956
microsoft.azd.extensions to azdext runtime and refresh Go scaffolding#7956Conversation
jongio
left a comment
There was a problem hiding this comment.
Migrates the developer extension to the SDK's root command builder and cleans up the duplicate cwd handling.
Issues to address:
- init.go:557 -
provisioning-provideris added to the prompt but there's noProvisioningProviderCapabilityinextensions.ValidCapabilities, so--capabilities provisioning-providerwill be rejected and registry validation will fail - init.go -
framework-service-provideris inValidCapabilitiesbut missing from the interactive prompt choices
…sh Go templates Agent-Logs-Url: https://github.com/Azure/azure-dev/sessions/fa4ce989-fe34-43a8-8d5d-0fd3d591b203 Co-authored-by: JeffreyCA <9157833+JeffreyCA@users.noreply.github.com>
Derive azd x init capability help and prompt choices from the canonical extension capability list so flag validation and interactive selection do not drift. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
d0d8481 to
b8ebbc7
Compare
microsoft.azd.extensions to azdext runtime and refresh Go scaffolding
There was a problem hiding this comment.
Pull request overview
Migrates the microsoft.azd.extensions developer extension to the azd SDK extension runtime (azdext.Run + NewExtensionRootCommand), refreshes Go scaffolding templates to generate SDK-aligned extensions by default, and updates capability docs/schemas to include provisioning-provider.
Changes:
- Switch extension execution and error reporting to SDK helpers (
azdext.Run,LocalError) and reuse SDK-managed global flags with per-command overrides. - Extend SDK flag-metadata generation to support per-command usage/default presentation (including hiding defaults) and add tests.
- Refresh Go scaffolding templates + bump generated Go module references; update docs/schemas for
provisioning-provider.
Reviewed changes
Copilot reviewed 30 out of 31 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/guides/creating-an-extension.md | Adds provisioning-provider to extension capability overview. |
| docs/concepts/glossary.md | Updates capability list to include provisioning-provider. |
| docs/architecture/extension-framework.md | Documents provisioning-provider capability in architecture guide. |
| cli/azd/pkg/azdext/metadata_generator.go | Adds per-command usage/default override support to generated metadata. |
| cli/azd/pkg/azdext/metadata_generator_test.go | Expands metadata tests for usage overrides and hidden defaults. |
| cli/azd/pkg/azdext/extension_commands_test.go | Adds help-rendering coverage for per-command usage/default behavior. |
| cli/azd/pkg/azdext/extension_command.go | Implements new annotation types for usage + hide-default; applies them in help rendering. |
| cli/azd/internal/grpcserver/framework_service.go | Uses canonical capability constant for framework service capability checks. |
| cli/azd/extensions/registry.schema.json | Adds provisioning-provider to registry capability enum. |
| cli/azd/extensions/microsoft.azd.extensions/main.go | Uses azdext.Run entrypoint; removes custom error path. |
| cli/azd/extensions/microsoft.azd.extensions/internal/user_friendly_error.go | Removes legacy user-friendly error type (SDK structured errors used instead). |
| cli/azd/extensions/microsoft.azd.extensions/internal/user_friendly_error_test.go | Removes tests for the deleted legacy error type. |
| cli/azd/extensions/microsoft.azd.extensions/internal/resources/languages/go/main.go.tmpl | Updates scaffolded Go main to call azdext.Run. |
| cli/azd/extensions/microsoft.azd.extensions/internal/resources/languages/go/internal/cmd/version.go.tmpl | Uses SDK NewVersionCommand helper. |
| cli/azd/extensions/microsoft.azd.extensions/internal/resources/languages/go/internal/cmd/root.go.tmpl | Uses SDK NewExtensionRootCommand to pick up global flags and context. |
| cli/azd/extensions/microsoft.azd.extensions/internal/resources/languages/go/internal/cmd/metadata.go.tmpl | Uses SDK NewMetadataCommand helper. |
| cli/azd/extensions/microsoft.azd.extensions/internal/resources/languages/go/internal/cmd/listen.go.tmpl | Uses SDK NewListenCommand helper. |
| cli/azd/extensions/microsoft.azd.extensions/internal/resources/languages/go/go.sum | Updates scaffolded dependency checksums due to module/runtime changes. |
| cli/azd/extensions/microsoft.azd.extensions/internal/resources/languages/go/go.mod.tmpl | Bumps scaffold go version + pins released azd module version (no pseudo-version). |
| cli/azd/extensions/microsoft.azd.extensions/internal/models/extension_schema.go | Converts missing-manifest error to azdext.LocalError with suggestion metadata. |
| cli/azd/extensions/microsoft.azd.extensions/internal/models/extension_schema_coverage_test.go | Validates LocalError code/category for missing manifest case. |
| cli/azd/extensions/microsoft.azd.extensions/internal/github/github.go | Returns structured LocalError when GitHub CLI is missing. |
| cli/azd/extensions/microsoft.azd.extensions/internal/cmd/root.go | Migrates to NewExtensionRootCommand and threads SDK globals into subcommands. |
| cli/azd/extensions/microsoft.azd.extensions/internal/cmd/release.go | Converts “release already exists” to structured LocalError. |
| cli/azd/extensions/microsoft.azd.extensions/internal/cmd/publish.go | Converts missing GitHub release case to structured LocalError. |
| cli/azd/extensions/microsoft.azd.extensions/internal/cmd/pack.go | Reuses SDK --output flag with per-command help/metadata and hidden default behavior. |
| cli/azd/extensions/microsoft.azd.extensions/internal/cmd/init.go | Syncs capability prompts/validation with canonical capability list; uses SDK --no-prompt. |
| cli/azd/extensions/microsoft.azd.extensions/internal/cmd/init_test.go | Ensures init capability prompt choices stay aligned with canonical capability list. |
| cli/azd/extensions/microsoft.azd.extensions/internal/cmd/build.go | Reuses SDK --output flag with per-command default/usage overrides for build output path. |
| cli/azd/extensions/extension.schema.json | Adds provisioning-provider to extension manifest schema. |
| cli/azd/docs/extensions/extension-framework.md | Updates developer extension docs to reflect SDK -C/--cwd behavior + provisioning capability. |
Use azdext.Run for microsoft.azd.extensions so command execution, structured error reporting, and suggestions flow through the SDK. Replace UserFriendlyError with LocalError-based failures and remove the custom error display path. Reuse SDK-managed global flags for init, build, and pack to avoid reserved flag conflicts, and extend SDK flag metadata so inherited flags can expose command-specific usage/default behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
b8ebbc7 to
a426719
Compare
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|
wbreza
left a comment
There was a problem hiding this comment.
Code Review — PR #7956
Scope: Migrate microsoft.azd.extensions to azdext runtime and refresh Go scaffolding
Reviewer: Automated parallel review (8 focus areas) with priority consensus
This review supplements the 4 existing inline comments. No duplicates.
🔴 CRITICAL (2)
C1 — Undocumented --cwd breaking change
cli/azd/docs/extensions/extension-framework.md
The --cwd flag moved from per-extension local ownership to SDK-managed global behavior (auto-changes directory in PersistentPreRunE). Existing extensions with custom --cwd handling will break silently. No migration guide or breaking change notice exists.
Suggested fix: Add a "Breaking Changes" section to extension migration docs explaining the new --cwd behavior.
C2 — Path traversal risk with delegated --cwd handling (needs verification)
internal/cmd/root.go
Extension delegates --cwd validation entirely to SDK's NewExtensionRootCommand. No visible validation in this PR ensures the SDK sanitizes against path traversal (e.g., ../../sensitive). Per AGENTS.md: "always validate the result is not ., .., empty, or contains path separators."
Suggested fix: Add explicit path validation post-SDK-callback, or document SDK's validation with a code comment referencing the SDK source. Note: This may already be handled by the SDK — needs verification.
🟠 HIGH (3)
H1 — Debug log suppression ordering bug
main.go + root.go
main.go calls log.SetOutput(io.Discard) BEFORE PersistentPreRunE can re-enable logging based on extCtx.Debug. Early startup logs from azdext.Run() are always lost, even in debug mode. This extends the existing review comment about debug suppression with a new finding: the ordering means the fix in root.go is incomplete.
Suggested fix: Remove log.SetOutput(io.Discard) from main.go and let PersistentPreRunE manage log output exclusively.
H2 — Pack --output flag override logic may be incorrect
internal/cmd/pack.go (lines 704-706)
go if outputPath != nil && cmd.Flags().Changed("output") { flags.outputPath = *outputPath }
cmd.Flags().Changed("output") returns false when SDK provides a default without the user explicitly passing --output. SDK-provided output format defaults are silently ignored, falling back to empty string.
Suggested fix: Remove the Changed("output") guard — just check outputPath != nil.
H3 — Test coverage gaps for core migration paths
No integration tests for:
azdext.Run()runtime initialization- SDK
PersistentPreRunEcallback chaining order LocalErrortransformation across all error paths (release, publish, GitHub, schema)- Flag binding from
extCtxpointers to command flags structs
🟡 MEDIUM (5)
M1 — Pointer parameter passing establishes fragile pattern
init.go, build.go, pack.go
Commands receive *bool / *string from extCtx as constructor args. Currently safe (dereference once), but establishes a mutable-pointer-sharing pattern with no documented ownership contract. Future commands mutating the pointer would corrupt shared SDK state.
Suggested fix: Pass by value instead of pointer, or document the immutability contract.
M2 — FlagOptions.Usage documentation vs. implementation mismatch
cli/azd/pkg/azdext/extension_commands.go
When Usage is set, it replaces the flag's usage string entirely (not appends). Documentation doesn't clearly state this. Extensions setting Usage without AllowedValues silently lose the original flag description.
M3 — capabilityLabel() returns empty string for unknown capabilities
internal/cmd/init.go (lines 631-647)
If the capability has only empty words, the function returns "", producing broken UI in the multi-select prompt.
Suggested fix: Fall back to string(cap) instead of empty string.
M4 — Glossary missing provisioning-provider definition
docs/concepts/glossary.md — Capability added to docs/schemas but no glossary entry explaining what it means for extension developers.
M5 — Large go.mod/go.sum dependency changes not described in PR body
~120 lines of dependency updates with only brief mention. Reduces review transparency.
🔵 LOW (1)
L1 — Missing Go doc comments on new/changed functions
newVersionCommand(outputFormat *string), newMetadataCommand(rootCmd *cobra.Command), and capabilityLabel() all lack doc comments explaining parameters and purpose.
Summary: 2 Critical · 3 High · 5 Medium · 1 Low
Automated review via parallel sub-agent analysis with priority consensus validation.
Resolves #7951
Resolves #7925
This PR migrates
microsoft.azd.extensionsto the SDK extension runtime so it usesazdext.Runfor command execution, SDK-managed global flags, and built-in structured error reporting. This removes the extension's custom user-friendly error path in favor ofLocalErrorsuggestions that can be reported back to the azd host consistently.The migration also resolves reserved global flag conflicts by reusing the SDK-provided
--no-promptand--outputflags for extension subcommands while preserving existing behavior for build and package output paths. The SDK flag metadata path now supports command-specific usage/default presentation so inherited flags can still show accurate help and metadata.Generated Go extension projects now use the SDK command helpers for listen, metadata, and version commands, and their module template is pinned to the latest published azd SDK module instead of the placeholder CLI version. This PR also keeps extension capability flows in sync with the canonical capability list and adds provisioning-provider coverage to docs and schemas.
Out of scope
Sub-issue #7954 (audit
.NET/JavaScript/Python/prototemplates) is left for a follow-up.Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
aka.ms/tmp/azd /tmp/azd version -lang=go1.26 x_amd64/vet bis g_.a pkg/mod/github.com/wk8/go-ordere-ifaceassert x_amd64/vet --gdwarf-5 /azure-sdk-for-g-json -o x_amd64/vet -o DsVGK0yIP .cfg x_amd64/vet s/errors/errors./opt/hostedtoolcache/go/1.26.1/x64/pkg/tool/linux_amd64/vet ntio/asm/keyset -lang=go1.26 x_amd64/vet(dns block)/tmp/azd azd ext source list -o json .cfg x_amd64/vet -p la/websocket -lang=go1.23 x_amd64/vet -o yADG/tfiIV0oFQH65beesyADG -trimpath x_amd64/vet -p google.golang.or--norc -lang=go1.23 x_amd64/vet(dns block)/tmp/azd /tmp/azd telemetry upload x_amd64/vet -o 646806/b782/_pkg_.a .cfg x_amd64/vet -p .io/proto/otlp/c-json -lang=go1.22 x_amd64/vet -o h_1E/rEdfsO0syOjwkxB6h_1E pkg/mod/github.com/!azure/azure-sdk-for-go/sdk/resourcemanager/a-nolocalimports x_amd64/vet -p github.com/Azure--norc -lang=go1.18 x_amd64/vet(dns block)example.com/tmp/go-build1192474333/b001/azdext.test /tmp/go-build1192474333/b001/azdext.test -test.paniconexit0 -test.timeout=10m0s -test.count=1 -n ts reserved. /agent/copilot/coverage_extra_test.go /usr/bin/head ts reserved. event_dispatcher-n /usr/bin/head head -n ration. All rights reserved. t_service_test.go /usr/bin/tail ration. All righhead cli/azd/pkg/inpu-n /usr/bin/tail tail(dns block)westus-0.in.applicationinsights.azure.com/tmp/azd /tmp/azd telemetry upload x_amd64/vet -o 646806/b782/_pkg_.a .cfg x_amd64/vet -p .io/proto/otlp/c-json -lang=go1.22 x_amd64/vet -o h_1E/rEdfsO0syOjwkxB6h_1E pkg/mod/github.com/!azure/azure-sdk-for-go/sdk/resourcemanager/a-nolocalimports x_amd64/vet -p github.com/Azure--norc -lang=go1.18 x_amd64/vet(dns block)/tmp/azd /tmp/azd telemetry upload x_amd64/vet -o 646806/b804/_pkg_.a .cfg x_amd64/vet ma.go /cpu -lang=go1.26 x_amd64/vet jIe6�� pkg/mod/github.com/!azure/azure-sdk-for-go/sdk/s-errorsas .cfg x_amd64/vet 646806/b804/symatail google.golang.or-3 -lang=go1.23 x_amd64/vet(dns block)If you need me to access, download, or install something from one of these locations, you can either: