Skip to content

Warn when VS Code uses an outdated Aspire CLI - #19670

Merged
Adam Ratzman (adamint) merged 31 commits into
mainfrom
ellahathaway-warn-outdated-aspire-cli
Sep 2, 2026
Merged

Warn when VS Code uses an outdated Aspire CLI#19670
Adam Ratzman (adamint) merged 31 commits into
mainfrom
ellahathaway-warn-outdated-aspire-cli

Conversation

@ellahathaway

@ellahathaway Ella Hathaway (ellahathaway) commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Description

This replaces the compatibility approach from closed PR #19447 with an update warning. It does not revive the pre-13.5 AppHost workaround and has no fixed minimum version or known-failure wording. Instead, VS Code warns when an Aspire CLI selected by an active extension operation is outdated for its installed published release lane.

For example, a stable 13.4.0 CLI warns when stable 13.5.2 is available.

The warning identifies the exact executable and offers Update Aspire CLI, which revalidates and updates that same resolved path and workspace target. Don't Show Again persists suppression for that exact path/version across extension sessions and concurrently open extension hosts.

Relates to #17354. This PR intentionally does not close the issue.

The implementation:

  • reports exact CLI use from command/debug gates, terminal commands, one-shot AppHost operations, external stop, ps, and describe;
  • keeps activation-time resolution and discovery silent;
  • reuses ConfigInfoProvider for one bounded, locale-independent aspire --version probe and structured aspire doctor --format json metadata;
  • uses Doctor's physical identityChannel, so stable accepts stable recommendations, daily/staging accept prerelease recommendations, and local/PR/run/default/unknown/cross-lane identities stay silent;
  • serializes and coalesces version probes by executable, serializes Doctor probes, samples an actively used CLI version at most every five minutes, caches successful update checks for six hours, and caps failed Doctor attempts for an unchanged version;
  • isolates recommendation state by resolution target, executable, and captured Doctor working directory;
  • shows at most one warning per exact normalized path/version during an extension session;
  • stores durable suppressions as append-only immutable marker files published atomically under extension global storage;
  • publishes a bounded notification claim before the final suppression read, while suppression publishes first and waits for earlier matching claims to dispatch, closing the normal cross-window snapshot race without a shared mutable lock;
  • reclaims dead, expired, future-dated, malformed, and reused-PID claim markers;
  • performs a fresh exact-version recheck before honoring a delayed update action;
  • preserves no-argument aspire-vscode.updateSelf behavior as window-scoped; and
  • cancels in-flight probes and suppresses continuations during disposal.

Scope and tradeoffs

aspire doctor is not stable-only: its existing CliUpdateNotifier considers stable and prerelease packages. When a prerelease CLI is behind stable, Doctor returns the stable recommendation first; the extension treats that cross-lane result as ineligible rather than suggesting a channel switch.

Doctor is currently the only structured update-status endpoint, so the extension bounds and caches that full command. Replacements are detected the next time an actual CLI operation occurs after the five-minute version sample expires; the extension does not keep separate heartbeat timers solely for update notices.

Suppression remains exact per normalized executable path/version. If a notification claim publishes first, suppression waits for its warning dispatch before completing. If suppression publishes first, every later claim sees the immutable marker and aborts. Claims are bounded so terminated or PID-reused extension hosts cannot wedge suppression indefinitely. An extension host suspended for the entire one-minute claim lifetime in the instruction-sized interval after final validation but before showWarningMessage can still dispatch that one already-in-flight warning after resuming; avoiding that adversarial boundary would require a long-lived OS/process-instance lock for an advisory notification. The durable suppression still prevents subsequent warnings.

UI evidence

VS Code warning for stable Aspire CLI 13.4.0 with stable 13.5.2 available and Update Aspire CLI and Don't Show Again actions

Captured from an isolated VS Code extension E2E run using a stable 13.4.0 CLI wrapper with stable 13.5.2 available. The displayed executable is under the generic C:\aev test root.

Validation

