Skip to content

Harden VS Code extension E2E tests#18217

Open
adamint wants to merge 14 commits into
microsoft:mainfrom
adamint:adamint/harden-vscode-e2e-flakes
Open

Harden VS Code extension E2E tests#18217
adamint wants to merge 14 commits into
microsoft:mainfrom
adamint:adamint/harden-vscode-e2e-flakes

Conversation

@adamint

@adamint adamint commented Jun 15, 2026

Copy link
Copy Markdown
Member

Description

This hardens the VS Code extension E2E shards that have been flaky in recent CI runs.

The recurring actionable failures were mostly two patterns:

  • zero-to-running timed out waiting for an integrated-browser editor title containing the dashboard host even though the dashboard URL was known and the HTTP probe succeeded.
  • Several endpoint/browser checks relied on VS Code editor titles as the signal that navigation happened, which is fragile under runner load.

This PR removes brittle integrated-browser title waits where the test already has stronger HTTP/state coverage, makes the tree action browser command await simpleBrowser.show and return the resolved endpoint URL through the E2E bridge, changes the debug-dashboard build-failure test to assert the stable debug-console failure summary/log path and then verify the injected compiler symbol in that surfaced CLI log, forces Aspire CLI E2E output to English, writes E2E control payloads atomically, and retries mutable fixture file writes on Windows file-lock errors.

I also checked the other recent failing shards. The tree-actions and apphost-tree failures were clustered in a cancelled PR-specific run that failed with ASPIRE009 from a CLI bundle experiment. The one standalone discovery-configuration failure was a Windows EBUSY while writing .aspire/settings.json, which is covered by the retry helper here.

Validation:

cd extension
corepack yarn run compile-e2e
corepack yarn run lint
corepack yarn run test

corepack yarn run test finished with 877 passing and 1 pending.

Fixes # (issue)

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
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No

Reduce E2E flakes by removing brittle integrated-browser title waits where HTTP/state checks already prove readiness, checking build failure diagnostics via the CLI log path, forcing the CLI locale to English, and adding Windows-safe retries for mutable fixture files and atomic E2E control writes.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 15, 2026 17:25
@github-actions

github-actions Bot commented Jun 15, 2026

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 -- 18217

Or

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

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

This PR hardens VS Code extension E2E tests that were flaky in CI by addressing two main failure patterns: integrated-browser editor title waits timing out (replaced with HTTP/state coverage that already existed), and debug console text waits timing out for build failure symbols (replaced with log file validation). Additionally, it forces English CLI output, makes E2E control file writes atomic, and adds retry logic for Windows file-lock errors.

Changes:

  • Removes brittle waitForEditorTitle assertions in zeroToRunning and treeActions tests where HTTP probes already provide equivalent coverage, and validates build-failure symbols via the CLI log file rather than debug console text.
  • Adds atomic write (writeJsonFileAtomic) for E2E control payloads and retry-on-EBUSY/EPERM (writeFileWithRetry) for mutable fixture files to prevent Windows file-lock flakiness.
  • Sets DOTNET_CLI_UI_LANGUAGE: 'en' in the E2E CLI environment to prevent localized output from breaking text-matching assertions.
Show a summary per file
File Description
extension/scripts/run-e2e.js Adds DOTNET_CLI_UI_LANGUAGE: 'en' to the CLI environment
extension/src/test-e2e/helpers/assertions.ts Introduces writeJsonFileAtomic, renameFileWithRetry, isRetryableRenameError, and sleepSynchronously for atomic control file writes
extension/src/test-e2e/helpers/fixtures.ts Introduces writeFileWithRetry, isRetryableFileSystemError, and sleepSynchronously for retrying mutable fixture file writes on Windows
extension/src/test-e2e/zeroToRunning.e2e.test.ts Removes the flaky waitForEditorTitle(dashboardHost) assertion
extension/src/test-e2e/treeActions.e2e.test.ts Removes waitForEditorTitle import and usage for endpoint URL host check
extension/src/test-e2e/debugDashboard.e2e.test.ts Replaces debug console symbol wait with log-file-based validation via getLogPathFromDebugConsoleOutput and waitForLogFileText
extension/src/test/e2eLaunchProfile.test.ts Updates meta-test assertions to verify the new patterns (atomic writes, retry helpers, no editor title waits)

Copilot's findings

  • Files reviewed: 7/7 changed files
  • Comments generated: 0

