Skip to content

Run tests with race detection on CI#5792

Open
stefanhaller wants to merge 6 commits into
synchronize-async-view-renderingfrom
run-tests-with-race-detection-on-ci
Open

Run tests with race detection on CI#5792
stefanhaller wants to merge 6 commits into
synchronize-async-view-renderingfrom
run-tests-with-race-detection-on-ci

Conversation

@stefanhaller

Copy link
Copy Markdown
Collaborator

Now that #5791 has made integration tests race-free, let's add a CI job that runs them with race detection turned on.

@stefanhaller stefanhaller added the maintenance For refactorings, CI changes, tests, version bumping, etc label Jul 10, 2026
@stefanhaller stefanhaller changed the base branch from master to synchronize-async-view-rendering July 10, 2026 12:51
@stefanhaller stefanhaller force-pushed the run-tests-with-race-detection-on-ci branch 3 times, most recently from 1304871 to 6800790 Compare July 10, 2026 18:31
@stefanhaller stefanhaller force-pushed the synchronize-async-view-rendering branch from 45b8511 to 2afc0ec Compare July 10, 2026 20:00
@stefanhaller stefanhaller force-pushed the run-tests-with-race-detection-on-ci branch from 6800790 to 43e1db7 Compare July 10, 2026 20:00
@stefanhaller stefanhaller force-pushed the synchronize-async-view-rendering branch from 2afc0ec to cc923b4 Compare July 10, 2026 20:41
@stefanhaller stefanhaller force-pushed the run-tests-with-race-detection-on-ci branch from 43e1db7 to 34f13d6 Compare July 10, 2026 20:42
stefanhaller and others added 6 commits July 10, 2026 22:43
When lazygit exits but leaves behind a subprocess that inherited its
stderr pipe and has detached from the pty, cmd.Wait() blocks in
awaitGoroutines waiting for that pipe to reach EOF -- which never
happens while the straggler is alive. With no WaitDelay set, that wait
is unbounded, so a single leaked process hangs the whole test binary
until the 10-minute global timeout fires and panics. Worse, the timeout
discards whatever lazygit wrote to stderr before exiting (a panic, a
-race report), which is exactly the output needed to diagnose the
failure.

This surfaces under -race, where lazygit runs slow enough to widen the
window for a spawned command to still be alive when lazygit quits, and
it's a blocker for enabling the race detector on CI.

Bound the wait with cmd.WaitDelay so Wait force-closes the pipe and
returns ErrWaitDelay instead of hanging, surface the captured stderr as
the error (falling back to the wait error when nothing was printed), and
kill the child's process group on failure so a straggler can't linger
into a later test or pile up across a run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The integration test watchdog fails a test if its recording takes longer
than 40 seconds. Under the race detector everything runs several times
slower, so legitimately slow tests (e.g. a conflicting interactive
rebase) blow that budget and fail even though nothing is actually stuck.

Key the timeout off a build-tag constant: the `race` tag is set
automatically when the binary is built with -race, so a race build gets
a 5x-longer budget while a normal build is unchanged, and the two can't
drift apart the way a runtime flag would. The base 40s stays in one
place; only the multiplier varies by build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Go's default 10-minute timeout was enough for running integration tests
normally (both locally and on CI), but with race detection turned on
they can take much longer to run. Increase the timeout unconditionally
to 30 minutes; we don't bother making a distinction between race vs.
normal, because a longer timeout doesn't hurt (I can't recall having hit
the global timeout ever; and we still have the per-test watchdog that
kills an individual test after 40s).
Add one extra integration-tests job that runs the whole suite under the
race detector. A `race` matrix dimension (default false) plus an include
entry adds a single git-latest job with LAZYGIT_RACE_DETECTOR set; races
live in lazygit's own Go code rather than in git, so one git version is
enough, and using latest skips the git-build steps.

The race job skips coverage collection: it's redundant with the non-race
latest job and would only slow the -race build down further.
The watchdog only log.Fatal'd with a message, so a hung test told us
that it timed out but not where it was stuck -- useless for diagnosing
an intermittent deadlock under the race detector. Dump all goroutine
stacks to stderr first (the harness surfaces this process's stderr on
failure), turning a bare timeout into an actionable stack trace.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
To spot slow or anomalous tests across CI runs, record each test's run
duration when LAZYGIT_TEST_TIMING is set (to a file path);
run_integration_tests.sh prints them at the end, sorted by slowest
first. CI sets it for all integration jobs.

The harness appends to a file rather than writing to stdout/stderr
because `go test` captures those and only surfaces them with -v, which
would drown the signal in every test's verbose logs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@stefanhaller stefanhaller force-pushed the synchronize-async-view-rendering branch from cc923b4 to 0020dbe Compare July 10, 2026 20:44
@stefanhaller stefanhaller force-pushed the run-tests-with-race-detection-on-ci branch from 34f13d6 to c51cb6b Compare July 10, 2026 20:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintenance For refactorings, CI changes, tests, version bumping, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant