Rename azd extension/tool UPGRADE commands to UPDATE - #9370
Rename azd extension/tool UPGRADE commands to UPDATE#9370Hiyo Shin (hyoshis) wants to merge 16 commits into
Conversation
Rename the user-facing 'azd extension upgrade' and 'azd tool upgrade' commands to 'update', keeping 'upgrade' as a cobra alias for backward compatibility. Update all displayed help text, flag descriptions, prompts, progress and summary messages, error strings, docs, and regenerate usage/figspec snapshots. Go identifiers, telemetry field-key constants, and the --no-dependency-upgrades flag name are unchanged. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Adds two sets of UX guidance to the azd style guides: 1. Responsive list/table layouts for list commands, documented as part of the core azd design patterns in azd-style-guide.md. 2. Agentic (AI / GitHub Copilot) UX patterns, moved into a dedicated agentic-ux-style-guide.md so the core guide focuses solely on core azd design patterns (which extensions may follow for consistency, but are not enforced). Adds cross-references in the core guide's overview and in cli/azd/AGENTS.md so agents reference the correct file for the flow they're working on. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 656aee2e-29aa-4b53-965c-63543c1dd44a
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: be625a8a-0787-45ea-b3d9-a782d4c2651f
|
Azure Pipelines: Successfully started running 1 pipeline(s). 21 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Renames extension/tool upgrade commands to update while retaining aliases, and refreshes related UX, documentation, tests, and snapshots.
Changes:
- Adds canonical
extension updateandtool updatecommands. - Updates user-facing terminology and generated snapshots.
- Adds broader CLI and agentic UX guidance.
Show a summary per file
| File | Description |
|---|---|
docs/guides/creating-an-extension.md |
Updates promotion guidance. |
cli/azd/docs/style-guidelines/azd-style-guide.md |
Adds responsive-layout guidance. |
cli/azd/docs/style-guidelines/agentic-ux-style-guide.md |
Adds agentic UX guidance. |
cli/azd/docs/extensions/extension-resolution-and-versioning.md |
Updates extension commands and terminology. |
cli/azd/docs/extensions/extension-framework.md |
Documents extension update and alias. |
cli/azd/cmd/tool.go |
Renames the tool command and output. |
cli/azd/cmd/tool_test.go |
Updates expected result messages. |
cli/azd/cmd/testdata/TestUsage-azd-tool.snap |
Updates tool command listing. |
cli/azd/cmd/testdata/TestUsage-azd-tool-update.snap |
Captures update-command help. |
cli/azd/cmd/testdata/TestUsage-azd-tool-check.snap |
Updates check help wording. |
cli/azd/cmd/testdata/TestUsage-azd-extension.snap |
Updates extension command listing. |
cli/azd/cmd/testdata/TestUsage-azd-extension-update.snap |
Captures update-command help. |
cli/azd/cmd/testdata/TestFigSpec.ts |
Updates completion specifications. |
cli/azd/cmd/extension.go |
Renames extension command and output. |
cli/azd/cmd/extension_upgrade_test.go |
Updates failure assertions. |
cli/azd/cmd/extension_test.go |
Updates summary assertions. |
cli/azd/CHANGELOG.md |
Records the command rename. |
cli/azd/AGENTS.md |
References expanded UX guidance. |
Review details
Comments suppressed due to low confidence (1)
cli/azd/cmd/tool.go:1537
- Changing this value to
updatechanges the serializedactionfield in--dry-run --output json; the normal update path makes the same change at line 1362. Existing automation invoking the backward-compatibleupgradealias can therefore break even though the command still resolves. Decouple the human-facing verb from the stable JSON value, or explicitly version and document this machine-output contract change.
action := "update"
- Files reviewed: 18/18 changed files
- Comments generated: 6
- Review effort level: Medium
Jon Gallant (jongio)
left a comment
There was a problem hiding this comment.
Two of the failing CI checks trace directly to this diff, and both are quick fixes.
golangci-lint fails with a single issue: cmd/extension.go:1061:1: File is not properly formatted (gofmt). The reindented return in the dependency-upgrade error path lost a tab. Inline suggestion below.
cspell fails on tabwriter at docs/style-guidelines/azd-style-guide.md:308, :375, and :422. Those lines come from the new responsive-table section in this PR, so the word needs to go in the cspell dictionary (or be wrapped so cspell skips it). Inline comment below.
Two smaller things that don't block:
--docs builds its deep link from c.CommandPath() (cmd/cobra_builder.go), so azd extension update --docs and azd tool update --docs now resolve to https://learn.microsoft.com/azure/developer/azure-developer-cli/reference#azd-extension-update and #azd-tool-update. Cobra reports the canonical path for alias invocations too, so azd extension upgrade --docs lands on the new anchor as well. Is the learn.microsoft.com reference page regenerated from this repo automatically, or does that anchor need a separate docs PR? Right now both the new name and the old alias point at an anchor that doesn't exist yet.
cli/azd/extensions/azure.coding-agent/README.md:32 still tells users to run azd extension upgrade azure.coding-agent. It keeps working via the alias, but it's user-facing copy in the same rename scope.
Address review feedback, complete customer-facing terminology updates, preserve compatibility, and remove unrelated documentation changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 21cd8119-a644-4b3c-8c99-3f89f63a9968
There was a problem hiding this comment.
Review details
Suppressed comments (4)
cli/azd/cmd/extension.go:2595
- The user-facing rename is incomplete for skipped dependency rows. This line appends
child.SkipReason, andpkg/extensions/manager.go:1159still producesdependency upgrades disabled; ... available, soazd extension update --no-dependency-upgradescontinues to display the old verb. Update that source string and its assertions to saydependency updates disabled.
"%s%s Updating %s dependency",
cli/azd/extensions/azure.coding-agent/README.md:29
- The sentence introducing this updated command still says users “want to upgrade” and is missing “have,” leaving this README inconsistent with the new command vocabulary. Update the introduction along with the command example.
azd extension update azure.coding-agent
docs/specs/metrics-audit/feature-telemetry-matrix.md:33
- The command inventory is still inconsistent: the Extensions row above this updated Tool row lists
extension list/show/install/upgrade. Change that command-facing reference toupdate; theext.upgradeevent andextension.upgrade.*keys should remain unchanged.
docs/specs/metrics-audit/telemetry-schema.md:20 - The telemetry schema terminology update is incomplete. Line 19 still calls
ext.installan install/upgrade event, lines 207-216 describe extension updates as upgrades, and lines 288, 312, and 320-327 still describe theazd toolcommand asupgrade. Update those command-facing headings and descriptions to “update” while retaining the intentionally stableext.upgradeandtool.upgrade.*keys.
- Files reviewed: 48/48 changed files
- Comments generated: 0 new
- Review effort level: Balanced
There was a problem hiding this comment.
I think we can go a bit further and use update everywhere in the code and output, and keep upgrade only where we really need backward compatibility.
Specifically, I think we can:
- Rename all Go identifiers, exported APIs, interfaces, tests, and filenames that belong to these extension and tool update flows from
UpgradetoUpdate. I don't see any external consumers using those exported APIs. - Rename telemetry to
ext.update,tool.update.*, and the matchingUpdateconstants. The command span names (cmd.extension.update) already change, so keeping the old telemetry names would leave us with mixed terms. - Rename
extension updateJSON from"upgraded"to"updated","upgraded"counts to"updated", anddependencyUpgradestodependencyUpdates. - Rename
tool updateJSON, including--dry-run, from"action": "upgrade"to"action": "update". - Add
--no-dependency-updatesas the new flag while keeping--no-dependency-upgradesas a hidden alias for existing scripts. - Keep
azd extension upgradeandazd tool upgradeas command aliases. - Keep
upgradefor terms owned by other tools or protocols, such ashelm upgrade, package-manager or pipupgradearguments, WebSocket upgrades, existing URLs, etc.
The JSON changes only affect extension update -o json, extension update --all -o json, and the matching tool update result and dry-run output, which I think this is an acceptable break - I don't see any occurrences users running azd ext upgrade or azd tool upgrade with --output json in our telemetry.
I also think we can also remove the hook compatibility change. The extension and tool commands do not use HooksMiddleware, so those old hook names never worked. The middleware change affects other commands and is not needed for this rename.
|
JeffreyCA I agree on dropping the hook compatibility change, and I think the case is stronger than "those names never worked".
So it isn't only that Dropping Unrelated to the code: the failing |
This reverts commit 87298c1.
There was a problem hiding this comment.
Review details
Suppressed comments (5)
docs/specs/metrics-audit/feature-telemetry-matrix.md:33
- The adjacent extension inventory still ends with
list/show/install/upgrade, leaving this telemetry matrix inconsistent with the canonical command name used elsewhere in the same table. Change only the command reference; keep theext.upgradeevent andextension.upgrade.*keys stable.
docs/specs/metrics-audit/telemetry-schema.md:20 - This event description now uses “update,” but the authoritative schema remains internally stale: lines 19 and 207–216 describe extension installs/fields as upgrades, and lines 288, 312, and 320–327 still describe
tool upgrade. Update those descriptive labels and notes while retaining the compatibility keys (ext.upgrade,extension.upgrade.*,tool.upgrade.*) and stable enum values.
cli/azd/docs/extensions/extension-framework.md:1214 - Earlier sections of this same guide still say azd filters versions during “install/upgrade” (line 1095) and “installs or upgrades” dependencies (line 1191). Update those operational references so the guide consistently uses the new canonical verb; the explicit backward-compatibility alias note should remain unchanged.
Pack manifests must include at least one dependency. They may omit `capabilities`, `namespace`, `entryPoint`, `usage`, and `examples` when the pack has no commands of its own. Installing a pack installs its dependencies recursively from the same extension source as the pack. Dependency versions in the manifest support semver constraints, but command-line `--version` values for `azd extension install` and `azd extension update` are exact versions.
cli/azd/CHANGELOG.md:7
- Repository guidance defers core
CHANGELOG.mdentries to release/version-bump PRs (cli/azd/AGENTS.md:240), and this command-rename PR is not release preparation. Remove this entry so it can be added by the release process.
- Rename the `azd extension upgrade` and `azd tool upgrade` commands to `azd extension update` and `azd tool update`. The former `upgrade` names continue to work as aliases for backward compatibility.
cli/azd/extensions/azure.coding-agent/README.md:29
- The sentence introducing this command still says “want to upgrade” and is missing “have,” so this README mixes the old and new vocabulary. Rewrite the sentence to use “update” consistently.
azd extension update azure.coding-agent
- Files reviewed: 46/46 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Jon Gallant (jongio)
left a comment
There was a problem hiding this comment.
Re-reviewed at 8c10781. The hooks middleware revert is byte-identical to main, and locally go build ./... plus the middleware, usage, figspec, tool, and extension suites all pass.
That revert is the only change since my last pass, so the items you and JeffreyCA settled on (JSON action / upgraded / dependencyUpgrades renames, ext.update and tool.update.* telemetry, --no-dependency-updates, Go identifier renames) are all still outstanding. Three things worth deciding before they land:
- The CHANGELOG entry needs a Breaking Changes split once the JSON keys move.
--no-dependency-updatesneeds explicit reconciliation with the old flag, or pflag will silently drop it.- The command span rename breaks telemetry continuity and there's no dashboard plan mentioned.
Details inline.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 21cd8119-a644-4b3c-8c99-3f89f63a9968
There was a problem hiding this comment.
Review details
Suppressed comments (7)
cli/azd/internal/tracing/events/events.go:32
- This changes the explicit telemetry contract from
ext.upgradetoext.update, even though the PR scope says explicit event keys remain unchanged. Unlike the intentionally auto-derivedcmd.extension.updatespan, this splits the lifecycle event into a new series and breaks existing dashboards and queries. Keep emitting the existingext.upgradeevent from the renamed command; only the command span name should change.
// ExtensionUpdateEvent tracks a single extension update attempt.
ExtensionUpdateEvent = "ext.update"
cli/azd/internal/tracing/fields/fields.go:1201
- The extension telemetry fields are also durable explicit keys. Replacing
extension.upgrade.*andextension.dependency_upgrade_countwith newupdatekeys splits historical metrics and contradicts the PR's non-goal of changing telemetry keys. Preserve the existing identifiers and key strings; only user-facing wording and the auto-derived command span should useupdate.
// ExtensionUpdateDurationMs is the time in milliseconds for one update.
ExtensionUpdateDurationMs = AttributeKey{
Key: attribute.Key("extension.update.duration_ms"),
cli/azd/cmd/tool.go:1362
- The
actionargument is serialized intotoolInstallResultItem.Action, so changing it toupdatebreaks the existing--output jsoncontract, including scripts that continue invoking the promisedupgradealias. Keep the machine-readable value stable asupgrade; if failure text must say “update,” pass a separate display verb instead of reusing the JSON value.
outcome := runToolOperation(ctx, toolsToUpgrade, operationFn, "Updating", "update", a.console,
cli/azd/cmd/tool.go:1537
- This value is emitted as the
actionfield by--dry-run --output json, so changing it fromupgradetoupdateis another machine-readable breaking change despite retaining the old command alias. Preserveupgradein JSON while usingupdateonly for the human-readable dry-run table.
action := "update"
cli/azd/internal/tracing/fields/fields.go:632
- These are explicit telemetry field keys, not command-path-derived names. Renaming them to
tool.update.*contradicts the stated compatibility scope and causes existingtool.upgrade.*dashboards and Kusto queries to stop receiving data. Keep the existingToolUpgrade*identifiers andtool.upgrade.*keys while allowing the command span itself to becomecmd.tool.update.
// ToolUpdateFromVersionKey records the previous version of a tool
// being updated (single-target updates only).
ToolUpdateFromVersionKey = AttributeKey{
Key: attribute.Key("tool.update.from_version"),
cli/azd/cmd/extension.go:2131
- This status description is telemetry, not user-facing text. Renaming it creates another incompatible value for downstream failure queries even though the PR is scoped to a command rename. Keep
upgrade.failedstable alongside the existing upgrade event and field keys.
span.SetStatus(codes.Error, "update.failed")
cli/azd/extensions/azure.coding-agent/README.md:29
- The introductory sentence still uses the old verb and is missing “have,” so it now contradicts the command directly below it. Update the sentence along with the example.
azd extension update azure.coding-agent
- Files reviewed: 49/49 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cca15ce2-dcb9-40a0-801d-5155841a1264
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cca15ce2-dcb9-40a0-801d-5155841a1264
There was a problem hiding this comment.
Review details
Suppressed comments (4)
cli/azd/internal/tracing/events/events.go:37
- [azd-code-reviewer] The stated scope explicitly keeps
ext.upgradeand the other explicit telemetry identifiers stable, but this change stops emittingext.upgradeand creates a new event series. Existing dashboards and queries will lose continuity. Keep the explicit event/field keys on their existingupgradenames; only the auto-derived command span should becomecmd.extension.update/cmd.tool.update.
// ExtensionUpdateEvent tracks a single extension update attempt.
ExtensionUpdateEvent = "ext.update"
cli/azd/cmd/extension.go:2089
- [azd-code-reviewer] The PR scope says
--no-dependency-upgradesremains the stable flag identifier, but these lines make a new flag canonical and hide the existing one. Keep--no-dependency-upgradesas the sole public flag and update only its description terminology; otherwise help, completion, and documentation expose a breaking flag rename outside the stated scope.
cmd.Flags().BoolVar(&flags.noDependencyUpdates, "no-dependency-updates", false,
"Do not update dependencies when updating an extension that has dependencies")
cmd.Flags().BoolVar(&flags.noDependencyUpdates, "no-dependency-upgrades", false,
"Do not update dependencies when updating an extension that has dependencies")
_ = cmd.Flags().MarkHidden("no-dependency-upgrades")
cli/azd/CHANGELOG.md:37
- [azd-code-reviewer] This entry is under the already released
1.30.0 (2026-08-05)section, so the release history incorrectly claims 1.30.0 contained this rename. Move it to the1.31.0-beta.1 (Unreleased)section (or remove it if the breaking-change bullets are sufficient).
- Rename the `azd extension upgrade` and `azd tool upgrade` commands to `azd extension update` and `azd tool update`. The former command names remain aliases. The extension dependency opt-out flag is now `--no-dependency-updates`; `--no-dependency-upgrades` remains available as a hidden alias for existing scripts.
cli/azd/cmd/tool.go:1362
- [azd-code-reviewer] This changes the machine-readable
actionvalue even when users invoke the legacyazd tool upgrade --output jsonalias, so scripts that the alias is intended to preserve can still break. Keep the stable JSON value"upgrade"here and in the dry-run path; the human-facing command and messages can still use “update.”
outcome := runToolOperation(ctx, toolsToUpgrade, operationFn, "Updating", "update", a.console,
- Files reviewed: 51/51 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Scope of Change
Renames:
• azd tool update --output json now returns: Telemetry identifiers change, including: These are documented under Breaking Changes. Out of Scope• Extension update JSON remains compatible: |
There was a problem hiding this comment.
Review details
Suppressed comments (7)
cli/azd/cmd/extension.go:2075
- [azd-code-reviewer] This makes
--no-dependency-updatesthe public flag and hides--no-dependency-upgrades, contradicting the stated non-goal that the stable--no-dependency-upgradesidentifier remains unchanged. Keep the existing flag canonical (its description can use “update” wording) rather than expanding this command rename into a flag rename.
cmd.Flags().BoolVar(&flags.noDependencyUpdates, "no-dependency-updates", false,
"Do not update dependencies when updating an extension that has dependencies")
cmd.Flags().BoolVar(&flags.noDependencyUpdates, "no-dependency-upgrades", false,
"Do not update dependencies when updating an extension that has dependencies")
_ = cmd.Flags().MarkHidden("no-dependency-upgrades")
cli/azd/cmd/tool.go:1537
- [azd-code-reviewer] The dry-run JSON path also changes its public
actionvalue toupdate, breaking existing consumers despite the compatibility alias. Keep the wire value stable asupgrade, or separate JSON serialization from the human-readable action label if the table should display “update.”
action := "update"
cli/azd/internal/tracing/events/events.go:37
- [azd-code-reviewer] The current revision replaces the explicit
ext.upgradeevent with a newext.updateevent, reintroducing the telemetry compatibility issue that the prior reply said was intentionally avoided. This contradicts the PR’s telemetry non-goal and splits historical dashboards/alerts across two event names; keepExtensionUpgradeEvent = "ext.upgrade"while allowing only the auto-derived command span to becomecmd.extension.update.
// ExtensionUpdateEvent tracks a single extension update attempt.
ExtensionUpdateEvent = "ext.update"
cli/azd/internal/tracing/fields/fields.go:634
- [azd-code-reviewer] Renaming these explicit attribute keys to
tool.update.*breaks existing telemetry queries and contradicts the stated non-goal thattool.upgrade.*remains stable. Keep the existing constant/key names; only the auto-derived command span should move tocmd.tool.update.
// ToolUpdateFromVersionKey records the previous version of a tool
// being updated (single-target updates only).
ToolUpdateFromVersionKey = AttributeKey{
Key: attribute.Key("tool.update.from_version"),
Classification: SystemMetadata,
cli/azd/internal/tracing/fields/fields.go:1214
- [azd-code-reviewer] The extension attribute rename likewise replaces stable
extension.upgrade.*telemetry with a new schema, contrary to the PR scope and the prior compatibility response. Preserve the existing keys/constants (includingextension.dependency_upgrade_count) so historical and current data remain query-compatible; only user-facing command text should use “update.”
// ExtensionUpdateDurationMs is the time in milliseconds for one update.
ExtensionUpdateDurationMs = AttributeKey{
Key: attribute.Key("extension.update.duration_ms"),
cli/azd/cmd/tool.go:1363
- [azd-code-reviewer] Passing
"update"here changes the machine-readableactionvalue fromupgradetoupdate, so scripts that invoke even the legacy alias no longer “keep working” if they inspect this field. Preserve the established JSON value independently from the new display verb; the extension update JSON contract already retains its existingupgradedvalues for this reason.
outcome := runToolOperation(ctx, toolsToUpgrade, operationFn, "Updating", "update", a.console,
a.formatter.Kind() == output.JsonFormat)
cli/azd/extensions/azure.coding-agent/README.md:29
- [azd-code-reviewer] The lead-in immediately above this updated command still says “want to upgrade” and is also missing “have,” so this example remains inconsistent with the new user-facing vocabulary. Update the sentence along with the command.
azd extension update azure.coding-agent
- Files reviewed: 51/51 changed files
- Comments generated: 0 new
- Review effort level: Balanced
JeffreyCA
left a comment
There was a problem hiding this comment.
Looks great, thank you Hiyo Shin (@hyoshis)!
|
/check-enforcer evaluate |
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|
Why
The
upgradeverb was inconsistent with the rest of azd's user-facing vocabulary,where "update" is the common term for moving to a newer version. This renames the
two user-facing
upgradecommands toupdateso the CLI reads consistently.Scope of Change
1. User-facing behavior
Renames:
• azd extension upgrade → azd extension update
• azd tool upgrade → azd tool update
• Keeps both old command names working as backward-compatible aliases.
• Adds --no-dependency-updates .
• Keeps --no-dependency-upgrades working as a hidden alias without a deprecation warning.
• Updates related messages such as “Update available,” “Updating Bicep,” extension update suggestions, and tool update results.
2. Breaking machine-readable changes
• azd tool update --output json now returns:
"action": "update"
``` instead of
"upgrade".• This also applies to dry-run JSON and when using the legacy `azd tool upgrade` alias.
Telemetry identifiers change, including:
• ext.upgrade → ext.update
• extension.upgrade.* → extension.update.*
• extension.dependency_upgrade_count → extension.dependency_update_count
• tool.upgrade.* → tool.update.*
These are documented under Breaking Changes.
Out of Scope
• Extension update JSON remains compatible:
- "status": "upgraded"
- dependencyUpgrades
- summary.upgraded
• Extension dependency reconciliation and version-selection behavior are unchanged.
• Internal Upgrade* APIs and types are largely retained.