Skip to content

Commit 9f3b36f

Browse files
wbrezaCopilot
andcommitted
docs: address PR review feedback on extension resolution doc
Fix accuracy issues identified in review: - Describe interactive source prompt for multi-source conflicts - Correct version constraint behavior (CLI accepts exact/latest only) - Fix compatibility filtering to describe filter-then-warn behavior - Correct dependency resolution to same-source pinning - Document azd init limitations (no version satisfaction check) - Add cache filename sanitization details - Fix prerelease selection behavior for latest Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 8cddf03 commit 9f3b36f

1 file changed

Lines changed: 42 additions & 29 deletions

File tree

cli/azd/docs/extensions/extension-resolution-and-versioning.md

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -63,51 +63,60 @@ All configured sources are loaded from `~/.azd/config.json` and sorted alphabeti
6363

6464
### 3. Handle Conflicts
6565

66-
If the same extension ID exists in **two or more sources**, `azd` returns an error rather than silently picking one:
66+
If the same extension ID exists in **two or more sources**, `azd` handles the conflict differently depending on the mode:
6767

68-
```
69-
The <id> extension was found in multiple sources.
70-
```
68+
- **Interactive mode**`azd` prompts the user to choose which source to install from.
69+
- **Non-interactive mode** (`--no-prompt` or CI environments) — `azd` returns an error:
7170

72-
To resolve this, specify the source explicitly:
71+
```
72+
The <id> extension was found in multiple sources.
73+
```
74+
75+
To avoid the prompt or error, specify the source explicitly:
7376

7477
```bash
7578
azd extension install <id> --source <source-name>
7679
```
7780

78-
There is no priority or merge logic between sources — each extension must be unambiguously resolvable to a single source (unless `--source` is provided).
81+
There is no priority or merge logic between sources — the `--source` flag is the only way to disambiguate programmatically.
7982

8083
## Version Constraints
8184

8285
### Constraint Syntax
8386

