mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
Fixes the CI flakes that failed most often across `main` and unrelated branches from Oct 5 to Oct 14. The counts come from 150 failed `CI` runs. Every change except the nextest config is test-only. | Flake | Runs hit | Root cause | Fix | |---|---|---|---| | `probe_codex_acp_version_…descendant_holds_pipe_open` | 5 | The test writes its script in-process and then execs it. If a sibling test spawns a process in that window, the child inherits the open write fd and Linux rejects the exec with `ETXTBSY`. The probe swallows that error as `None`. | Write probe scripts from a short-lived `/bin/sh` (`write_executable_script`) | | `empty-edit-delete.spec.ts` (`:51`, `:74`, `:95`) | 11 | The seeded `mock-general-welcome` id isn't hex, so `formatTimelineMessages` can't overlay its edit. The post-subscribe window refetch then reverts the row. | Emit a per-test message with a real id after the exact channel subscription is live | | `huddle-transcription.spec.ts:798` | 9 | The composer's delayed initial autofocus (TipTap `focus()` runs in rAF) lands after the voice popover opens and dismisses it. | Wait for `message-input` focus before opening the popover | | `voice-note.spec.ts:906` | 6 | The fixture `ping.mp3` is about 1s long, so playback can end before `paused === false` is observed. | Loop the fixture audio | | `workflows.spec.ts:291` | 5 | The `Message text` fill runs before the inspector swaps to the new step, so it fills the trigger's condition instead. | Scope the fill to the step inspector after its `Action` menu appears | | `cluster_global_probe_commits_tokens_and_sessions_prove_coverage` | 3 | The `max-threads = 1` group only serializes these tests with each other. Other tests' sessions still mask cluster-wide `pg_stat_activity` (`MaskedActivity`). | `threads-required = "num-test-threads"` | | `test_usage_metrics_lock_has_single_owner_and_releases_on_drop` | 1 (this PR) | The test retries the lock right after dropping the leader. Postgres releases a session advisory lock only after the backend notices the disconnect, so the retry can run first. | Poll for the successor, bounded at 5s | ### Validation - **ETXTBSY:** a Linux experiment with Rust 1.95 using the same write→chmod→spawn pattern under concurrent spawns hit `ETXTBSY` 4–7% of the time. Using the `sh` writer, it hit 0 of 6,000. I did not catch it inside the full suite locally, so this fix is based on the mechanism, not an in-suite repro. All 11 probe tests pass on Linux and macOS. - **empty-edit-delete:** the baseline failed 16 of 45 runs (`--repeat-each`, 6 workers, no retries). The spec fix alone brings that to 4/45. The remaining failures come from a separate product race, described below. - **huddle:** the baseline failed 5 of 10 runs. With the fix, 60 of 60 passed without retries. - **nextest:** checked with a throwaway crate on 0.9.136. A grouped test with `num-test-threads` ran alone, even with `max-threads = 1`. - I have not stress-run the voice-note and workflows fixes; they rely on CI. ### Not in this PR - **Product bug in `useChannelLinks`:** the debounced `#channel` autocomplete close lets Enter accept a stale suggestion for about 120ms. That accounts for the remaining `empty-edit-delete` failures, and it affects users too. With the spec fix plus a synchronous close, the spec passed 120 of 120 runs. This needs a product decision, so it's held for a separate PR. - **Composer autofocus race:** the delayed autofocus can close an overlay the user just opened. The real fix is to revalidate when the delayed focus runs. Overlaps #6530. - **`thread-head-stale-edit.spec.ts:55`:** a forced click on a pointer-events-none action bar is suspected, but I couldn't reproduce it. - **Remaining ETXTBSY exposure:** about 40 other Rust tests write and then exec scripts, and 17 specs still edit the non-hex seed message. Root-cause lanes by Princess Donut, Mongo and Mordecai. Carl integrated and verified them. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <32a2e2c9d428ee08902cab75d956da2c1d235a22d4766b0dd4138bf6e2e5db1d@buzz.block.builderlab.xyz> Co-authored-by: Princess Donut <5d97ac8c272fa949af56c71e586146b1706e5c4c3daa125db5b4625e12e0686c@buzz.block.builderlab.xyz> Co-authored-by: Mongo <81cabd2ca1792494372ed410283c00770c0cf35afca052e940fa522883212b45@buzz.block.builderlab.xyz> Co-authored-by: Mordecai <f314b6033b6e13df94c8e9e1187d3666b6b9ce54e66ee986e31cdaa909e8dcbc@buzz.block.builderlab.xyz> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
46 lines
2.0 KiB
TOML
46 lines
2.0 KiB
TOML
nextest-version = "0.9.136"
|
|
# The PostgreSQL lane uses a run-scoped desired-state template database and a
|
|
# per-test wrapper, both of which require nextest's script support.
|
|
experimental = ["setup-scripts", "wrapper-scripts"]
|
|
|
|
[scripts.setup.postgres-template]
|
|
# Bootstrap the desired-state source database once per nextest invocation.
|
|
command = { command-line = "scripts/postgres-test-setup.sh", relative-to = "workspace-root" }
|
|
slow-timeout = "60s"
|
|
|
|
[scripts.wrapper.postgres-isolation]
|
|
# Clone or create a unique database for each test process, then drop it on exit.
|
|
command = { command-line = "scripts/postgres-test-wrapper.sh", relative-to = "workspace-root" }
|
|
|
|
[profile.postgres-ci]
|
|
# This structural convention keeps new PostgreSQL-backed tests discoverable
|
|
# without maintaining an exact list of test names.
|
|
default-filter = """
|
|
(test(/postgres_tests::/) or binary(/^postgres_/))
|
|
and not test(/(^|::)external_infra[^:]*::/)
|
|
"""
|
|
fail-fast = false
|
|
# Eight workers was the fastest stable setting in the Blox benchmark while the
|
|
# wrapper retained one database per concurrently running test process.
|
|
test-threads = 8
|
|
|
|
[test-groups.postgres-cluster-global]
|
|
# These tests inspect cluster-wide activity or create least-privilege sessions,
|
|
# so database-per-test isolation alone cannot make them independent.
|
|
max-threads = 1
|
|
|
|
[[profile.postgres-ci.overrides]]
|
|
filter = "test(/cluster_global_/)"
|
|
test-group = "postgres-cluster-global"
|
|
# The group only serializes these tests with each other. They read unfiltered,
|
|
# cluster-wide `pg_stat_activity`, so any overlapping test's session can mask
|
|
# activity; claim every worker so they run alone.
|
|
threads-required = "num-test-threads"
|
|
|
|
[[profile.postgres-ci.scripts]]
|
|
# Script filters are separate from default-filter: they attach the setup and
|
|
# isolation wrapper to the same automatically discovered test set.
|
|
filter = "(test(/postgres_tests::/) or binary(/^postgres_/)) and not test(/(^|::)external_infra[^:]*::/)"
|
|
setup = "postgres-template"
|
|
run-wrapper = "postgres-isolation"
|