fix(extensions): centralize compatibility-aware resolution - #9733
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
887d5a0 to
b837e76
Compare
This comment was marked as outdated.
This comment was marked as outdated.
There was a problem hiding this comment.
Copilot review overview
Review tier: Balanced
Findings: None
Issues resolved since last review (1)
| Severity | Finding |
|---|---|
cli/azd/cmd/extension.go — When the requested version exists only in an unrelated configured source, resolution.Error() is… View resolved comment |
There was a problem hiding this comment.
Copilot review overview
Review tier: Balanced
Findings: None
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
cli/azd/cmd/extension.go:2531
- Scope this error before returning it. If the stored source lacks the requested version while an unrelated source publishes only an azd-incompatible copy,
resolution.Error()reports that unrelated incompatibility even though update cannot select that source. UseErrorForUpgradeSourceshere so the stored/main-source missing-version diagnostic and retry command are preserved.
if resolutionErr := resolution.Error(); resolutionErr != nil {
cli/azd/cmd/extension.go:2658
- This detects an incompatible installed release only when the selected target source itself has a newer incompatible release. For an extension installed from
devat incompatible v2 wheredevhas no compatible release andazdsupplies compatible v1, the selected main-registry candidate makes this condition false (andresolution.Matchesomits the dev row), so update emits only “installed version is newer” and loses the promised explicit downgrade command. Determine the installed release from both compatible and incompatible source rows independently ofhasNewerIncompatible.
if hasNewerIncompatible {
installedRelease := findPublishedExtensionVersion(
resolution.Matches,
installed.Source,
installed.Version,
Make the extension manager own the running azd version and apply requiredAzdVersion consistently across init, auto-install, provider discovery, recursive dependencies, explicit installs, and updates. Keep catalog lookup raw while install resolution evaluates version, capability, provider, and azd compatibility against one selected release. Report unavailable requested versions with the latest compatible alternative. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Shorten resolver comments and align install, update, provider, and version compatibility messages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26991398-a901-48b6-96ec-a22349c7355c
Use a typed sentinel when install or update cannot find a selected extension version so telemetry does not fall back to an opaque error string. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26991398-a901-48b6-96ec-a22349c7355c
Return no success action result when any extension update fails, so the CLI does not print SUCCESS after ERROR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26991398-a901-48b6-96ec-a22349c7355c
Align the cancellation regression test with failed update batches returning no success ActionResult. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26991398-a901-48b6-96ec-a22349c7355c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
7255de4 to
f8fa793
Compare
There was a problem hiding this comment.
Copilot review overview
Review tier: Balanced
Findings: 1
New issues introduced by this change (1)
| Severity | Finding |
|---|---|
cli/azd/cmd/extension.go — This retry command is guaranteed to be a no-op when the compatible alternative is lower than the… |
Suppressed comments (1)
cli/azd/cmd/extension.go:2535
resolution.Error()considers every configured source before update-source eligibility. For an extension installed fromdev, ifdevlacks the requested version while an unrelated source publishes only an incompatible copy, this returns the unrelated compatibility error even though update cannot select that source. Scope the error throughErrorForUpgradeSourceshere so diagnostics stay limited to the stored/main or explicitly requested source.
if resolutionErr := resolution.Error(); resolutionErr != nil {
if versionErr, ok := errors.AsType[*extensions.ExtensionVersionNotFoundError](resolutionErr); ok {
return fail(versionMismatchError(versionErr))
}
return fail(resolutionErr)
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|

Fixes #9354
Fixes #9538
Supersedes #9539.
Summary
This PR makes extension compatibility a manager-owned policy. Every install path now selects releases against the running azd version, including init, project and command auto-install, provider lookup, explicit install, update, and recursive dependencies.
It also replaces the misleading
no extensions foundresult for an unavailable requested version. azd now reports the latest compatible version and gives the user a command that installs or updates to it.Issue
Extension discovery and installation used different compatibility rules. Explicit install and update checked
requiredAzdVersionnear the end of the operation, but automatic discovery paths could select an incompatible release or include an incompatible source in an ambiguity prompt.The same split affected provider metadata. A lookup could match a capability from one release, inspect a provider from another release, then install a third release after compatibility filtering.
When a user requested a version that was not published, version filtering removed the extension before the command could explain the mismatch:
This looked like a bad extension ID or registry configuration even when the extension existed.
Resolution
pkg/extensions.Managernow owns the azd version used for compatibility checks. Production managers use the running version by default. Tests and development scenarios can supply a fixed version or explicitly disable compatibility.Raw catalogue lookup remains separate from install resolution:
FindExtensionskeeps all published metadata available for list and show commands.ResolveExtensionsclassifies installable, incompatible, and version-mismatched extensions in one source enumeration.Recursive dependencies use the same manager policy as their parent. Dependency fallback now chooses the parent source only when it has a compatible release that satisfies the declared constraint. Otherwise, registry-backed installs can fall back to the main azd registry.
Typed resolution errors implement
Suggestion(). Common command paths use the error middleware, while extension update adapts these errors to preserve its source-selection and structured-output behaviour.Compatibility details
Development builds continue to skip azd compatibility checks. PR and daily build prerelease tags are compared using their base version because standard semver constraints exclude prerelease versions by default.
Malformed
requiredAzdVersionconstraints retain the existing fail-open behaviour and log a warning. Installed records also retain their current format, so this change does not add a config migration.Extension update does not switch to an unrelated source or automatically downgrade an installed extension. Diagnostics use only sources eligible for the update. When the installed version is incompatible and newer than the compatible release, azd skips the update and provides an explicit downgrade command. Self-contained bundle installs do not accept
--version.Testing
Focused coverage verifies manager defaults and explicit compatibility opt-out, source eligibility, selected-release capability and provider checks, recursive dependency fallback, init and auto-install integration, namespace and provider diagnostics, source-scoped update errors, JSON missing-version details, incompatible installed releases, bundle flag validation, and install and update commands.