[rush-daemon] Print the native operation summary and duration line on the daemon path - #6068
Merged
Sean Larkin (TheLarkInn) merged 4 commits intoSep 24, 2026
Merged
Conversation
…r phased requests Fixes #6053 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Summary rendering does not honor the request-local warnings policy, causing output to diverge from the command result and native Rush.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
Restores native operation summaries and duration output for daemon-routed phased builds, including warm no-op and coalesced requests.
Changes:
- Adds request-scoped summary rendering using Rush’s native formatter.
- Emits summaries before each request result.
- Adds coverage for cold, warm, failing, and coalesced builds.
| File | Description |
|---|---|
libraries/rush-sdk/src/test/__snapshots__/script.test.ts.snap |
Updates exported API snapshot. |
libraries/rush-lib/src/index.ts |
Exports the internal summary formatter. |
libraries/rush-daemon/src/test/PhasedRequestSummary.test.ts |
Tests request summary behavior. |
libraries/rush-daemon/src/PhasedRequestSummary.ts |
Implements request-scoped summary rendering. |
libraries/rush-daemon/src/PhasedRequestRouter.ts |
Emits summaries before result frames. |
common/reviews/api/rush-lib.api.md |
Records the new internal export. |
common/changes/@rushstack/rush-daemon/rushd-summary-banner_2026-09-24-01-30.json |
Adds daemon patch changelog. |
common/changes/@microsoft/rush/rushd-summary-banner_2026-09-24-01-30.json |
Adds Rush patch changelog. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Mo Jazayeri (mojaza)
approved these changes
Sep 24, 2026
Sean Larkin (TheLarkInn)
deleted the
thelarkinn-fix-rushd-summary-banner
branch
September 24, 2026 21:19
This was referenced Sep 24, 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
On the daemon path (
rush-client build), the end-of-run summary tables (==[ SUCCESS / FROM CACHE / SKIPPED / BLOCKED / FAILURE: N operations ]==, including the error or warning report under--[ FAILURE: … ]--) and the trailingrush build (X seconds)line were never printed. A warm no-op build printed 0 bytes. This PR restores them for each request.Root cause
PhasedScriptAction.tsgives the daemon enginenew Terminal(new NoOpTerminalProvider())aspresentationTerminal. SoOperationResultSummarizerPluginwrites into a no-op terminal. OnlyeventSink.onActivitylines reach the client.afterExecuteIterationAsync, and that hook runs once per shared iteration. Coalesced requests share that iteration, and each may have selected a different subset of operations.scheduleIterationAsyncreturnsfalse), so nothing ran to print a summary. The client prints nothing for aresult.Fix
libraries/rush-daemon/src/PhasedRequestSummary.ts. When the batch coordinator finishes each participating live request (#finishEntryAsync, before the final flush and the result frame), it:graph.operations(so the order matches native), keeps only the request'sactiveOperations, and uses the records the request's sink observed. Selected operations that the warm graph disabled or did not schedule are reported asSkipped("These operations were already up to date:"). It never mutates the shared records._printOperationStatus, the same code the native summarizer uses, so the output is byte-identical.rush <command> (<duration>), orrush <command> - Errors! (…)on an execution error. The duration is measured from when the router receives the request.PhasedRequestEventSink.onActivity, buffered into one activity event per contiguous stdout or stderr run.Operations failed.goes to stderr, as in native.@microsoft/rush-lib: export the existing@internal_printOperationStatus(and update the API report).Why activity events and not a new protocol frame: this follows the approach
EngineTerminalProvideralready uses. The existingLegacyCollatedRendererrenders globalactivityChangedtext as-is at every verbosity. So the change needs no protocol, transport, client or renderer changes, and it stays compatible with the existing wire contract. A structuredrequestSummaryevent could be added later for the reporter renderers, but it isn't needed for parity. Building the summary per request (not per iteration) keeps presentation isolated: coalesced clients each get a summary of only what they asked for.Tests
New
libraries/rush-daemon/src/test/PhasedRequestSummary.test.ts. It drivesPhasedRequestRouteragainst a realOperationGraph:==[ SUCCESS: 2 operations ]==+ operation names + therush build (N.NN seconds)line, before the result framescheduled: false):==[ SKIPPED: 2 operations ]==/ "already up to date" + the duration line--[ FAILURE: … ]--,Operations failed.on stderr, and the duration linerush build --to @rushstack/rush-daemon --to @rushstack/rush-cli-client(including lint) andrush test --only @rushstack/rush-daemonpass on Linux, and every existing rush-daemon test still passes.Linux validation
WSL Ubuntu-24.04, node 22.23.2, synthetic 12-project workspace (
mkws-synth --projects 12),RUSH_DAEMON=1, one shell per sequence: cold build, then a warm no-op, thentouch packages/p04/src/FAIL+ build. "Before" is the unfixedrush-clientfrommain; "after" isapps/rush-cli-client/bin/rush-clientbuilt from this branch."p12 (build)" completed successfully in 0.53 seconds.==[ FROM CACHE: 12 operations ]==table +rush build (1.93 seconds)==[ SKIPPED: 12 operations ]==/ "These operations were already up to date:" +rush build (0.39 seconds)"p12 (build)" is blocked by "p04 (build)".--[ FAILURE: p04 (build) ]--,Operations failed.,rush build (0.70 seconds)After: warm no-op (complete output)
After: failing build (tail)
Fixes #6053
This PR came out of the automated rushd Linux performance/behavior analysis ("Rushd Hive").