Skip to content

Stop two CI flakes blocking the merge queue - #369

Merged
btsouth merged 2 commits into
mainfrom
fix/delete-pending-retry-scope
Aug 22, 2026
Merged

Stop two CI flakes blocking the merge queue#369
btsouth merged 2 commits into
mainfrom
fix/delete-pending-retry-scope

Conversation

@btsouth

@btsouth btsouth commented Aug 22, 2026

Copy link
Copy Markdown
Owner

Two unrelated flakes have each failed PRs today that did not touch them.

1. TrayPanel > keeps a counted star ask visible when the tray is empty

Failed on #367 and #355 with:

TypeError: Cannot read properties of undefined (reading 'then')
  The above error occurred in the <TrayPanel> component

afterEach calls vi.restoreAllMocks(), which resets every mock to the implementation it was created with — and for a bare vi.fn() that is "return undefined". LocaleProvider does listen(...).then(...), so any call landing outside the beforeEach→test window throws.

It is always this test because it is the only one that sets starPromptMocks.reason, so it is the only one that renders the prompt and takes the slower path.

eventMocks.listen is now declared as vi.fn(() => Promise.resolve(() => {})), so a restore leaves it harmless. beforeEach still installs the listener-capturing version the tests drive.

Proof — same file, forcing eventMocks.listen.mockReset() before the render:

listen declared as Result
vi.fn() (before) 1 failed | 24 passed — the exact CI error
vi.fn(() => Promise.resolve(…)) (after) 25 passed

2. an_unenforceable_lock_fails_closed_instead_of_writing_unserialized

Failed on #355. This one is my regression from #368. That PR added a retry for Windows' delete-pending state, which reports access-denied. A directory planted at the sibling path — which is exactly what this test does — is also access-denied on Windows, but it never clears. The retry sat on it for the full second and broke the test's sub-second bound.

The retry now skips a directory, the grace drops from 1s to 250ms (still orders of magnitude longer than delete-pending needs), and the test asserts against DELETE_PENDING_GRACE rather than a bare literal so the two cannot drift.

Verified

Frontend: 88 files, 707 tests passing. Rust: 26 secure_file tests, clippy -D warnings clean.


Note

Low Risk
Test-only mock change plus a narrower Windows lock retry that fails faster on an unfixable directory sibling. Does not change the successful lock or write path.

Overview
Stops two unrelated CI flakes: a Vitest mock restore that made listen() return undefined, and a Windows exclusive-create retry that sat on a directory for the full grace period.

eventMocks.listen is now created as a function that resolves to an unsubscribe, so vi.restoreAllMocks() in afterEach no longer breaks LocaleProvider's listen(...).then(...) outside the beforeEach window.

On the lock path, try_exclusive_create no longer retries PermissionDenied when the sibling is a directory (that never clears on Windows). DELETE_PENDING_GRACE drops from 1s to 250ms, and the fail-closed test asserts against that constant so it cannot drift.

Reviewed by Cursor Bugbot for commit 383d3b1. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix CI flakes in TrayPanel test mock and secure_file lock retry logic

  • Changes the eventMocks.listen mock in TrayPanel.test.tsx to return a resolved Promise to prevent errors when mocks are restored.
  • Reduces DELETE_PENDING_GRACE from 1 second to 250 milliseconds in secure_file.rs.
  • Updates StateWriteLock.try_exclusive_create to fail fast when the lock path is a directory instead of retrying until the deadline.
  • Behavioral Change: DELETE_PENDING_GRACE reduction lowers the maximum wait time for exclusive-create retries on Windows.

Macroscope summarized 383d3b1.

@btsouth
btsouth enabled auto-merge (squash) August 22, 2026 18:23
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@tsouth89, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 44 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 524c6b21-68ef-4f58-9a44-36916deadb40

📥 Commits

Reviewing files that changed from the base of the PR and between 3358b28 and 383d3b1.

📒 Files selected for processing (2)
  • apps/desktop-tauri/src/surfaces/TrayPanel.test.tsx
  • rust/src/secure_file.rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ceiling 383d3b1 Commit Preview URL

Branch Preview URL
Aug 22 2026, 06:31 PM

Both have failed PRs today that had nothing to do with them.

TrayPanel: afterEach calls vi.restoreAllMocks(), which resets every mock
to the implementation it was created with - and for a bare vi.fn() that is
"return undefined". LocaleProvider does listen(...).then(...), so a call
landing outside the beforeEach-to-test window threw

  TypeError: Cannot read properties of undefined (reading 'then')

and failed whichever test was on screen. It was always the star-ask test
because that is the only one that renders the prompt. eventMocks.listen is
now declared with a resolved-promise default, so a restore leaves it
harmless; beforeEach still installs the listener-capturing version.

secure_file: the delete-pending retry added for the Windows release race
also sat on a directory planted at the sibling path, which Windows reports
as access-denied too but which never clears. That spent the whole grace
period before failing and broke the sub-second bound in
an_unenforceable_lock_fails_closed_instead_of_writing_unserialized. The
retry now skips a directory, the grace is 250ms rather than a second, and
the test asserts against that constant instead of a bare literal.
tsc infers the mock's call signature from the implementation it is created
with, so a zero-argument default rejected the two-argument
mockImplementation in beforeEach. The build typechecks the test files, so
this failed CI even though vitest was green.
@btsouth
btsouth force-pushed the fix/delete-pending-retry-scope branch from 182b0d8 to 383d3b1 Compare August 22, 2026 18:31
@btsouth
btsouth merged commit 63c2179 into main Aug 22, 2026
14 checks passed
@btsouth
btsouth deleted the fix/delete-pending-retry-scope branch August 22, 2026 18: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