Azure / Azure/azure-dev

1P extensions: migrate to `azdext.NewExtensionRootCommand` and remove reserved flag conflicts

Open
#7,950 0 comments 1 reaction 2 assignees Claimed by @JeffreyCA View on GitHub
area/extensions engineering item
Dominant language
Go
Stars
569
Forks
364
Avg merge
2d 19h
Merged PRs (30d)
136

Description

## Summary

Audit and migrate the remaining first-party extensions in `cli/azd/extensions/` to use `azdext.NewExtensionRootCommand` (introduced in #6856), and remove flags that conflict with azd's reserved global flag set (`internal/reserved_flags.go`). This is the same migration completed for `azure.ai.agents` in #7796 / PR #7950, generalized to the rest of the 1P fleet.

Reserved flags to remove: `--debug`, `--no-prompt`, `--cwd`, `--environment` (`-e`), `--output` (`-o`), `--help` (`-h`), `--docs`, `--trace-log-file`, `--trace-log-url`.

## Scope

This issue covers **all first-party extensions in one PR** except `microsoft.azd.extensions`, which has additional surface area (scaffolding templates, `--cwd` semantic collision) and is tracked separately in #7951.

### Conflicts to fix

| Extension | Conflicts | Notes |
|---|---|---|
| `azure.ai.finetune` | manual root `--debug`, `--no-prompt`; `init --environment` (long-name only, short is `-n`); `operations` `--output`/`-o` (×2) | uses `rootFlagsDefinition` global pattern |
| `azure.ai.models` | manual root `--debug`, `--no-prompt`; `init --environment` (long-name only, short is `-n`); `custom show --output`/`-o`; `custom list --output`/`-o` | uses `rootFlagsDefinition` global pattern |
| `azure.appservice` | manual root `--debug`, `--no-prompt` | uses `rootFlagsDefinition` global pattern |
| `azure.coding-agent` | manual root `--debug` | minimal extension |
| `microsoft.azd.concurx` | manual root `--debug`; `up --debug` (subcommand) | duplicate registration on `up` |
| `microsoft.azd.demo` | none directly, but custom root (no SDK) | should still adopt `NewExtensionRootCommand` for consistency |

### Already migrated

- `azure.ai.agents` — done in #7796 / PR #7950

### Tracked separately

- `microsoft.azd.extensions` — see #7951 (extension + scaffolding templates + `--cwd` rename)

### Stub / non-Go / dead — skip

- `azure.ai.customtraining` — binary-only stub (no Go source)
- `azd.internal.pack` — meta-package (no commands)
- `microsoft.azd.ai.builder` — dead extension, not maintained

## Migration template (per extension)

Mirror what was done for `azure.ai.agents` in #7796:

1. **Root**: replace bespoke `cobra.Command{}` + `rootFlagsDefinition` pattern with:
```go
rootCmd, extCtx := azdext.NewExtensionRootCommand(azdext.ExtensionCommandOptions{
Name: "",
Use: "",
Short: "",
})
```
Drop manual `--debug` / `--no-prompt` registrations and any `AZD_*` env-var fallback. Thread `*azdext.ExtensionContext` to subcommand constructors.

2. **`init --environment`**: drop the local flag where present (`azure.ai.finetune`, `azure.ai.models`). Read `extCtx.Environment` instead.

3. **`--output` / `-o`**: replace per-subcommand redeclarations with `azdext.RegisterFlagOptions` (#7826) and read `extCtx.OutputFormat` in `RunE`. Per-command default + allowed values are expressed declaratively.

4. **`PersistentPreRunE` chains**: remove any `cmd.PersistentPreRunE` that manually invokes `parent.PersistentPreRunE` / `root.PersistentPreRunE` — `NewExtensionRootCommand` sets `cobra.EnableTraverseRunHooks = true`, so the SDK pre-run already runs from root → leaf and double-invocation is wrong.

5. **`go.mod` bump**: extensions in their own modules (`azure.ai.finetune`, `azure.ai.models`, `azure.appservice`, `azure.coding-agent`, `microsoft.azd.concurx`) need a bump to the SDK version that includes `RegisterFlagOptions` (#7826) + `EnableTraverseRunHooks` + the reserved-flag registry (#7312). The monorepo extension (`microsoft.azd.demo`) follows the parent `cli/azd` module automatically.

6. **`requiredAzdVersion`** in `extension.yaml`: bump to a version that ships the SDK enforcement so users on older azd see a clear install-time error rather than a runtime conflict.

## Validation

Per extension touched:

```bash
cd cli/azd/extensions/
go build ./... && go test ./...
azd x build
azd --help
```

Plus `go test ./cli/azd/pkg/azdext/...` for `ValidateNoReservedFlagConflicts` coverage.

## Out of scope

- `azure.ai.agents` (already migrated via #7796 / PR #7950)
- `microsoft.azd.extensions` (tracked in #7951)
- `microsoft.azd.ai.builder` (dead extension)
- Changes to the reserved flag registry itself
- Changes to `NewExtensionRootCommand` API surface

## Related

- #7796 — `azure.ai.agents` migration (precedent + template)
- #7951 — `microsoft.azd.extensions` migration (separate due to scaffolding scope)
- #7826 — `azdext.RegisterFlagOptions`
- #7312 — reserved flag registry
- #6856 — `azdext.NewExtensionRootCommand`
- `cli/azd/docs/extensions/extensions-style-guide.md` — Reserved Global Flags section
- `cli/azd/docs/design/extension-flag-architecture.md`

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.