test(core): poll the installer PTY instead of racing it - #53
Merged
Merged
Conversation
`check (22)` failed on a docs-only PR with
FAIL tests/tools.spec.ts > ros2_install interactive flow (mock installer, no network)
> start -> send -> status -> stop drives the installer menus via PTY
AssertionError: expected '' to contain '众多工具'
and the identical job passed on an immediate re-run — as it had on every
neighbouring PR and on both Node versions. A test that reds a docs-only change
on a coin flip is worse than no test: it teaches everyone to re-run CI until it
turns green, which is exactly the signal this repository's merge discipline
depends on.
The cause is a race, not an environment quirk. `ros2_install` drives the
installer inside a pty daemon whose output arrives asynchronously, but the test
read `status` exactly once, immediately after `start`, and required the menu to
be there already. The two following steps guessed fixed durations
(`setTimeout(800)` and `setTimeout(2500)`) — the same hazard written as a delay,
which lowers the odds without removing the race and pays that cost on every run.
Replace all three with `statusUntil(...)`: a bounded 100 ms poll on a predicate,
returning the moment the awaited output actually appears. The final step's
predicate requires `state` to have reached `exited` too, rather than assuming
output and state flip together. The test timeout grows 15 s -> 30 s so that a
real failure still surfaces as the specific assertion that never arrived instead
of a generic timeout.
This path is `it.skipIf(!ptyUsable)`, and this host cannot allocate a pty, so the
change is verified by CI (`check (22)` / `check (24)`) and not locally — the same
local-skip/CI-truth split recorded in §19.8 of the maintenance log.
StvLi
added a commit
that referenced
this pull request
Sep 29, 2026
docs: record the flake fix (#53) in the round-16 log
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A docs-only PR (#52) went red on
check (22), and the same job passed on an immediate re-run. That is the PTY test, and this fixes it.Evidence
check (22)Cause
Not the environment — a race in the test.
ros2_installdrives the installer inside a pty daemon whose output arrives asynchronously, but the test readstatusexactly once, immediately afterstart, and required the menu to be present already:The next two steps were the same hazard written as a guessed duration —
setTimeout(800)andsetTimeout(2500). Those lower the odds without removing the race, and pay that cost on every single run.Fix
statusUntil(t, session, predicate, timeoutMs)— a bounded 100 ms poll that returns the moment the awaited output appears. Each step now waits for the specific thing it asserts instead of for a duration, and the final step's predicate also requiresstateto have reachedexitedrather than assuming output and state flip together. Timeout 15 s → 30 s so a genuine failure still reports as which assertion never arrived, not a generic timeout.Verification
pnpm run typecheckpasses. The test isit.skipIf(!ptyUsable), and this host cannot allocate a pty, so the PTY path is exercised by CI only — the local-skip / CI-truth split already recorded in §19.8 of the maintenance log. Bothcheck (22)andcheck (24)are the real verification here.Worth noting as a category, since this repository has now hit it twice: a flaky gate is a maintenance liability in its own right. The maintain log's own guidance is "push → open a PR → wait for CI green before merging", and that only means something while green is informative.