Current head: c9ae206478

  • corepack yarn run compile-tests
  • corepack yarn run unit-test --grep "outdatedCliNotifier|outdatedCliSuppressionStore": 19 passed
  • corepack yarn run lint
  • corepack yarn webpack
  • Isolated corrected UI screenshot E2E: 1 passed
  • Stable regression: 13.4.0 recommends and displays stable 13.5.2
  • Channel regressions: prerelease-ahead-of-stable, cross-lane silence, and unpublished identities
  • Multi-root regressions: exact-path update routing, target/working-directory recommendation isolation, bounded shared-path probes, and same-session notification reservation
  • Suppression regressions: two live notifiers observe a completed suppression; suppression after the final snapshot waits for earlier warning dispatch; concurrent stores preserve independent writes; dead, expired, future-dated, malformed, and reused-PID claims are reclaimed; expired claims do not display
  • Probe regressions: timeout, cancellation, process-tree termination, bounded retries, nonzero Doctor output, and --nologo fallback
  • Simplification: 25 changed files / 2,104 additions, down from 38 / 3,457
  • Current-head CI is running
  • All addressed review threads are resolved

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
    • No

Copilot AI balanced review requested due to automatic review settings August 25, 2026 17:28
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 19670

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 19670"

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds proactive warnings when VS Code uses an Aspire CLI older than 13.5.0.

Changes:

  • Probes resolved CLI versions and deduplicates warnings.
  • Triggers checks during active data, command, and debug operations.
  • Adds localized UI, unit tests, and E2E coverage.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
extension/src/utils/workspace.ts Emits resolved CLI operation events.
extension/src/utils/outdatedCliNotifier.ts Implements warning and update action.
extension/src/utils/configInfoProvider.ts Adds detailed CLI version probing.
extension/src/test/workspace.test.ts Tests resolution events.
extension/src/test/outdatedCliNotifier.test.ts Tests warning behavior.
extension/src/test/configInfoProvider.test.ts Tests version boundaries and failures.
extension/src/test/appHostDataRepository.test.ts Tests data activation callbacks.
extension/src/test-e2e/helpers/fixtures.ts Adds an outdated-CLI wrapper.
extension/src/test-e2e/cliPathRejectionNotification.e2e.test.ts Exercises warning and update UI.
extension/src/loc/strings.ts Adds localized strings.
extension/src/extension.ts Wires notifier activation.
extension/src/data/AppHostDataRepository.ts Reports data activation transitions.
extension/package.nls.json Defines localization resources.
extension/loc/xlf/aspire-vscode.xlf Updates generated translation input.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread extension/src/utils/outdatedCliNotifier.ts Outdated
Comment thread extension/src/utils/outdatedCliNotifier.ts Outdated
Copilot AI review requested due to automatic review settings August 25, 2026 17:43
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.

Comment thread extension/src/utils/outdatedCliNotifier.ts Outdated
Comment thread extension/src/extension.ts Outdated
@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Copilot AI review requested due to automatic review settings August 25, 2026 18:34
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings August 25, 2026 18:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated no new comments.

Suppressed comments (1)

extension/src/utils/outdatedCliNotifier.ts:75

  • This treats every workspace folder as an active CLI target. In contrast, active repository polling resolves only the window target for aspire ps, and folder targets only for running AppHosts being described. Opening the Aspire view in a multi-root workspace can therefore warn about (and offer to update) an outdated CLI configured in an unrelated folder that no active data source uses, contrary to the “actively selects a CLI” behavior above. Please derive the targets from the active polling/describe operations (or emit their actual resolutions) instead of enumerating all folders.
        const targets = [
            windowCliPathTarget,
            ...(vscode.workspace.workspaceFolders ?? []).map(workspaceFolderCliPathTarget),
        ];
        await Promise.all(targets.map(target => this.notifyIfOutdated(target)));

@github-actions

This comment has been minimized.

Comment thread extension/src/utils/outdatedCliNotifier.ts Outdated
@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Copilot AI review requested due to automatic review settings August 25, 2026 21:18
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.

Comment thread extension/src/utils/outdatedCliNotifier.ts Outdated
Serialize distinct Doctor probes, persist suppression keys without cross-window overwrite races, and avoid redundant Doctor retries.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Scope recommendations to the captured Doctor context and make suppression compaction safe across concurrent VS Code windows.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Use immutable global-storage files for cross-window suppression and bound filesystem failure retries without dropping confirmed update notifications.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Restore deploy and publish resolution ownership, remove redundant reporting and lifecycle machinery, trust Doctor's published channel, and consolidate probe and suppression state.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Notify the outdated CLI checker when an external AppHost stop directly resolves its executable.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Use the real latest stable 13.5.2 version in update-warning tests and UI evidence.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Coalesce probes by executable, serialize distinct paths, and keep update-action revalidation fresh.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Store suppressions as append-only atomic markers so concurrently open extension hosts cannot overwrite each other's choices.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Serialize the final suppression check and warning dispatch with suppression writes across extension hosts, while retaining in-session deduplication and recovering abandoned leases.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Transfer abandoned-lock cleanup through an atomically renamed recovery link so another extension host can safely resume if a cleaner exits mid-recovery.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Expire owner and cleanup leases so reused process IDs cannot permanently wedge CLI warning suppression, and fence expired notification claims before UI dispatch.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Publish notification claims before the final suppression read and publish suppressions before waiting for earlier claims, eliminating stale-writer recovery while preserving cross-window ordering.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Treat negative claim age as expired so wall-clock corrections cannot extend cross-window suppression claims beyond their bound.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Show the required installed identity channel in the structured CLI update metadata example.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Keep activation-time restore silent while reporting the exact CLI for forced restores, including retries queued behind active automatic work.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
Include bounded executable metadata in CLI identity so same-version replacements refresh update recommendations and invalidate stale warning actions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 06ff4fb7-3a0a-4a61-8653-8345b646778c
@ellahathaway
Ella Hathaway (ellahathaway) force-pushed the ellahathaway-warn-outdated-aspire-cli branch from f1edaea to 752fc2e Compare September 2, 2026 00:46
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Tests selector

0 / 99 PR test projects · 2 PR jobs · 0 advisory-only targets, from 27 changed files.

Selected PR test projects (0 / 99)

none — no PR-gated .NET test projects run for this change.

Selected PR jobs (2)

extension-e2e, extension-unit

Advisory workflow impact (0)

none


How these were chosen — grouped by what changed

Job reasons

Job Triggered by
extension-e2e extension/loc/xlf/aspire-vscode.xlf, extension/package.nls.json, extension/src/activation/registerCliCommands.ts, extension/src/commands/update.ts, extension/src/data/AppHostDataRepository.ts, extension/src/data/appHostCliRunner.ts, extension/src/data/appHostPsPoller.ts, extension/src/extension.ts, extension/src/loc/strings.ts, extension/src/services/AppHostStopper.ts, extension/src/test/appHostCliRunner.test.ts, extension/src/test/appHostDataRepository.test.ts, extension/src/test/appHostStopper.test.ts, extension/src/test/aspirePackageRestoreProvider.test.ts, extension/src/test/aspireTerminalProvider.test.ts, extension/src/test/configInfoProvider.test.ts, extension/src/test/outdatedCliNotifier.test.ts, extension/src/test/outdatedCliSuppressionStore.test.ts, extension/src/test/registerCliCommands.test.ts, extension/src/test/workspace.test.ts, extension/src/utils/AspirePackageRestoreProvider.ts, extension/src/utils/AspireTerminalProvider.ts, extension/src/utils/cliOperationResolution.ts, extension/src/utils/configInfoProvider.ts, extension/src/utils/outdatedCliNotifier.ts, extension/src/utils/outdatedCliSuppressionStore.ts, extension/src/utils/workspace.ts
extension-unit extension/loc/xlf/aspire-vscode.xlf, extension/package.nls.json, extension/src/activation/registerCliCommands.ts, extension/src/commands/update.ts, extension/src/data/AppHostDataRepository.ts, extension/src/data/appHostCliRunner.ts, extension/src/data/appHostPsPoller.ts, extension/src/extension.ts, extension/src/loc/strings.ts, extension/src/services/AppHostStopper.ts, extension/src/test/appHostCliRunner.test.ts, extension/src/test/appHostDataRepository.test.ts, extension/src/test/appHostStopper.test.ts, extension/src/test/aspirePackageRestoreProvider.test.ts, extension/src/test/aspireTerminalProvider.test.ts, extension/src/test/configInfoProvider.test.ts, extension/src/test/outdatedCliNotifier.test.ts, extension/src/test/outdatedCliSuppressionStore.test.ts, extension/src/test/registerCliCommands.test.ts, extension/src/test/workspace.test.ts, extension/src/utils/AspirePackageRestoreProvider.ts, extension/src/utils/AspireTerminalProvider.ts, extension/src/utils/cliOperationResolution.ts, extension/src/utils/configInfoProvider.ts, extension/src/utils/outdatedCliNotifier.ts, extension/src/utils/outdatedCliSuppressionStore.ts, extension/src/utils/workspace.ts

Selection computed for commit 752fc2e.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Session deduplication violates the documented path/version scope, and suppression refreshes can cause unbounded redundant filesystem reads.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

extension/src/utils/outdatedCliNotifier.ts:84

  • The suppression refresh runs before any shared in-flight work is consulted or populated. Concurrent first-use reports therefore all call readAll() in parallel—even for the same check key—and each call rereads every append-only marker; activation of many describe streams can create an unbounded O(reports × markers) filesystem burst before the version/Doctor queues help. Coalesce suppression refreshes globally behind one shared in-flight promise.
  • Files reviewed: 27/27 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread extension/src/utils/outdatedCliNotifier.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Executable replacement can produce duplicate warnings for the same path and version within one session.

Review details

Suppressed comments (1)

extension/src/utils/outdatedCliNotifier.ts:406

  • executableIdentity makes the session key change when the executable is replaced in place, so the same normalized path/version can display a second warning in one extension session. This contradicts the stated at-most-once guarantee; keep executable identity for recommendation invalidation, but reserve displayed notifications by path/version only (as the durable suppression key already does).
function getSessionNotificationKey(cli: CliVersionInfo): string {
    return `${getNotificationKey(cli.cliPath, cli.version)}\u0000${cli.executableIdentity}`;
}
  • Files reviewed: 27/27 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@aspire-repo-bot

Copy link
Copy Markdown
Contributor

Pull request created: #1608

Generated by PR Documentation Check · auto · 38.3 AIC · ⌖ 13.2 AIC · ⊞ 19.7K

@aspire-repo-bot

Copy link
Copy Markdown
Contributor

📝 Documentation has been drafted in microsoft/aspire.dev#1608 targeting release/13.6.

Added a new "Outdated CLI warning" note to src/frontend/src/content/docs/get-started/aspire-vscode-extension.mdx documenting the new VS Code warning notification (with Update Aspire CLI / Don't Show Again actions) shown when a selected Aspire CLI is outdated for its release lane, per triggered signal pr_body_has_cli_flag_mention (evidence: PR body's aspire --version/aspire doctor --format json mention).

Note

This draft PR needs human review before merging.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

🔍 CI Failure Analysis: Transient Infrastructure Failure

The CI build failed due to transient infrastructure issues.

Failed jobs:

  • Tests / Hosting.GitHub.Models / Hosting.GitHub.Models (windows-latest) — Process completed with exit code -1073741502 (0xC0000142 STATUS_DLL_INIT_FAILED) in post-test cleanup/upload steps (hang dump check, upload logs/results, CLI E2E recordings, summary generation) on windows-latest runner. Known transient Windows runner process-initialization failure unrelated to PR content (PR only touches VS Code extension TypeScript files). (transient-infra)
  • Tests / Hosting.Azure / Hosting.Azure (ubuntu-latest) — AzureSqlPrincipalReconciliationTests fail because SqlServerContainerFixture cannot bind Docker port 1433 (address already in use) on a shared CI runner. This is an environmental Docker networking conflict, not related to the PR's VS Code extension changes. (flaky-test)

If a rerun was not already requested automatically, visit the workflow run page to rerun the failed jobs manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants