-
Notifications
You must be signed in to change notification settings - Fork 270
Honor installed extension source during upgrade #6720
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
ef2e5db
cd82110
f0be149
6aeb952
a7d58c7
b3aa4c9
c7f0de4
9cd64a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -913,9 +913,16 @@ func (a *extensionUpgradeAction) Run(ctx context.Context) (*actions.ActionResult | |||||||||||||||||||||||||||||||||||||||||||||||
| return nil, fmt.Errorf("failed to get installed extension: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Honor the source from which the extension was originally installed | ||||||||||||||||||||||||||||||||||||||||||||||||
| // Only use the --source flag if explicitly provided by the user | ||||||||||||||||||||||||||||||||||||||||||||||||
| sourceToUse := installed.Source | ||||||||||||||||||||||||||||||||||||||||||||||||
| if a.flags.source != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||
| sourceToUse = a.flags.source | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| filterOptions := &extensions.FilterOptions{ | ||||||||||||||||||||||||||||||||||||||||||||||||
| Id: extensionId, | ||||||||||||||||||||||||||||||||||||||||||||||||
| Source: a.flags.source, | ||||||||||||||||||||||||||||||||||||||||||||||||
| Source: sourceToUse, | ||||||||||||||||||||||||||||||||||||||||||||||||
| Version: a.flags.version, | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -927,17 +934,46 @@ func (a *extensionUpgradeAction) Run(ctx context.Context) (*actions.ActionResult | |||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if len(matches) == 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||
| a.console.StopSpinner(ctx, stepMessage, input.StepFailed) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
| a.console.StopSpinner(ctx, stepMessage, input.StepFailed) | |
| a.console.StopSpinner(ctx, stepMessage, input.StepFailed) | |
| // When upgrading all extensions, skip missing extensions with a warning | |
| // instead of failing the entire operation. | |
| if a.flags.all { | |
| a.console.MessageUxItem(ctx, &ux.WarningMessage{ | |
| Description: fmt.Sprintf( | |
| "Skipping upgrade for extension %s because it was not found in source %s", | |
| extensionId, | |
| sourceToUse, | |
| ), | |
| }) | |
| return nil, nil | |
| } |
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The warning for multiple matches (lines 942-951) indicates an unexpected state when filtering by exact source and extension ID. However, this warning uses the first match without any explanation of why the first one was chosen or what criteria differentiate the matches. Consider either: (1) sorting the matches by version (descending) and documenting this in the warning, or (2) returning an error since this truly is an unexpected/invalid state in the extension registry that should be investigated rather than silently worked around.
| // When filtering by exact source and extension ID, there should only be one match | |
| // However, if there are multiple matches (unexpected), we'll use the first one | |
| if len(matches) > 1 { | |
| a.console.MessageUxItem(ctx, &ux.WarningMessage{ | |
| Description: fmt.Sprintf( | |
| "Found %d matches for %s in source %s, using the first match", | |
| len(matches), | |
| extensionId, | |
| sourceToUse, | |
| ), | |
| }) | |
| // When filtering by exact source and extension ID, there should only be one match. | |
| // If there are multiple matches, this indicates an invalid or inconsistent state in the | |
| // extension registry; fail explicitly so this can be investigated rather than silently | |
| // proceeding with an arbitrary selection. | |
| if len(matches) > 1 { | |
| a.console.StopSpinner(ctx, stepMessage, input.StepFailed) | |
| return nil, fmt.Errorf( | |
| "found %d matches for extension %s in source %s; expected exactly one match", | |
| len(matches), | |
| extensionId, | |
| sourceToUse, | |
| ) |
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The warning about newer versions in other sources is displayed while the spinner is still active (line 954 shows spinner, lines 957-975 show the warning). This will result in the warning being interleaved with the spinner output, making it hard to read. The warning should be displayed either before the spinner starts or after it's stopped. Consider moving the checkForNewerVersionInOtherSources call to after line 1011 (after the spinner is stopped) or stopping the spinner before showing the warning and restarting it afterward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we showed the message after the upgrade instead of before and made it a little more concise? It feels a little verbose currently. Maybe something like:
E.g. upgrading from 0.0.1 to 0.0.2:
(✓) Done: Upgrading microsoft.azd.concurx extension (0.0.2)
A newer version 0.1.0 is available in source 'azd' (installed: 0.0.2 from 'local').
To switch: azd ext uninstall microsoft.azd.concurx && azd ext install microsoft.azd.concurx --source azd
If no upgrade available on current source:
(-) Skipped: Upgrading microsoft.azd.concurx extension (No upgrade available)
A newer version 0.1.0 is available in source 'azd' (installed: 0.0.2 from 'local').
To switch: azd ext uninstall microsoft.azd.concurx && azd ext install microsoft.azd.concurx --source azd
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The instruction message for switching sources suggests running two separate commands (uninstall + install). However, this workflow could lose user configuration or settings associated with the extension. Consider adding a note about this potential data loss, or alternatively, document whether the extension manager preserves configuration across uninstall/install operations. Additionally, it might be helpful to mention that the user can specify --source <source> flag directly with the upgrade command to override the default behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for honoring the installed extension's source is good, but there's a potential edge case when
--allis used with--source. If a user runsazd extension upgrade --all --source specific-source, all installed extensions will be attempted to be upgraded fromspecific-source, even if they were originally installed from different sources. This will fail with "extension X not found in source specific-source" for extensions not available in that source. Consider adding validation to prevent this confusing combination, similar to the existing check for--versionwith multiple extensions at line 870-872.