Skip to content

fix failing windows ci#1

Merged
ealmloff merged 13 commits intomainfrom
fix-windows-ci
May 1, 2026
Merged

fix failing windows ci#1
ealmloff merged 13 commits intomainfrom
fix-windows-ci

Conversation

@ealmloff
Copy link
Copy Markdown
Member

@ealmloff ealmloff commented May 1, 2026

No description provided.

ealmloff and others added 13 commits May 1, 2026 12:01
CI shows the synthetic click reaching the right pixel above the calculator
button without registering as a press. The numeric hwnd/pid output isn't
enough to tell whether the click is hitting the inner CoreWindow, a stray
overlay, or a window that's not actually visible. Dump the class name, title,
visibility, iconic state, and root ancestor for every hwnd we touch (focus
target, pre-click target/foreground, post-click cursor target/foreground) so
the next CI run pinpoints what's actually receiving the input.
Diagnostics show the windows-11-arm runner boots with a UWP window titled
'Microsoft account' (separate process, z-above Calculator at the click
coordinate) that intercepts synthetic clicks. Calculator is correctly the
foreground window, but WindowFromPoint at the button's pixel returns the
popup's CoreWindow, so SendInput-based tests fail while UI Automation tests
(which go through the a11y tree, not z-order) pass. Add a workflow step that
enumerates top-level windows and kills the host process for any titled
'Microsoft account' before running the e2e tests.

Also reformat a touched eprintln to satisfy cargo fmt --check.
\$pid is a PowerShell automatic read-only variable holding the current
process id; assigning to it threw "Cannot overwrite variable PID because
it is read-only or constant" and aborted the dismissal step before any
blocker windows could be killed.
The workflow-level dismissal kills the popup that's present when CI starts,
but a fresh "Microsoft account" UWP popup respawns during the cargo build
and again z-stacks above Calculator at the click point — confirmed in the
last run by a new PID showing up in WindowFromPoint diagnostics. Add a
PowerShell helper on CalculatorGuard that enumerates top-level windows and
kills the host process for any titled "Microsoft account", and call it
right before the SendInput-based click so the cleanup happens in the
relevant time window.
The popup respawns faster than a single kill cycle can clear it. Loop the
window enumeration up to 5 times with brief sleeps, and additionally kill
any process named AccountsControlHost / WindowsHelloUI /
CloudExperienceHostBroker (the UWP hosts that typically display
'Microsoft account' UI). Add Write-Host logging so the next CI run shows
exactly what was killed and when.
The "Microsoft account" popup on the windows-11-arm runner respawns within
~500ms of being killed (confirmed by a fresh PID showing up in
WindowFromPoint after each PowerShell-based dismissal). PowerShell process
startup alone takes longer than that window, so the popup is back before
SendInput dispatches.

Move the dismissal in-process: enumerate top-level windows from Rust and
call ShowWindow(SW_HIDE) on any whose title matches a blocker. Hidden
windows aren't returned by WindowFromPoint and don't trigger a respawn
(unlike killing the host), so the click lands on Calculator. Runs in
microseconds instead of hundreds of ms.

The PowerShell-based dismiss_blocking_popups helper is no longer needed
and has been removed; the workflow's one-time popup kill stays as a
defense in depth for the long compile window.
The previous run revealed two "Microsoft account" windows in different
processes (Shell_OOBEProxy pid:9572 + Windows.UI.Core.CoreWindow pid:7556).
Hiding the first via EnumWindows didn't catch the second — likely because
it became visible only after the first was hidden, so a single enumeration
pass missed it.

Add a complementary pass driven by WindowFromPoint at the click coordinate:
walk up to the root window, hide it if its title is a blocker, retry up to
six times. This is more reliable because it asks "what's actually under the
click pixel right now" instead of relying on a snapshot of all top-levels.
Run both passes (title-based catches off-cursor popups; point-based catches
the one that's actually intercepting the click) before SendInput.
Last run hid 3 of the OOBE windows but a fourth — class
'UserOOBEWindowClass' with an empty title — was layered underneath and
took over the click target after the first three were hidden. Empty-title
windows can't be caught by title-only matching.

Generalize the helpers around a BlockerSpec { titles, classes } so we can
match either property. Add Shell_OOBEProxy and UserOOBEWindowClass as
class blockers; keep "Microsoft account" as the title blocker.
cargo fmt --check on linux-x64 reformatted two eprintlns and trimmed an
empty line; apply the same locally.
The previous run was green, confirming the approach works. Clean up the
patch so the CI workaround doesn't bleed into the public library API:

- Move BlockerSpec / hide_top_level_blockers / hide_blockers_at_point and
  the supporting helpers from src/platform/msft.rs into the test file.
  They're CI-only — only this test needs them — so they shouldn't live in
  userspace code or be re-exported.
- Restore mouse_click_at and focus_window to their pre-debug shape (drop
  the eprintln! diagnostics that were only there to identify what was
  blocking the click).
- Remove the describe_window helper and the imports it pulled in
  (GetClassNameW, GetWindowTextW, IsIconic, IsWindowVisible, GA_ROOT,
  GetAncestor, EnumWindows, ShowWindow, SW_HIDE).
- Drop the workflow-level "Dismiss Windows blocker popups" step. The test
  now handles dismissal itself, much faster and more thoroughly than the
  workflow's one-shot kill could.

Net: ~250 lines deleted, ~90 added — and all of the runtime CI-only logic
lives next to the only test that needs it.
@ealmloff ealmloff merged commit ed44e3d into main May 1, 2026
11 checks passed
@ealmloff ealmloff deleted the fix-windows-ci branch May 5, 2026 19:35
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.

1 participant