adamint added 2 commits June 15, 2026 13:35
Keep the debug-dashboard sentinel assertion on the debug console flush path, and make the tree action browser-open command await simpleBrowser.show while returning the resolved endpoint URL through the E2E bridge.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Avoid waiting for compiler diagnostics to stream inline to the debug console. Assert the stable debug-console failure summary and log path, then verify the injected compiler symbol in the surfaced CLI log.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 15, 2026 17:40

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.

Copilot's findings

  • Files reviewed: 9/9 changed files
  • Comments generated: 0 new

Suppress intentional experimental interaction APIs in the generated E2E AppHost fixture so local fallback SDKs do not fail startup before tree-action coverage can run.

Also retry EBUSY during atomic E2E control-file renames and keep a lightweight debug-console compiler diagnostic assertion while validating the full injected symbol in the CLI log.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@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.

Assert terminal hyperlink output before parsing the debug-dashboard log path, so regressions fail with the intended message.

Scope the EBUSY meta-test to the atomic rename helper so it actually guards the Windows control-file rename retry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 15, 2026 18:24

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.

Copilot's findings

  • Files reviewed: 9/9 changed files
  • Comments generated: 1

Comment thread extension/src/test-e2e/helpers/fixtures.ts Outdated
@adamint adamint marked this pull request as ready for review June 15, 2026 18:36
Export the existing synchronous sleep helper from assertions and reuse it in fixture writes instead of maintaining a second Atomics.wait implementation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@adamint adamint marked this pull request as draft June 15, 2026 18:38
@adamint adamint marked this pull request as ready for review June 15, 2026 18:41
Copilot AI review requested due to automatic review settings June 15, 2026 18:41

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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@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.

@adamint adamint marked this pull request as draft June 15, 2026 19:41
adamint and others added 2 commits June 15, 2026 15:46
Use lightweight file-based secondary AppHost candidates for discovery-only E2E tests to avoid CI MSBuild contention, and wait for stopped AppHosts to disappear before deleting fixture directories.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assert restored discovery clears stale secondary AppHost candidates and retry EACCES for Windows fixture writes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 15, 2026 19:58

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.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new

Retry EBUSY for extension-side atomic state-file renames and give command-palette E2E enough timeout headroom for slow discovery diagnostics.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@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.

Avoid failing teardown when extension state is stale after the Aspire CLI has already stopped the AppHost. Wait on the captured AppHost PID instead, and force cleanup only when that process is still alive.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 15, 2026 20:38

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.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new

adamint and others added 2 commits June 15, 2026 16:54
Keep successful Aspire CLI stop teardown wait-only so stale extension state cannot terminate a recycled PID. If stop fails or times out, require the captured AppHost process to exit before reporting teardown success.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When Aspire CLI stop times out or reports a stop failure, use aspire ps --format json to confirm whether the AppHost is still visible before failing teardown. This keeps stale extension state from failing cleanup while preserving failure when the CLI still reports the AppHost running.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 15, 2026 21:04

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.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new

adamint and others added 2 commits June 15, 2026 17:19
Use aspire ps as the stop-failure authority, wait on the PID reported by ps, and re-check ps before treating teardown as complete. Also route AppHost source/config cleanup through retrying helpers so Windows file locks do not short-circuit cleanup.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 15, 2026 21:51

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.

Copilot's findings

  • Files reviewed: 12/12 changed files
  • Comments generated: 1

Comment on lines +340 to +341
}
async function waitForRunningAppHostProcessExitFromState(appHostPath: string, timeoutMs: number): Promise<void> {
@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.

Comment on lines +94 to +96
const openedEndpoint = await executeE2eControlCommand({ name: 'openInIntegratedBrowser', appHostPath, resourceName: 'e2e-worker' });
await waitForCommandOutcome('aspire-vscode.openInIntegratedBrowser', 'success', 60000, before);
assert.ok((await waitForEditorTitle(new URL(endpointUrl).host, 120000, { matchCase: false })).toLowerCase().includes(new URL(endpointUrl).host.toLowerCase()));
assert.strictEqual((openedEndpoint.result as { url?: string }).url, endpointUrl);

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.

This assertion verifies the endpoint is healthy, but it doesn’t prove the integrated browser actually opened the expected URL in VS Code. The test can still pass if openInIntegratedBrowser is a no-op or opens the wrong target, as long as the endpoint responds.

@adamint adamint marked this pull request as ready for review June 16, 2026 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants