Skip to content

Commit 89b6f78

Browse files
Recommend the VS Code extension in aspire doctor (#18624)
* Add doctor check recommending the VS Code extension `aspire doctor` now detects when VS Code is present but the Aspire VS Code extension (microsoft-aspire.aspire-vscode) is not installed, and surfaces a warning recommending installation under a new "Development tools" category. - Add VsCodeExtensionCheck that reuses existing VS Code presence signals (TERM_PROGRAM + code/code-insiders on PATH) and scans the extension directories for the installed extension folder. - Add "devtools" category with rendering/order wiring and resource strings. - Expose vsCodeInstalled/extensionInstalled/extensionId in JSON metadata. - Add unit tests and update cli-output-formats spec. Fixes #18300 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Address PR review: ignore inaccessible extension dirs and add default-home test Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Address code-review findings for VS Code extension doctor check - Inject command resolver into Detect so the PATH-based VS Code detection fallback is deterministically testable. - Make VSCODE_EXTENSIONS override exclusive (yield break) to avoid a false 'installed' result from default roots. - Reset EnumerationOptions.AttributesToSkip to None so extension folders with unexpected attributes are not skipped. - Require a digit after the '<id>-' prefix so a different extension whose id starts with ours is not matched. - Fix doctor JSON sample warnings count (1 -> 2) in cli-output-formats.md. - Add tests: per-root detection, override exclusivity, PATH-fallback, not-installed, prefix-boundary, and extensionId metadata assertion. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Refactor VsCodeExtensionCheck to sibling commandResolver DI pattern Replace the Func<VsCodeExtensionDetection> factory testing seam with the commandResolver-injection convention used by the sibling environment checks (e.g. TypeScriptAppHostToolingCheck). Real dependencies are now stored as fields and the CheckAsync tests flow through the real detection wiring instead of injecting canned detection results. Also extract IsVersionedExtensionFolder as a named predicate. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Add test for non-existent extensions directory resilience Covers the DirectoryContainsExtension Directory.Exists guard: when VSCODE_EXTENSIONS points at a path that does not exist, detection must report the extension missing without throwing. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Address PR review: aka.ms link, two return paths, TemporaryWorkspace, whitespace - Switch MarketplaceUrl to https://aka.ms/aspire/vscode-extension redirect (and docs spec) - Refactor CheckAsync into distinct pass/warning return paths - Use shared TemporaryWorkspace helper in tests instead of a private temp-dir class - Strip trailing whitespace on added Designer.cs separator lines Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Title-case Development Tools category header for consistency Match the title-cased sibling category headers (.NET SDK, Container Runtime, Environment). Regenerated xlf files via UpdateXlf. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 74130cb commit 89b6f78

21 files changed

Lines changed: 827 additions & 1 deletion

docs/specs/cli-output-formats.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,18 +451,33 @@ The JSON form includes secret values. Do not redirect it to logs or files unless
451451
"message": "Container runtime is not running.",
452452
"fix": "Start Docker Desktop.",
453453
"link": "https://learn.microsoft.com/dotnet/aspire/"
454+
},
455+
{
456+
"category": "devtools",
457+
"name": "vscode-extension",
458+
"status": "warning",
459+
"message": "VS Code is installed, but the Aspire extension is not installed",
460+
"fix": "Install the Aspire extension from the VS Code Marketplace for an integrated Aspire experience.",
461+
"link": "https://aka.ms/aspire/vscode-extension",
462+
"metadata": {
463+
"vsCodeInstalled": true,
464+
"extensionInstalled": false,
465+
"extensionId": "microsoft-aspire.aspire-vscode"
466+
}
454467
}
455468
],
456469
"summary": {
457470
"passed": 2,
458-
"warnings": 1,
471+
"warnings": 2,
459472
"failed": 0
460473
}
461474
}
462475
```
463476

464477
`status` is one of `pass`, `warning`, or `fail`. Individual checks can include `details`, `fix`, `link`, or command-specific `metadata`.
465478

479+
The `devtools` category surfaces development-tooling recommendations. The `vscode-extension` check only appears when VS Code is detected: it reports `warning` when the [Aspire VS Code extension](https://aka.ms/aspire/vscode-extension) is missing and `pass` when it is installed. Its `metadata` exposes `vsCodeInstalled` (bool), `extensionInstalled` (bool), and `extensionId` (string).
480+
466481
### `aspire config info`
467482

468483
`aspire config info --json` is a hidden tooling command that emits configuration paths, feature metadata, settings schemas, and advertised CLI capabilities:

src/Aspire.Cli/Commands/DoctorCommand.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ private static string GetCategoryHeader(string category)
228228
"apphost" => DoctorCommandStrings.AppHostCategoryHeader,
229229
"container" => DoctorCommandStrings.ContainerCategoryHeader,
230230
"environment" => DoctorCommandStrings.EnvironmentCategoryHeader,
231+
"devtools" => DoctorCommandStrings.DevelopmentToolsCategoryHeader,
231232
_ => category
232233
};
233234
}
@@ -241,6 +242,7 @@ private static int GetCategoryOrder(string category)
241242
"sdk" => 2,
242243
"container" => 3,
243244
"environment" => 4,
245+
"devtools" => 5,
244246
_ => 99
245247
};
246248
}

src/Aspire.Cli/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,7 @@ internal static async Task<IHost> BuildApplicationAsync(string[] args, CliStartu
592592
builder.Services.AddSingleton<IEnvironmentCheck, DeprecatedAgentConfigCheck>();
593593
builder.Services.AddSingleton<IEnvironmentCheck, LegacySettingsFileCheck>();
594594
builder.Services.AddSingleton<IEnvironmentCheck, PendingMigrationsCheck>();
595+
builder.Services.AddSingleton<IEnvironmentCheck, VsCodeExtensionCheck>();
595596
builder.Services.AddSingleton<IEnvironmentChecker, EnvironmentChecker>();
596597

597598
// MCP server transport factory - creates transport only when needed to avoid

src/Aspire.Cli/Resources/DoctorCommandStrings.Designer.cs

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Aspire.Cli/Resources/DoctorCommandStrings.resx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,18 @@
8282
<data name="EnvironmentCategoryHeader" xml:space="preserve">
8383
<value>Environment</value>
8484
</data>
85+
<data name="DevelopmentToolsCategoryHeader" xml:space="preserve">
86+
<value>Development Tools</value>
87+
</data>
88+
<data name="VsCodeExtensionInstalledMessage" xml:space="preserve">
89+
<value>Aspire extension for VS Code is installed</value>
90+
</data>
91+
<data name="VsCodeExtensionMissingMessage" xml:space="preserve">
92+
<value>VS Code is installed, but the Aspire extension is not installed</value>
93+
</data>
94+
<data name="VsCodeExtensionMissingFix" xml:space="preserve">
95+
<value>Install the Aspire extension from the VS Code Marketplace for an integrated Aspire experience.</value>
96+
</data>
8597
<data name="SummaryFormat" xml:space="preserve">
8698
<value>Summary: {0} passed, {1} warnings, {2} failed</value>
8799
</data>

src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.cs.xlf

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.de.xlf

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.es.xlf

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.fr.xlf

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.it.xlf

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)