ci: UI test runs adopt compile admission's product, skip the re-upload, and report progress - #15331
Conversation
…d, and report progress - The app-host product contract hashed SDKROOT as the runner found it. Some owned Macs' runner services export it as the selected Xcode's MacOSX.sdk and others export nothing, so a UI test build on one kind never adopted the product compile admission had just published from the other and compiled the app again. SDKROOT that names the default SDK now hashes as unset. - A test-e2e.yml build that adopted a product and ran the tests itself no longer uploads that product again after the tests: the producer already publishes it. A sibling dispatch stops waiting on such a build at once. - ci.yml's "Wait for the UI test run" prints one line a minute: compile admission's state while the dispatch waits for its product, then the test run's job, runner or queue, current step and elapsed times. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 17 minutes. View limit detailsLimit details: You’ve used all 10 included reviews currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository: manaflow-ai/cmux/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (11)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
All contributors have signed the CLA ✍️ ✅ |
|
Dogfood build of cmux DEV pr-15331-0ef73091.app The link opens this exact commit in the cmux dev menu bar app. The build starts on each push and the page waits until it is ready; a newer push replaces it. It signs in against production, so Cloud or backend changes still need a tagged build with a development backend. |
CI failure attributionCI passes on Written by |
673b162 to
50a4273
Compare
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
…dget Review fixes: - Progress catches every exception (spawning gh can raise OSError on a busy runner), so it can never fail the wait or change its verdict. - Progress reads on every third poll, a third more REST calls on the job token instead of twice as many. - A sibling wait ends early only for a build that skipped its compile and packaged a product, not one whose earlier step failed. - The test run is matched whatever order its title names the same selectors in (the dispatcher reuses such a run), and looked up again once it ends. - app_host_test_rerun.py --source-run-id on an adopting test-e2e.yml run says that run uploads no product and where to find the one it adopted. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
50a4273 to
0ef7309
Compare
|
Merge receipt for |
0e298fb ci: wait for the product's canonical root instead of compiling beside it (manaflow-ai#15379) 3088273 ci: UI test runs adopt compile admission's product, skip the re-upload, and report progress (manaflow-ai#15331) b681e7e Keep a pending banner quiet once its pane is focused (manaflow-ai#15357) 03a2f6e Record that cloud_vm_sessions.attachment_count is cumulative (manaflow-ai#15321) 48258b4 fix(iroh-v2): check the team socket cap before opening the session (manaflow-ai#15340) 2638d56 Agent activity reorder follow-ups: group on-top check, search, subtitle (manaflow-ai#15362) 9ed83fd Dogfood journey: record whether a paused Cloud machine is asleep (manaflow-ai#15293) 7171ea8 Add app.tabBarVisibility to hide the pane tab bar when a pane has one tab (manaflow-ai#15294) 8743ec8 test: stop Computer Use onboarding tests waiting out the helper status deadline (manaflow-ai#15329) 6e4f1da ci: drain the snapshot's owned queue by what the machines finished since (manaflow-ai#15374) 9373164 ci: queue a pull request's admission for a root runner when Blacksmith's wait is longer (manaflow-ai#15376) 634a155 test: expect injected pane attention accent (manaflow-ai#15370) cd030e9 Keep a named Cloud machine's prompt name instead of flipping to its slug (manaflow-ai#15288) 24ee0ee Exit 1 when cmux terminal screen wait times out (manaflow-ai#15282) 1b857ac test: cover a live Codex turn owner keeping its turn on SessionStart (manaflow-ai#13588) 56ec600 PR media: prune media of long-closed pull requests (manaflow-ai#15364) 4898cde ci: bound the SwiftPM scratch holder and cache scratch sizes (manaflow-ai#15366) # Conflicts: # .github/workflows/ci-guards.yml # .github/workflows/ci.yml # .github/workflows/test-e2e.yml
Why
A pull request that changes a UI test class runs it in
ui-tests, which dispatchestest-e2e.ymland waits. On #15160 (run 36404376226) that looked stuck and compiled the app again although compile admission had just built it. The comparable dispatch, run 36403079789, spent:Cause of the recompile
test-e2e.ymlalready adopts compile admission's product and runstest-without-buildingwhen their product contracts match. They did not match. I compared the receipts sealed in the two artifacts (admissionaf95251f, run 36401440165, and the UI run'sf807552c): they differ only inenvironment.SDKROOT. Hashing the UI run's contract withSDKROOTunset givesaf95251f, admission's key.Some owned Macs' runner services export
SDKROOT=<Xcode>/.../MacOSX.sdk, and others export nothing (5 of 12 checked hosts export it). Both build against the same SDK, and the SDK build is already in the contract assdk. The UI run in question landed on a Mac of one kind and admission on the other, so it missed withno_matching_contract_artifactand compiled. A pair on two Macs of the same kind (runs 36402498206 and 36404799894) adopted the product.What
reuse_app_host_products.contract()recordsSDKROOTas empty when it resolves to the selected Xcode's default macOS SDK (xcrun --show-sdk-path). Any other SDK still hashes. Products built withSDKROOTunset keep their keys, so nothing already published changes name.testjob, which reads it.e2e_sibling_build.pystops waiting on a sibling whose compile step was skipped, because the product it adopted is already there.buildis queued (label, time) or running (runner, time), the current step, compile time or "adopted the compiled product, no build", and "testing N selected classes for T". It reads on every third verdict poll (a third more REST calls on the job token), and a failed read of any kind only skips a line: the test-e2e job list once the run is known, and before that, alternately, the listing that finds it and this attempt's jobs. A failed read skips a line and never changes the verdict. The webhook feed and glaeda-gh are not reachable from this GitHub-hosted runner, so this uses the job token.Measured before (CI history)
ci-timing.json, PRui-testsjob, last 24 h: run p50 1333 s, p90 1535 s, n=13.test-e2e.ymlbuild jobs on owned Macs, 2026-09-27 23:29Z to 09-28 09:53Z (300 runs):ci-ui-tests.ymlin that window:Measured after (this PR's CI)
ui-testsin run 36412727305 (job 108897404233). One line a minute, for example:SDKROOT) and run 36422710055 (a Mac that exports it) sealed the same product key,ce56a748. Both found admission's product by contract.Upload the compiled test product after the testsskipped. Its selector matched no test at that commit (my selector choice), so the step failed; the product path is what this run shows. Before, an adopting run spent p50 162 s uploading after its tests.root_unavailable). That is the next fix.Testing
python3 tests/test_reuse_app_host_products.py(118 OK, including the new SDKROOT case),tests/test_reuse_release_product.py,tests/test_e2e_sibling_build.py,tests/test_ci_ui_tests_dispatch.py(newProgressTests),tests/test_ci_e2e_compilation_cache.py(the new late-upload condition passes;E2ECapturePreflighttimes out locally on main too).actionlintand a YAML parse ofci.ymlandtest-e2e.yml.HelpMenuUITestsran this PR'sui-testslane (the measurements above). It has been dropped.Note for #15327
Whichever of this and #15327 lands second:
await_verdictthere follows a replacement dispatch run (watched). RecreateProgress, or resetprogress.e2e, each timewatchedchanges, and callprogress.report()inside that loop'scheck().Changelog
none
🤖 Generated with Claude Code