84-
When installing an extension, you can specify a version constraint using the `--version` flag. `azd` uses the [Masterminds semver](https://github.com/Masterminds/semver) library to parse and evaluate constraints.
87+
Version constraints differ between the CLI and `azure.yaml`:
8588

86-
| Syntax | Example | Matches |
87-
|--------|---------|---------|
88-
| Exact | `1.0.0` | Only `1.0.0` |
89-
| Caret | `^1.2.3` | `>=1.2.3, <2.0.0` |
90-
| Tilde | `~1.2.3` | `>=1.2.3, <1.3.0` |
91-
| Range | `>=1.0.0,<2.0.0` | Explicit lower and upper bounds |
92-
| Latest | `latest` or omitted | Highest available version |
89+
#### CLI `--version` flag
9390

94-
Examples:
91+
The `azd extension install --version` flag accepts only an **exact version string** or **`latest`** (the default when omitted):
9592

9693
```bash
9794
# Install an exact version
9895
azd extension install my.extension --version 1.0.0
9996

100-
# Install the latest patch in the 1.2.x line
101-
azd extension install my.extension --version "~1.2.0"
97+
# Install the latest version (default)
98+
azd extension install my.extension --version latest
99+
azd extension install my.extension
100+
```
102101

103-
# Install any compatible version in the 1.x range
104-
azd extension install my.extension --version "^1.0.0"
102+
#### `azure.yaml` `requiredVersions.extensions`
105103

106-
# Install with explicit bounds
107-
azd extension install my.extension --version ">=1.0.0,<2.0.0"
104+
The `requiredVersions.extensions` section in `azure.yaml` supports the full semver constraint syntax provided by the [Masterminds semver](https://github.com/Masterminds/semver) library:
108105

109-
# Install the latest version (default)
110-
azd extension install my.extension
106+
| Syntax | Example | Matches |
107+
|--------|---------|---------|
108+
| Exact | `1.0.0` | Only `1.0.0` |
109+
| Caret | `^1.2.3` | `>=1.2.3, <2.0.0` |
110+
| Tilde | `~1.2.3` | `>=1.2.3, <1.3.0` |
111+
| Range | `>=1.0.0,<2.0.0` | Explicit lower and upper bounds |
112+
| Latest | `latest` or omitted | Highest available version |
113+
114+
```yaml
115+
requiredVersions:
116+
extensions:
117+
azure.ai.agents: ">=1.0.0"
118+
microsoft.azd.demo: "latest"
119+
my.custom.extension: "^2.0.0"
111120
```
112121
113122
### Version Selection
@@ -127,16 +136,17 @@ When `azd` resolves versions, it filters them into compatible and incompatible s
127136

128137
### Behavior
129138

130-
- If the highest version matching the user's constraint is **compatible**, it is installed normally.
131-
- If the highest version matching the user's constraint is **incompatible**, the install fails with guidance to upgrade `azd`.
139+
- `azd` filters out all versions whose `requiredAzdVersion` constraint is not satisfied by the running `azd` version, then selects the **highest remaining compatible version** that also matches the user's version constraint.
140+
- If a **newer incompatible version** exists beyond the selected version, `azd` shows a **warning** suggesting the user upgrade `azd`.
141+
- If **no compatible versions** remain after filtering, the install **fails** with guidance to upgrade `azd`. The install also fails if the user explicitly requests a specific version that is incompatible.
132142
- If `requiredAzdVersion` is **empty or cannot be parsed**, the version is treated as compatible (fail-open). This ensures that extensions without the field remain installable.
133143

134144
## Install Flow
135145

136146
Once a version is resolved, installation proceeds through these steps:
137147

138148
1. **Resolve version** — Apply the version constraint against available versions, filter by `azd` compatibility, and select the highest match.
139-
2. **Resolve dependencies** — If the extension declares dependencies, resolve each one recursively from configured sources. Dependencies follow the same conflict and version rules.
149+
2. **Resolve dependencies** — If the extension declares dependencies, resolve each one recursively from the **same source as the parent extension**. Cross-source dependency resolution is not performed. Dependencies follow the same version and compatibility rules.
140150
3. **Match platform artifact** — Find the artifact for the current OS and architecture. `azd` first looks for `<os>/<arch>` (for example, `linux/amd64` or `windows/amd64`). If no exact match is found, it falls back to `<os>` only (for example, `linux` or `windows`).
141151
4. **Download** — Fetch the artifact from its URL (HTTP/HTTPS) or copy from a local file path.
142152
5. **Validate checksum** — Verify the downloaded file against the published checksum. Supported algorithms are `sha256` and `sha512`.
@@ -167,7 +177,10 @@ Each entry maps an extension ID to a version constraint string. The same constra
167177

168178
- When `azd init` runs, it reads the `requiredVersions.extensions` map and installs each extension with the specified constraint.
169179
- If the constraint value is `null` or empty, `"latest"` is used (the highest available version is installed).
170-
- Extensions already installed at a satisfying version are not re-downloaded.
180+
- If an extension is already installed (any version), `azd init` **skips it** — it does not check whether the installed version satisfies the configured constraint.
181+
- `azd init` does **not** apply `requiredAzdVersion` compatibility filtering (unlike `azd extension install`).
182+
183+
> **Note:** These are known limitations in the current implementation and may be addressed in future versions.
171184

172185
## Caching
173186

@@ -179,7 +192,7 @@ Each entry maps an extension ID to a version constraint string. The same constra
179192
~/.azd/cache/extensions/<source-name>.json
180193
```
181194

182-
Each source has its own cache file, named after the source.
195+
Each source has its own cache file. The filename is derived from the source name by lowercasing it and replacing any characters outside `[a-zA-Z0-9._-]` with `_`. For example, a source named `"My Source!"` would be cached as `my_source_.json`.
183196

184197
### Default TTL
185198

@@ -247,7 +260,7 @@ Use pre-release suffixes for testing before a stable release:
247260
2.0.0-rc.1
248261
```
249262

250-
Pre-release versions are not selected by default when a user installs with `latest` — they must be requested explicitly with an exact version constraint.
263+
When `latest` is specified (or the version is omitted), `azd` selects the **highest semantic version**, which can be a pre-release if it sorts higher than the latest stable version. For semver range constraints in `azure.yaml`, pre-release versions are generally excluded unless the constraint itself explicitly includes a pre-release identifier.
251264

252265
## Troubleshooting
253266

0 commit comments

Comments
 (0)