[ci-fix-net11] De-flake DropEventCoordinates: retry until the drop reports valid positive coordinates - #36027
Conversation
…t 1/5) DropEventCoordinates is intermittently flaky on iOS 18.5: the retry loop accepted the first parseable drop reading even when the synthesized gesture landed with degenerate (0,0)/negative coordinates, which then failed the strictly-positive assertion. A degenerate drop also still fires OnDrop and moves "Blue" into the target layout, so a naive retry dragged within the same layout and was ignored. De-flake without weakening any assertion: - Tighten the loop success condition to the same positive-coordinate check the test already asserts, so an invalid first reading triggers a retry instead of a hard failure. - Reset to a clean state (ResetButton) between retries so each retry is a valid cross-layout drag. No assertions removed/weakened, no timeout bumped, no [Retry]/[Ignore] added. Refs: #35981 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The net11.0 split-validation run (Run 10) succeeded — it opened draft PR #36027 against net11.0 with a clean 1-file de-flake, proving base-branch: net11.0 yields a small transport patch (well under the 10 MB cap that blocked the main-based path). Removes the TEMP canary scaffolding now that validation is complete: - push: branches:[pureween/bookish-garbanzo] trigger - max-daily-ai-credits: 20000 override - Step 0 single-issue #35981 override blockquote - create-pull-request max: 1 -> 3 ci-status-fix-net11.md now mirrors ci-status-fix.md's production shape: schedule + workflow_dispatch only, no credits override, max: 3, scoped to ci-scan-net11 against net11.0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run maui-pr-uitests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
…#35927) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## What this PR adds Two new agentic workflows that walk open CI-failure tracking issues filed by the existing scanners and open draft `[ci-fix]` PRs against the matching branch: - `.github/workflows/ci-status-fix.md` — processes `[ci-scan]` issues, opens PRs against **`main`**. - `.github/workflows/ci-status-fix-net11.md` — processes `[ci-scan-net11]` issues, opens PRs against **`net11.0`**. They are the natural counterpart to the existing `ci-status-main.md` / `ci-status-net11.md` detection workflows: one pair identifies, the other proposes a fix. **No KBE / Build Analysis integration** — just identify → auto-fix PR, as requested. Also includes two small, surgical prompt edits to both scanner files so the fixers can trust what they emit. ## Why two workflows instead of one The fixer logic is identical for both branches; the split is forced by a gh-aw transport constraint, not by behavior. gh-aw always generates a "transport patch" for its `create-pull-request` safe-output **relative to a single static `base-branch`**, and `max-patch-size` is hard-capped at **10 MB** by the gh-aw schema (raising it past 10 MB is a compile error). The `main` ↔ `net11.0` divergence is ~22 MB / ~1,000 files, so a one-file `net11.0` fix built against a `main` base produces a ~22 MB transport patch and is unconditionally rejected (file-count guard, then size). Because `base-branch` is one static value per workflow, each base needs its own workflow. With `base-branch: net11.0`, gh-aw builds the transport patch relative to `net11.0`, so the patch is just the fix's own delta. This was validated live (see below): the net11.0 fixer opened a clean **1-file** draft PR against `net11.0`. ## Design highlights **Each workflow is hard-pinned to exactly one base branch, enforced at three layers.** 1. **gh-aw declarative gate**: `safe-outputs.create-pull-request.base-branch` pins the base (`main` / `net11.0`), and `allowed-base-branches` (`[main]` / `[net11.0]`) makes gh-aw reject any other base. 2. **Prompt rule**: the agent only processes the matching label (`ci-scan` / `ci-scan-net11`) and checks out `origin/<branch>` (Step 5.2) before authoring, so the transport patch and the downstream push are both exactly the one-file fix delta. 3. **Self-check before emission**: the agent greps its own PR body for `Target branch: <branch>` and confirms `base` matches; mismatch aborts. **Iterative, capped at 5 attempts per tracking issue.** Attempt count comes from a live GitHub PR search for `"Refs: dotnet/maui#<N>"` in closed-unmerged `[ci-fix]` PRs (GitHub is the durable store — no per-run state needed). After the 5th closed-unmerged attempt the workflow stops and defers to humans (the open tracking issue is the hand-off surface). A dedicated `[ci-fix][needs-human]` hand-off PR is planned but **currently deferred** (Step 6 records a skip and emits no PR). Each attempt reads prior closed PRs' approaches and close comments and must propose a substantively different approach. **"Is it actually fixed?" check.** Before any fix attempt, the agent fetches the latest completed build of the failing pipeline on the target branch and `grep -F`s the issue's failure signature against the leaf-log output. Zero hits → silently skips ("appears fixed in latest build"). Tracking issue closure stays a human decision. **De-flake capability for intermittent test failures.** A flakiness probe classifies a reproducing failure as (a) infra → skip, (b) test-quality → de-flake PR, or (c) product-masking → product fix / hand-off. A de-flake replaces sleeps/races with condition waits and tightened assertions; it **never** adds `[Ignore]` / `[Retry]`, weakens assertions, or bumps timeouts. **Visual-regression filter is the first gate.** Silently skips any issue whose title, body, error message, or failed task names match `screenshot` / `snapshot` / `visual diff` / `baseline image` / `VerifyScreenshot` / etc. gh-aw can't judge visual diffs and must never modify baseline images. **Never mutes a test.** Stages with `[ActiveIssue]`, `Skip = "..."`, `[SkipOnPlatform]`, csproj `<*Incompatible>` / `<ExcludeFromTestRun>`, or edits to baseline images under `TestAssets` / `Snapshots` / `Baselines` are detected and rejected. If the only candidate fix is a mute, the run records a skip and stops. **MAUI area bounds.** Compile / XAML breaks are in bounds (≤ 20 lines, single file when possible). Device-test and UI-test failures (past the visual-regression gate) become `help`-only PRs or de-flakes. Handler lifecycle, threading, safe-area, perf hot-paths, Gradle/Maven feed, and infra failures are skipped — too risky for an autonomous fix. **Outputs only via `safe-outputs`.** Tracking issues are locked so no comments are possible. `draft: true`, `max: 3` PRs per run, `environment: gh-aw-agents` gating on the write-capable job, `allowed-files` restricts to `src/Core/**`, `src/Controls/**`, `src/Essentials/**`, `src/BlazorWebView/**`, `src/TestUtils/**`, `src/Templates/**`, `**/PublicAPI.Unshipped.txt` (which already excludes `.github/**`). ## Validated live The net11.0 workflow was run end-to-end against a real `[ci-scan-net11]` issue (#35981, a flaky `DropEventCoordinates` iOS 18.5 drag-and-drop test). It opened draft PR **#36027** targeting `net11.0` with a clean **1-file** de-flake (reset-between-retries + a tightened positive-coordinate assertion; no banned mute/retry patterns) and correct body markers (`Refs`, `Target branch: net11.0`, `Attempt 1/5`, `Flake class: test-quality`). #36027 is left open as a genuine candidate fix for maintainers to review — it proves the `base-branch: net11.0` split produces a small, in-cap transport patch. ## Two small scanner edits (so the fixers can rely on what they emit) Both `ci-status-main.md` and `ci-status-net11.md`: 1. **Mandatory `Build ID: <integer>` line** in the issue body template. The fixer requires it as a field gate (skipping any issue missing it) and cites it as the *original failing build* in its PR audit trail; the existing `Build: <URL>` line is opaque to grep. (The reproduce-check itself re-fetches the *latest* build of the pipeline.) 2. **Match-count gate** requiring the scanner to verify its own primary error substring actually appears in the fetched failure log before filing, and embed the result as a second hidden marker: ``` <!-- ci-scan-match-count: N hits in failure.log --> ``` Issues with 0 matches are not filed. This blocks hallucinated signatures from ever entering the fixers' work lists. The substring is treated as untrusted data — it is written to a pattern file via a fresh per-run random-delimiter single-quoted heredoc and matched with `grep -F -f` (never interpolated into a shell command), mirroring the injection-proof pattern the fixers use. ## Lifecycle and stop conditions | State | Action | |---|---| | Open `[ci-fix]` PR already exists for the issue | Skip — human owns the PR | | Merged `[ci-fix]` PR exists | Skip — fix already landed | | Open human PR (non-`agentic-workflows` label) references the issue | Skip — human is on it | | `attempt_count < 5` and signature still reproduces | Open attempt N+1 | | `attempt_count >= 5` | Stop and defer to humans; never retry (dedicated `[ci-fix][needs-human]` PR deferred — see Step 6) | | `attempt_count` search inconclusive (API error / `incomplete_results`) | Skip — cannot safely confirm the cap | | Latest build no longer reproduces the signature | Skip — "appears fixed" | | Issue body missing required fields (`Build ID`, fingerprint, error block) | Skip — scanner needs prompt update | | Only candidate fix is a mute | Skip | | Only candidate fix modifies visual baselines | Skip | | No novel approach producible vs prior attempts | Skip — defer to next tick | ## Files - **NEW**: `.github/workflows/ci-status-fix.md` — main-branch fixer (`base-branch: main`) - **NEW**: `.github/workflows/ci-status-fix.lock.yml` — generated by `gh aw compile` - **NEW**: `.github/workflows/ci-status-fix-net11.md` — net11.0-branch fixer (`base-branch: net11.0`) - **NEW**: `.github/workflows/ci-status-fix-net11.lock.yml` — generated by `gh aw compile` - **EDIT**: `.github/workflows/ci-status-main.md` — `Build ID` line + match-count gate - **EDIT**: `.github/workflows/ci-status-net11.md` — `Build ID` line + match-count gate `gh aw compile` passes cleanly on both new workflows (0 errors, 0 warnings). ## Things this PR explicitly does NOT do - Does **not** integrate Build Analysis / KBE in any form. - Does **not** add a feedback / KPI workflow (could be a follow-up if maintainers want one — the marker blocks in PR bodies are designed to make it easy). - Does **not** read PR review comments as instructions — the integrity gate filters them and the agent never treats them as authoring input. - Does **not** close tracking issues — closure stays a human decision. - Does **not** modify any production source code in this PR; workflow-only change. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
MauiBot
left a comment
There was a problem hiding this comment.
AI Review Summary
@github-actions[bot] — new AI review results are available based on this last commit:
eb3c2f0. To request a fresh review after new comments or commits, comment/review rerun.
🗂️ Review Sessions — click to expand
🚦 Gate — Test Before & After Fix
Gate Result: ⚠️ INCONCLUSIVE
Platform: ANDROID
⚠️ verify-tests-fail.ps1exited before writing a verification report. Diagnostics below.
Exit code: 3
Artifacts written before exit:
test-failure-DragAndDropUITests.log(8.6 KB)verification-log.txt(0.2 KB)
Gate output log (last 60 lines)
07-05 14:43:02.457 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/DragStartRelativeScreen'
07-05 14:43:02.597 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/TargetView'
07-05 14:43:02.628 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/TargetView'
07-05 14:43:03.301 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/GoButton'
07-05 14:43:03.761 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/LabelDragElement'
07-05 14:43:03.925 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/LabelDragElement'
07-05 14:43:04.429 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/DragTarget'
07-05 14:43:06.552 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/LabelDragElement'
07-05 14:43:07.079 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/DragTarget'
07-05 14:43:09.275 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/DragStartEventsLabel'
07-05 14:43:09.720 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/DragStartEventsLabel'
07-05 14:43:09.736 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/DragOverEventsLabel'
07-05 14:43:09.745 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/DragOverEventsLabel'
07-05 14:43:09.761 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/DropCompletedEventsLabel'
07-05 14:43:09.769 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/DropCompletedEventsLabel'
07-05 14:43:09.784 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/DropEventsLabel'
07-05 14:43:09.791 22849 22881 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/DropEventsLabel'
07-05 14:43:09.956 10916 12038 I ActivityManager: Force stopping com.microsoft.maui.uitests appid=10154 user=0: from pid 23138
07-05 14:43:09.957 10916 12038 I ActivityManager: Killing 22960:com.microsoft.maui.uitests/u0a154 (adj 0): stop com.microsoft.maui.uitests due to from pid 23138
07-05 14:43:09.962 10916 12038 W ActivityTaskManager: Force removing ActivityRecord{462f2b1 u0 com.microsoft.maui.uitests/.MainActivity t27 f}}: app died, no saved state
07-05 14:43:10.750 10916 11122 D AutofillSession: handling death of Token{c32e158 ActivityRecord{462f2b1 u0 com.microsoft.maui.uitests/.MainActivity t-1 f}}} when saving=false
07-05 14:43:10.965 10916 11903 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.microsoft.maui.uitests/.MainActivity} from uid 2000
07-05 14:43:11.319 10916 10945 I ActivityManager: Start proc 23158:com.microsoft.maui.uitests/u0a154 for pre-top-activity {com.microsoft.maui.uitests/com.microsoft.maui.uitests.MainActivity}
07-05 14:43:12.673 23158 23158 D DOTNET : AndroidCryptoNative_InitLibraryOnLoad: jint AndroidCryptoNative_InitLibraryOnLoad(JavaVM *, void *) in /__w/1/s/src/runtime/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c
07-05 14:43:12.544 23158 23158 W ft.maui.uitests: type=1400 audit(0.0:3452): avc: denied { read } for name="memory.use_hierarchy" dev="cgroup" ino=15 scontext=u:r:untrusted_app:s0:c154,c256,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=com.microsoft.maui.uitests
07-05 14:43:12.552 23158 23158 W ft.maui.uitests: type=1400 audit(0.0:3453): avc: denied { read } for name="memory.limit_in_bytes" dev="cgroup" ino=10 scontext=u:r:untrusted_app:s0:c154,c256,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=com.microsoft.maui.uitests
07-05 14:43:13.857 23158 23158 W ft.maui.uitest: ClassLoaderContext classpath size mismatch. expected=15, found=2 (DLC[];PCL[base.apk*1604962157:base.apk!classes2.dex*892330443:base.apk!classes3.dex*4132208247:base.apk!classes4.dex*1189418256:base.apk!classes5.dex*603145810:base.apk!classes6.dex*3249919879:base.apk!classes7.dex*4272712489:base.apk!classes8.dex*2286867051:base.apk!classes9.dex*1990284164:base.apk!classes10.dex*1304220855:base.apk!classes11.dex*2113592843:base.apk!classes12.dex*567841885:base.apk!classes13.dex*1284683107:base.apk!classes14.dex*287099224:base.apk!classes15.dex*3381648213]{PCL[/system/framework/org.apache.http.legacy.jar*1452144318]#PCL[/system/framework/com.android.location.provider.jar*4177849200]#PCL[/system/framework/com.android.media.remotedisplay.jar*1128910120]#PCL[/system_ext/framework/androidx.window.sidecar.jar*709954415]} | DLC[];PCL[/data/app/~~RZLOTliMdNj5QfXUcOdKrg==/com.microsoft.maui.uitests-i8zhO1bEOvLPhEo8dovNoA==/base.apk*1230500770:/data/app/~~RZLOTliMdNj5QfXUcOdKrg==/com.microsoft.maui.uitests-i8zhO1bEOvLPhEo8dovNoA==/base.apk!classes2.dex*2427112916]{PCL[/system/framework/org.apache.http.legacy.jar*1452144318]#PCL[/system_ext/framework/androidx.window.sidecar.jar*709954415]})
07-05 14:43:13.858 23158 23158 W ft.maui.uitest: Found duplicated class when checking oat files: 'Landroid/support/v4/graphics/drawable/IconCompatParcelizer;' in /data/app/~~AIF_OzOUmmrcbLrC9vEziw==/com.google.android.gms-7fnw_1FzPb3XzJl6tPuy6w==/split_MapsDynamite_installtime.apk!classes2.dex and /data/app/~~RZLOTliMdNj5QfXUcOdKrg==/com.microsoft.maui.uitests-i8zhO1bEOvLPhEo8dovNoA==/base.apk
07-05 14:43:14.735 11555 15781 I PhenotypeResourceReader: unable to find any Phenotype resource metadata for com.microsoft.maui.uitests
07-05 14:43:16.000 10916 10943 D ArtManagerInternalImpl: /data/misc/iorapd/com.microsoft.maui.uitests/1/com.microsoft.maui.uitests.MainActivity/compiled_traces/compiled_trace.pb doesn't exist
07-05 14:43:16.305 23158 23242 W ft.maui.uitest: ClassLoaderContext classpath size mismatch. expected=15, found=2 (DLC[];PCL[base.apk*1604962157:base.apk!classes2.dex*892330443:base.apk!classes3.dex*4132208247:base.apk!classes4.dex*1189418256:base.apk!classes5.dex*603145810:base.apk!classes6.dex*3249919879:base.apk!classes7.dex*4272712489:base.apk!classes8.dex*2286867051:base.apk!classes9.dex*1990284164:base.apk!classes10.dex*1304220855:base.apk!classes11.dex*2113592843:base.apk!classes12.dex*567841885:base.apk!classes13.dex*1284683107:base.apk!classes14.dex*287099224:base.apk!classes15.dex*3381648213]{PCL[/system/framework/org.apache.http.legacy.jar*1452144318]#PCL[/system/framework/com.android.location.provider.jar*4177849200]#PCL[/system/framework/com.android.media.remotedisplay.jar*1128910120]#PCL[/system_ext/framework/androidx.window.sidecar.jar*709954415]} | DLC[];PCL[/data/app/~~RZLOTliMdNj5QfXUcOdKrg==/com.microsoft.maui.uitests-i8zhO1bEOvLPhEo8dovNoA==/base.apk*1230500770:/data/app/~~RZLOTliMdNj5QfXUcOdKrg==/com.microsoft.maui.uitests-i8zhO1bEOvLPhEo8dovNoA==/base.apk!classes2.dex*2427112916]{PCL[/system/framework/org.apache.http.legacy.jar*1452144318]#PCL[/system_ext/framework/androidx.window.sidecar.jar*709954415]})
07-05 14:43:16.525 23158 23242 W ft.maui.uitest: Found duplicated class when checking oat files: 'Landroid/support/v4/graphics/drawable/IconCompatParcelizer;' in /data/app/~~AIF_OzOUmmrcbLrC9vEziw==/com.google.android.gms-7fnw_1FzPb3XzJl6tPuy6w==/split_GoogleCertificates_installtime.apk!classes2.dex and /data/app/~~RZLOTliMdNj5QfXUcOdKrg==/com.microsoft.maui.uitests-i8zhO1bEOvLPhEo8dovNoA==/base.apk
07-05 14:43:16.538 10916 10943 I ActivityTaskManager: Displayed com.microsoft.maui.uitests/.MainActivity: +5s34ms
07-05 14:43:16.665 23158 23231 I PhClient: Shared storage file not found for com.google.android.gms.clearcut_client#com.microsoft.maui.uitests
07-05 14:43:16.666 23158 23231 I PhClient: Unable to retrieve flag snapshot for com.google.android.gms.clearcut_client#com.microsoft.maui.uitests, using defaults.
07-05 14:43:16.733 23158 23231 I PhClient: Shared storage file not found for com.google.android.libraries.consentverifier#com.microsoft.maui.uitests
07-05 14:43:16.738 23158 23231 I PhClient: Unable to retrieve flag snapshot for com.google.android.libraries.consentverifier#com.microsoft.maui.uitests, using defaults.
ℹ️ Full device log: /home/vsts/work/1/s/CustomAgentLogsTmp/UITests/android-device.log
═══════════════════════════════════════════════════════
✅ All tests passed
╔═══════════════════════════════════════════════════════════╗
║ Test Summary ║
╠═══════════════════════════════════════════════════════════╣
║ Platform: ANDROID ║
║ Device: emulator-5554 ║
║ Test Filter: DragAndDropUITests ║
║ Result: SUCCESS ✅ ║
║ Logs: /home/vsts/work/1/s/CustomAgentLogsTmp/UITests
╚═══════════════════════════════════════════════════════════╝
📊 Parsed test results: Passed=6 Failed=0 Total=6 (from 1 result blocks)
==========================================
VERIFICATION RESULTS
==========================================
🖥️ [UITest] DragAndDropUITests: PASSED ❌ (should fail!)
╔═══════════════════════════════════════════════════════════╗
║ VERIFICATION FAILED ❌ ║
╠═══════════════════════════════════════════════════════════╣
║ 8/1 test(s) PASSED but should FAIL! ║
║ Those tests don't reproduce the bug. Revise them! ║
╚═══════════════════════════════════════════════════════════╝
📱 UI Tests — Gestures
Detected UI test categories: Gestures
🧪 UI Test Execution Results (deep, platform pool)
| Category | Tests | Snapshot diffs |
|---|---|---|
Gestures |
0/60 (setup failed; 60 marked failed) | — |
⚠️ Gestures — fixture setup failed for 60 tests
NUnit reported a OneTimeSetUp/fixture setup failure before test bodies ran; the TRX marked each affected test failed.
Multiple setup failure signatures were present; showing the first one. See the TRX artifact for all details.
OneTimeSetUp: System.TimeoutException : SwipeGestureRecognizer triggers while scrolling CollectionView horizontally on iOS
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
at Microsoft.Maui.TestCases.Tests._IssuesUITest.NavigateToIssue(String issue) in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/_IssuesUITest.cs:line 54
at Microsoft.Maui.TestCases.Tests._IssuesUITest.TryToResetTestState() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/_IssuesUITest.cs:line 25
at Microsoft.Maui.TestCases.Tests.UITest.FixtureSetup() in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 584
at UITest.Appium.NUnit.UITestBase.OneTimeSetup() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 221
at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack
...
📎 Download drop-deep-uitests artifact (TRX + snapshot diffs)
🧭 Next Steps — review latest findings
No alternative fix was selected for this run. Review the session findings and CI results before merging.
|
♻️ Attempt 1/10 — red is an unrelated CI flake, not caused by this PR (head The current reds are UI-test categories unrelated to this PR's A maintainer re-run (
|
|
🎯 Target test validated green on Transitioning this PR from draft to ready for review and adding Automated by the CI Failure Fixer (net11.0). Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
|
DragAndDropUITests.DropEventCoordinates validated green on all platforms (iOS/Android/MacCatalyst/WinUI, buildId 1476818) on head eb3c2f0; the de-flake fix is verified. Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
|
Azure Pipelines: Successfully started running 1 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
kubaflo
left a comment
There was a problem hiding this comment.
🔍 AI-generated review — GitHub Copilot CLI on behalf of @kubaflo. Independent code-review of this
[ci-fix]de-flake.
Round 1 — LGTM (sound de-flake; verified)
Clean, well-root-caused fix for the intermittent DropEventCoordinates failure on the iOS 18.5 leg.
Change (DragAndDropUITests.cs, +17/-1): wraps the existing 3-iteration loop with (a) a clean-state reset on retry (App.Tap("ResetButton") → wait for Blue/Green) and (b) a stricter success gate — accept the drop only when dropCoordinates is non-null and X > 0 && Y > 0, matching the final assertion instead of accepting the first (possibly degenerate (0,0)/negative) reading.
Verified against the codebase:
- ✅
ResetButtonexists on the page under test —TestCases.HostApp/Elements/DragAndDropBetweenLayouts.xaml:7(AutomationId="ResetButton",Clicked="ResetLayouts"). The change edits only the test file, and the button is pre-existing, so no HostApp change is needed. - ✅
ResetLayouts(DragAndDropBetweenLayouts.xaml.cs:124) clears both layouts and regenerates "Blue" into the source (SLAllColors) and "Green" into the target (SLRainbow), each withAutomationId=color. This makes the retry's reasoning correct — Blue is returned to its source so the nextDragAndDrop("Blue","Green")is a valid cross-layout drop (the in-code comment aboutSource == layoutno-op is accurate), and theWaitForElement("Blue"/"Green")calls resolve. - ✅ New success condition mirrors the post-loop assertion (positive X,Y), so the loop can no longer "succeed" on an invalid reading and then fail the assert.
CI status (transparent)
Required rollup is currently red, but the failures are in unrelated categories and the touched test's own legs are green:
- ✅ Green:
iOS …DragAndDropshard, andGesturesshards on iOS / Android / MacCatalyst / WinUI — i.e. the category this PR de-flakes passes on every platform. - ❌ Red (pre-existing, unrelated):
iOS/MacCatalyst …WebView,Android …CollectionView,AOT macOS,RunOniOS…TrimFull. A 17-line gesture-test edit cannot cause WebView/CollectionView/AOT/integration failures.maui-pris re-running.
Verdict
LGTM — de-flake is correct and its target legs are green; the red rollup is confirmed PR-unrelated. No inline findings. (Reporting LGTM only — not posting a formal Approve.)
kubaflo
left a comment
There was a problem hiding this comment.
Multi-model consensus: LGTM (Claude Opus 4.8 · GPT-5.5 · Gemini 3.1 Pro — independent → cross-pollinated, unanimous high confidence).
What this changes: de-flakes the DropEventCoordinates UI test. On a retry it now taps ResetButton (→ ResetLayouts restores Red/Purple/Yellow/Blue + Green and blanks the coordinate labels) before re-dragging, and tightens the retry-loop success gate from != null to X > 0 && Y > 0.
Why it's correct (the decisive point all three models + I independently reached): the new loop gate is now identical to the pre-existing final assertion (dropRelativeToLayout.X > 0 && Y > 0). Previously the loop accepted any non-null reading, so a degenerate (0,0)/negative coordinate synthesized by the iOS-18.5 gesture was accepted by the loop and then hard-failed the assertion — the flake. Now such a reading triggers a clean retry instead. Crucially, this cannot introduce a false failure: any drop the loop now rejects would already have failed the final assertion. Assert.Fail still fires if all 3 attempts are exhausted (no false pass).
X>0 && Y>0edge case — not a bug: the drop coord is(int)e.GetPosition(SLRainbow)at Green's center;App.DragAndDrop("Blue","Green")targets center →≈(colWidth/2, ~25), comfortably positive. A real drop can't land at layout origin.- ResetButton cross-platform — safe: the exact
Tap("ResetButton"); WaitForElement("Blue"/"Green")sequence already runs unconditionally before the loop, proving it's tappable on every platform.
CI (the ci-fix acceptance criterion): the target test passes.
maui-pr✅ pass (build 1520750 — all builds, packs, Helix unit tests, and every integration-test leg green).- The DragAndDrop UI-test leg passed on all 4 platforms at this head (
eb3c2f02b2cc, build 1476818): MacCatalyst ✅ / WinUI ✅ / Android ✅ / iOS-vlatest ✅. maui-pr-uitests❌ is confirmed unrelated — the only failing legs are Android CollectionView and MacCatalyst/iOS WebView, categories this single-file DragAndDrop test cannot affect.
No ❌/
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Refs: #35981
Target branch: net11.0
CI failure fixer — de-flake
Failing test
DropEventCoordinates(src/Controls/tests/TestCases.Shared.Tests/Tests/DragAndDropUITests.cs),[Category(Gestures)], iOS 18.5 leg. Intermittent — fails on the first attempt, passes on retry (2 of the last 10 builds on 2026-06-16).Root cause (test-quality flake)
The pre-existing retry loop accepted the first parseable drop reading:
On iOS 18.5 the first synthesized Appium drag-and-drop gesture can land with degenerate
(0,0)/negative coordinates. Those parse to a non-nullPoint, so the loop broke and accepted them — but the assertion immediately below requires strictly positive coordinates:→ hard failure on attempt 1, green on a later run.
Additionally, a degenerate drop still fires
OnDrop, which moves "Blue" out ofSLAllColorsinto the target layout (DragAndDropBetweenLayouts.xaml.cs). A naive retry then drags Blue → Green within the same layout, whereOnDropearly-returns (Source == layout) and never updates the label — so the existing retry could not recover.This is a defect in the test, not the product: the same product code reports correct positive coordinates on the passing run. The intermittency tracks an Appium/simulator gesture-injection change on iOS 18.5 (signature absent before 2026-06-16), not a product regression — so de-flaking the test is appropriate, not muting a product bug.
The de-flake
ResetButton) between retries so each retry is a valid cross-layout drag (Blue back inSLAllColors).The happy path (a good first drop) is unchanged — it breaks on the first iteration with no reset.
Not a mute
[Retry]/[Repeat]/[Ignore]/[ActiveIssue]/[SkipOnPlatform]added.Thread.Sleep(500)is unchanged (not bumped) — no timeout was enlarged to outlast a slow path.Validation
Not run —
maui-pr-uitestsrequires an iOS device/simulator rig not available to the fixer. The change is a synchronization / state-reset correction in test code only. Per-test pass/fail lives in the published TRX (AzDO test-results API), which this read-only agent does not access; the defect was confirmed statically present and unchanged at the current net11.0 tip (f7909d5a, the source built by the latest leg).Evidence
f7909d5a= current net11.0 tip)Prior approaches
First attempt for this issue — no prior
[ci-fix]PRs to contrast.