Skip to content

[release/17.0] Keep the debugger install hint E2E fixture under the run root to fix Windows EBUSY teardown - #22022

Closed
Mitch Denny (mitchdenny) wants to merge 1 commit into
mitchdenny-backport-17-0-24-pr21916from
mitchdenny-backport-17-0-25-pr21918
Closed

Mitch Denny (mitchdenny) wants to merge 1 commit into
mitchdenny-backport-17-0-24-pr21916from
mitchdenny-backport-17-0-25-pr21918

Conversation

@mitchdenny

Copy link
Copy Markdown
Member

Description

Backport of #21918 to release/17.0 (cherry-picked from 07ccac0 with no modifications). Layer 25 of 55 in the release/17.0 backport stack; stacked on #22021.

Backport recommendation: No — Extension test flake.

Backport of #21918

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

…Windows EBUSY teardown (#21918)

## Description

**What failed:** The Windows VS Code extension E2E `edge-cases` shard
passed `shows debugger install guidance while the Aspire panel and
AppHost source are closed`, then failed its `after each` hook with
`EBUSY: resource busy or locked, rmdir
'...\workspace\DebuggerInstallHintApp'`. Examples: [run 41501727353 /
job
125481871205](https://github.com/microsoft/aspire/actions/runs/41501727353/job/125481871205)
and [run 40535943499 / job
122310290672](https://github.com/microsoft/aspire/actions/runs/40535943499/job/122310290672).

## Failure stats (14d, attempt 1)

`CI` workflow on microsoft/aspire, runs created 2026-10-25 06:28 →
2026-11-08 06:28 UTC, **attempt 1 only**. Denominator: attempt-1 jobs
that ran (success or failure). Hits: the failed job's log matches the
signature. Jobs that lost their runner, which have no log, are excluded.
Main runs have no reruns, so their flake check is the next main run of
the job.

| | |
|---|---|
| Signature | `EBUSY: resource busy or locked, rmdir
…DebuggerInstallHintApp` |
| Job | VS Code extension E2E (Windows, edge-cases) |
| main pushes: hits / runs | 0 / 153 (0.00%) |
| main pushes, 30d: hits / runs | 0 / 265 (0.00%). The 16 days before
the 14d window add 0 hits. |
| PR runs: hits / runs | 2 / 798 (0.25%); 0 PR-caused excluded |
| Combined rate | 2 / 951 = **0.21%** |
| Flake check | PR: 2/2 rerun hits passed on rerun (0 never rerun) |
| First / last hit | 2026-10-27 / 2026-11-02 |
| Still hitting main? | Last main hit: never. 79 main runs since the
last hit (2026-11-02), with 0 hits |
| Fix evidence | Local: source-contract test fails before and passes
after. The Windows EBUSY was not reproduced. This PR's CI: Windows
edge-cases passed 1/1. |

Failing attempt-1 jobs, most recent first (2 of 2 log-verified hits):

| Date (UTC) | Branch | Job | Signature excerpt |
|---|---|---|---|
| [2026-11-02
18:33](https://github.com/microsoft/aspire/actions/runs/41501727353/job/125481871205)
| `ievangelist-go-remove-experimental-flag` | VS Code extension E2E
(Windows, edge-cases) | `EBUSY: resource busy or locked, rmdir
'C:\Users\runneradmin\AppData\Local\Temp\aev-M7MFpn\workspace\DebuggerInstallHintA…`
|
| [2026-10-27
15:56](https://github.com/microsoft/aspire/actions/runs/40535943499/job/122310290672)
| `dependabot/github_actions/github-actions-ebbe822166` | VS Code
extension E2E (Windows, edge-cases) | `EBUSY: resource busy or locked,
rmdir
'C:\Users\runneradmin\AppData\Local\Temp\aev-8x6mbU\workspace\DebuggerInstallHintA…`
|

**Verdict: WEAK.** Only **2 hits** (both PR runs, both passed on rerun,
never on main). No hit since 2026-11-02 (79 main runs). The fix is not
validated against the actual lock.

<!-- /failure-stats -->

**Why:** The fixture AppHost starts DCP with `--detach` in the AppHost's
working directory, which is the generated project directory. DCP can
outlive the AppHost while it cleans up, so Windows keeps that directory
busy even after `aspire stop` succeeds and the AppHost process exits.
The in-session `removeGeneratedProject` rmdir then fails. In the second
run, the outer runner later logs the same lock as a non-blocking
warning, so the lock outlives the test.

**Fix:** This follows the #20289 pattern.
- The test now creates the fixture under the runner-owned
`ASPIRE_EXTENSION_E2E_RUN_ROOT` in a per-invocation
`.e2e-debugger-install-hint-<n>` directory, outside the workspace. The
workspace `aspire.config.json` still selects it: the CLI adds a
configured AppHost that sits outside the scan directory as a candidate.
- Teardown still stops the AppHost and restores the workspace config. It
no longer deletes the directory. `run-e2e.js` removes the run root after
VS Code and the session's processes exit, and it already tolerates
Windows locks.
- `createEmptyAppHostProject` takes an optional output root. The default
is unchanged, so other callers behave the same.
- A new source-contract test in `e2eLaunchProfile.test.ts` locks in the
cleanup ownership boundary.

## Confidence

- New test `keeps the debugger install hint fixture under the run root
and defers its deletion to the runner`:
- **Before** (E2E source changes reverted, test kept): fails with an
`AssertionError`.
  - **After**: passes.
- The full compiled `e2eLaunchProfile.test.js` suite passes (127 tests).
`tsc -p .`, `tsc -p tsconfig.e2e.json` and `eslint src` also pass.
- **Not run locally:** the Electron `vscode-test` unit suite and the
Windows E2E `edge-cases` shard. The EBUSY only reproduces on Windows.
This PR's CI runs that shard, which is the end-to-end check.

**How we stop this recurring:** Fixtures that run an AppHost now live
under the run root, and the runner deletes them. The contract test fails
if this test goes back to deleting its fixture in-session.

Refs #21600, #19282

## Checklist

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

**🤖 Posted by AspireAgent (AI Agent)**

Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 07ccac0)
@github-actions

This comment has been minimized.

@mitchdenny
Mitch Denny (mitchdenny) force-pushed the mitchdenny-backport-17-0-25-pr21918 branch from 05fe695 to 911dd8c Compare November 10, 2026 04:22
@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 -- 22022

Or

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

@mitchdenny

Copy link
Copy Markdown
Member Author

Approved for inclusion in release/17.0. Do not merge yet.

@github-actions

This comment has been minimized.

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.

2 participants