Warn when VS Code uses an outdated Aspire CLI - #19670
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 19670Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 19670" |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
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.
This comment has been minimized.
This comment has been minimized.
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
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)));
This comment has been minimized.
This comment has been minimized.
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
This comment has been minimized.
This comment has been minimized.
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
f1edaea to
752fc2e
Compare
Tests selector0 / 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)
Advisory workflow impact (0)none How these were chosen — grouped by what changedJob reasons
Selection computed for commit |
There was a problem hiding this comment.
🟡 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
There was a problem hiding this comment.
🔵 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
executableIdentitymakes 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
|
Pull request created: #1608
|
|
📝 Documentation has been drafted in microsoft/aspire.dev#1608 targeting Added a new "Outdated CLI warning" note to Note This draft PR needs human review before merging. |
|
🔍 CI Failure Analysis: Transient Infrastructure Failure The CI build failed due to transient infrastructure issues. Failed jobs:
If a rerun was not already requested automatically, visit the workflow run page to rerun the failed jobs manually. |
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.0CLI warns when stable13.5.2is 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:
ps, anddescribe;ConfigInfoProviderfor one bounded, locale-independentaspire --versionprobe and structuredaspire doctor --format jsonmetadata;identityChannel, so stable accepts stable recommendations, daily/staging accept prerelease recommendations, and local/PR/run/default/unknown/cross-lane identities stay silent;aspire-vscode.updateSelfbehavior as window-scoped; andScope and tradeoffs
aspire doctoris not stable-only: its existingCliUpdateNotifierconsiders 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
showWarningMessagecan 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
Captured from an isolated VS Code extension E2E run using a stable
13.4.0CLI wrapper with stable13.5.2available. The displayed executable is under the genericC:\aevtest root.Validation
Current head:
c9ae206478corepack yarn run compile-testscorepack yarn run unit-test --grep "outdatedCliNotifier|outdatedCliSuppressionStore": 19 passedcorepack yarn run lintcorepack yarn webpack13.4.0recommends and displays stable13.5.2--nologofallbackChecklist