feat(tool): implement version providers for tool update checks#8085
Conversation
There was a problem hiding this comment.
Pull request overview
This PR upgrades azd tool check from a cache-only POC into a provider-based update check system that can resolve “latest available” versions from external sources and compare them using semantic versioning.
Changes:
- Added a
LatestVersionProviderinterface with implementations for package managers (npm/winget/brew), VS Code Marketplace, and the azd extension registry cache. - Updated
UpdateChecker.Check()to resolve latest versions via providers (cache-first with expiry) and to use semver comparison (Masterminds/semver/v3). - Wired provider selection into the IoC container and expanded test coverage for provider-based behavior.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| cli/azd/pkg/tool/version_provider.go | Introduces version-provider interface + implementations and provider selection logic. |
| cli/azd/pkg/tool/version_provider_test.go | Adds unit tests for providers and selection logic. |
| cli/azd/pkg/tool/update_checker.go | Updates update-check flow to query providers and compare versions via semver. |
| cli/azd/pkg/tool/update_checker_test.go | Expands tests for provider-based update checking, caching, and semver edge cases. |
| cli/azd/pkg/tool/manager_test.go | Updates tests for the new NewUpdateChecker constructor signature. |
| cli/azd/cmd/middleware/tool_update_check_test.go | Updates middleware test for the new NewUpdateChecker constructor signature. |
| cli/azd/cmd/container.go | Wires provider selection into DI and adds helper to create an extension registry cache manager. |
jongio
left a comment
There was a problem hiding this comment.
The 3-provider design (package manager / extension registry / marketplace) is well-structured and the cache-first strategy with per-provider timeouts is solid.
The automated reviewer's comments are all valid. The most critical one: defaultExtensionSource = "default" on line 229 of version_provider.go will cause extension version checks to silently fail. Confirmed by reading source_manager.go:158 where the default source is registered as "azd", and registry_cache.go:94 where sanitizeSourceName only maps empty strings to "default". Passing the literal string "default" will look for a cache file default.json that never gets created (the real file is azd.json).
One note on the fix: the automated review suggests using extensions.MainRegistryName but that constant doesn't exist in the codebase. The straightforward fix is to change the value to "azd" directly (or introduce a new exported const if you want to keep it DRY with source_manager.go).
The other 5 automated comments (cache refresh, marketplace magic numbers, marketplace test URL, Linux az coverage, and lazy init for the registry cache manager) are all reasonable improvements that can be addressed incrementally.
|
Thanks for the thorough review, @jongio! All feedback has been addressed in �d4bfd3:
|
jongio
left a comment
There was a problem hiding this comment.
Correction on my earlier review: I incorrectly flagged defaultExtensionSource = "default" as still present and said extensions.MainRegistryName doesn't exist. Both wrong - the fix commit (ed4bfd3) already addressed the source name, and MainRegistryName is defined in registry_resolver.go.
After verifying the fix commit against current HEAD, all 6 automated review comments are addressed:
- Source name correctly uses
extensions.MainRegistryName(azd) errors.Ischecks forErrCacheNotFound/ErrCacheExpiredwith actionable runazd extension listguidanceaptsupport added withparseAptCandidate(strips Debian revision suffix correctly)- Marketplace magic numbers extracted into
vsMarketplaceFilterByNameandvsMarketplaceQueryFlagswith bitmask docs baseURLfield makesMarketplaceVersionProvidertestable against httptest serverstryNewRegistryCacheManagerlazy init is correct as-is -MustRegisterSingletonclosure only runs on first resolution
Two CI lint items to fix before merge:
- cspell: add extensionquery and bitmask to the dictionary
- go-fix:
strings.SplitSeqandstrings.CutPrefixsuggestions in the parsers
…#8070) Replace the POC carry-forward logic in UpdateChecker.Check() with real version providers that query remote sources for latest versions: - PackageManagerVersionProvider: queries npm, winget, brew for latest package versions - ExtensionRegistryVersionProvider: queries azd extension registry for library tools (e.g. azure.ai.agents) - MarketplaceVersionProvider: queries VS Code Marketplace API for extension tools - SelectVersionProvider factory: selects the right provider based on tool category and configuration Also: - Use semver comparison (Masterminds/semver) instead of string equality for version comparison, fixing pre-release version handling - Add cache-first logic with expiration support - Add per-tool 15-second timeout for provider calls - Wire providers into IoC container in cmd/container.go - Add comprehensive tests for all providers and updated Check() behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace defaultExtensionSource with extensions.MainRegistryName - Add cache miss/expiry detection with actionable error messages - Add apt package manager support for Linux az CLI update checks - Extract VS Marketplace magic numbers into named constants - Make MarketplaceVersionProvider baseURL injectable for testing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add extensionquery and bitmask to cspell dictionary - Apply Go modernizations: SplitSeq, CutPrefix Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
5fee0f4 to
7ecea31
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
|
* feat(tool): implement version providers for tool update checks (#8070) Replace the POC carry-forward logic in UpdateChecker.Check() with real version providers that query remote sources for latest versions: - PackageManagerVersionProvider: queries npm, winget, brew for latest package versions - ExtensionRegistryVersionProvider: queries azd extension registry for library tools (e.g. azure.ai.agents) - MarketplaceVersionProvider: queries VS Code Marketplace API for extension tools - SelectVersionProvider factory: selects the right provider based on tool category and configuration Also: - Use semver comparison (Masterminds/semver) instead of string equality for version comparison, fixing pre-release version handling - Add cache-first logic with expiration support - Add per-tool 15-second timeout for provider calls - Wire providers into IoC container in cmd/container.go - Add comprehensive tests for all providers and updated Check() behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: address PR review feedback on version providers - Replace defaultExtensionSource with extensions.MainRegistryName - Add cache miss/expiry detection with actionable error messages - Add apt package manager support for Linux az CLI update checks - Extract VS Marketplace magic numbers into named constants - Make MarketplaceVersionProvider baseURL injectable for testing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: resolve cspell and go-fix preflight failures - Add extensionquery and bitmask to cspell dictionary - Apply Go modernizations: SplitSeq, CutPrefix Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: therealjohn <1501196+therealjohn@users.noreply.github.com>
Summary
Fixes #8070 —
azd tool checknow correctly detects available updates for installed tools.The
UpdateChecker.Check()method was a POC that never fetched latest versions from remote sources. The cache started empty and stayed empty, soUpdateAvailablewas alwaysfalsefor every tool.Changes
New:
LatestVersionProviderinterface (version_provider.go)Pluggable strategy for fetching latest versions per tool, with three implementations:
PackageManagerVersionProviderExtensionRegistryVersionProviderRegistryCacheManagerfrom extensions packageMarketplaceVersionProviderProvider selection is automatic based on tool category and install strategy.
Fixed:
UpdateChecker.Check()(update_checker.go)latestVer != currentVer) withsemver.NewVersion().GreaterThan()usingMasterminds/semver/v3(consistent with extensions package)IoC wiring (
container.go)tryNewRegistryCacheManager()helper for safe extension registry accessTesting
version_provider_test.go(743 lines): Tests for all three providers with mocked command runners and HTTP responses, provider selection logic, version parsing edge casesupdate_checker_test.go(+301 lines): Tests for provider-based Check() including newer/same/older versions, provider errors, pre-release semver handling (0.1.6-previewvs0.1.29-preview), cache hit/miss behaviorRisk Assessment
UpdateCheckCachestruct is additive only