Repository navigation
fix: two flaky required checks — the Visual Studio mask and e2e 845 - #806
Merged
Sunrisepeak merged 2 commits intoOct 13, 2026
Merged
Conversation
`845_play_game_restores_the_terminal.sh` sent its arrow keys and its Ctrl-C at a fixed 1.5s after the fork, while the build reaches Phase::Building only after its build program has compiled and run (and after the toolchain was resolved). On the runner where run 38406939721's macos leg failed, that work was 1.24s of the 1.5s budget, so the signal landed in the Programs phase and G1's `Building .* · snake \d+` found no row to match -- while the rows that did reach the terminal carried the score, and only the phase word differed (phase_status() prints `Running` for Phase::Programs). The wait is now the row itself: the arrows and the Ctrl-C go out when the frame the assertion names first appears, which is also the frame that proves the prepare action (the 4s sleep) is running. A 60s cap keeps a build that never draws the row from hanging the leg. The score assertion is unchanged.
The "Mask Visual Studio" step renamed `...\Microsoft Visual Studio\*\*\VC` to `VC.masked` in one attempt and treated "Access to the path is denied" as final. That refusal is a state of the host, not of the image: on windows-2025-vs2026 (image 20260925.250) run 38406939721 was refused at 13:59 UTC where the same image committed the same rename at 09:57 and 14:32. Since the step's postcondition is what keeps an incomplete mask from reading as a green "bare Windows" row, the refusal turned into a red required check. The rename is now retried (5 attempts, 2s apart), and a directory that stays locked is answered one level deeper: a handle into VC does not block renaming VC\Tools, and VC\Tools\MSVC is where vswhere's resolution, the environment strategy and the well-known-path scan all end. The postcondition, the env variables it clears and the failure it prints are unchanged. The block had three copies — ci-windows.yml, ci-fresh-install.yml and measure-windows-tool-crt.yml — which is why they could drift; it now lives in .github/actions/mask-visual-studio and the three call sites name it.
1 of 3 tasks
Sunrisepeak
approved these changes
Oct 13, 2026
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.
Summary
Two required checks failed intermittently on run 38406939721 (PR #804), on files that run never touched. The analysis is in #804 (comment); this PR makes both deterministic.
e2e 845 (
test:commit).845_play_game_restores_the_terminal.shsent its arrow keys and Ctrl-C at a fixedt0 + 1.5s, while the build reachesPhase::Buildingonly after its build program has compiled and run (and after the toolchain was resolved) — 1.24s of that budget on the runner that failed. The signal therefore landed in the Programs phase and G1'sBuilding .* · snake \d+had no row to match, although the rows that reached the terminal did carry the score;phase_status()printsRunningforPhase::ProgramsandBuildingonly forPhase::Building. The wait is now the row itself: the arrows and the Ctrl-C go out when the frame the assertion names first appears, with a 60s cap so a build that never draws it fails rather than hangs. The assertion is unchanged, and it now also proves the kill lands while the prepare action (the 4s sleep) runs.The Visual Studio mask (
fix:commit). The mask renamed...\Microsoft Visual Studio\*\*\VConce and treated "Access to the path is denied" as final. That refusal is host state, not image state: onwindows-2025-vs2026(image20260925.250) the same image committed the same rename at 09:57 and 14:32 UTC and was refused at 13:59. Because the postcondition is what keeps an incomplete mask from reading as a green "bare Windows" row, the refusal became a red required check. The rename is now retried, and a directory that stays locked is answered one level deeper — a handle intoVCdoes not block renamingVC\Tools, andVC\Tools\MSVCis where vswhere's resolution, the environment strategy and the well-known-path scan all end. The postcondition is unchanged. The block had three copies (ci-windows.yml,ci-fresh-install.yml,measure-windows-tool-crt.yml), which is how it could drift; it now lives in.github/actions/mask-visual-studioand all three sites name it.Closes #805
Test plan
mcpp test(unit/integration): not applicable, no C++ changedplay.py, against a local mcpp: the script's own heredocs extracted unmodified, project built from them. Unloaded, both pass. With the Programs phase held past 1.5s (a sleep in the build program — the CI runner's shape), the oldplay.pyfails exactly as CI did (AssertionError: G1: no status row carries the score, all framesRunning) and the new one passes, its frames reachingBuilding … · app: app:install 0:00 · snake 0before the keys go out.bash -non the script; the extractedplay.pycompiled and executed by that runbash tests/e2e/232_workflow_syntax.sh(24 workflows, plus its.github/actionsscan);.github/tools/check_workflow_assertions.pyreports 0 problems;tools/lint-ci-assertions.shreports the same 5 warnings as before this change;git diff --checkcleanaction.yml,ci-windows.yml,ci-fresh-install.ymlandmeasure-windows-tool-crt.ymlall parse as YAML (PyYAML), and the new action reads asruns.using: compositewith its one steppwshon this host, so it is unrun here — thewindows / bare Windowsjob in this PR's CI is where it runs, and this PR touches.github/**, so the full matrix runs it