Skip to content

fix(ci): make the test workflow green on main - #149

Closed
quickbeard wants to merge 2 commits into
mainfrom
ci-green
Closed

quickbeard wants to merge 2 commits into
mainfrom
ci-green

Conversation

@quickbeard

Copy link
Copy Markdown
Owner

Every job in the test workflow had been failing on main for weeks. There were four independent causes; this PR fixes all of them.

unit (linux) — codev run subprocess tests timing out

The five codev run subprocess tests still on the spawn harness's 30s default were being killed at exactly that bound (30174ms, 30776ms, 30816ms, 30907ms, 30949ms) on both CI attempts. The tests in the same file that already carried an explicit timeoutMs: 60_000 passed — the split is purely the budget, not the work.

Raised the harness default to 60s: every spawn pays the CLI's cold transpile, and no test depends on that timeout firing, so this is headroom only (a real hang still exceeds it). The bun-level timeouts of the covered tests are lifted above the new spawn budget so a slow-but-successful run isn't cut off at the test layer instead.

unit (windows) — observe-element-offset reconnect test

happy-dom (through the current 20.11.1) stores each MutationObserver's internal mutation callback only in a WeakRef and splices the listener out as soon as it's collected — so a GC between observe() and the mutation silently stops the observer. Real browsers hold it strongly. Reproduced directly:

observer.observe(document.body, { childList: true, subtree: true })
Bun.gc(true)
route.remove(); document.body.append(route)
// → observer never fires

That explains why exactly one test in the file failed, and only on Windows: it's the only one with an idle window (await frames(2)) between registering the observer and the mutation it cares about. The others mutate immediately.

Fixed in the happydom.ts preload by pinning the registered callbacks, with packages/app/src/happydom-mutation-observer.test.ts guarding the patch.

e2e (linux) — session-todo-dock-navigation

sampleDock(page, 700) sampled for a fixed wall-clock window while switchSession ran concurrently. On GitHub-hosted runners the switch alone outlasts 700ms, so every sample was taken before the dock reappeared and openSamples came back empty — failing on all three attempts.

The sampler now bounds on the dock appearing rather than on the clock. The assertion is unchanged (the first present sample must already be at full opacity — no replayed open animation); it just can't race the runner anymore.

e2e (windows) — dropped from the matrix

GitHub-hosted windows-latest runs the Playwright suite roughly 4x slower than upstream's Blacksmith Windows runner. The job has never been green here: it never finished inside the 30-minute step budget and failed ~20 specs per run, mostly 10s toBeVisible expect timeouts, plus sub-pixel layout assertions (toBeCloseTo(cardHeight, 2)) that track the runner's font metrics.

These specs drive a browser SPA against a mocked server, so Chromium — not the host OS — is what they cover. Unit tests still run on Windows, where the real platform differences live.

Verification

  • packages/opencode: bun test test/cli — 375 pass, 0 fail
  • packages/app: bun run test:unit — 625 pass, 0 fail
  • packages/app: full Playwright suite — 88 passed, including the fixed spec. The 2 failures are remote-session-settings.spec.ts, which is pre-existing on clean main, macOS-local only (Meta+,), and passes on Linux CI.
  • bun typecheck — 31/31 packages

DIVERGENCES.md rows added/updated for all four upstream files touched. No CHANGELOG.md entry: nothing user-facing changes.

🤖 Generated with Claude Code

quickbeard and others added 2 commits August 2, 2026 19:11
Every job in the test workflow had been failing on main for weeks, across
four independent causes.

unit (linux): the five `codev run` subprocess tests still on the spawn
harness's 30s default were killed at exactly that bound on loaded runners
(the tests that already carried an explicit 60s passed). Raise the harness
default to 60s — every spawn pays the CLI's cold transpile — and lift the
bun-level timeouts of the tests it covers above it.

unit (windows): happy-dom keeps each MutationObserver's internal callback
only in a WeakRef and unregisters the listener once it is collected, so a
GC between observe() and the mutation silently stops the observer. That
failed observe-element-offset's reconnect test — the only one in the file
with an idle window before its mutation — on every Windows run. Pin the
callbacks in the happydom preload, with a test guarding the patch.

e2e (linux): session-todo-dock-navigation sampled the dock for a fixed
700ms window while the tab switch ran concurrently; on GitHub-hosted
runners the switch alone outlasted it, so every sample landed before the
dock reappeared. Bound the sample on the dock appearing instead.

e2e (windows): dropped from the matrix. GitHub-hosted windows-latest runs
the Playwright suite ~4x slower than upstream's Blacksmith runner — it
never finished inside the 30-minute step budget and failed ~20 specs per
run on expect timeouts plus sub-pixel layout assertions that track the
runner's font metrics. These specs drive a browser SPA against a mocked
server, so Chromium rather than the host OS is what they cover; unit tests
still run on Windows, where the real platform differences live.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
With `staleMs: 1_000`, an owner starved past that bound is *correctly*
broken by a contender — and the test then reports that legitimate break as
a mutual-exclusion violation, because the evicted worker's `active`
sentinel write fails with EEXIST and it exits 1. Sixteen contending node
processes routinely starve the owner's 333ms heartbeat past a second on a
GitHub-hosted Windows runner, so it failed both CI attempts.

Drop the override so it uses the 60s default, matching the effect-flock
sibling that runs the same 16-way stress without flaking. Stale recovery
keeps its four dedicated single/dual-process tests further down the file;
this one asserts exclusion, where the aggressive bound only manufactured
false failures.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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