From 4b9eab994ace7075b0fe4ec6cce01505e87fe878 Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Tue, 29 Apr 2025 10:00:54 -0400 Subject: [PATCH] fix(core): tui summary should handle in progress tasks properly (#30905) ## Current Behavior When running via run-many failures that include a continuous task are indicated as a cancellation on the tui summary ## Expected Behavior Failures that run to completion are not cancelled, and should be displayed as a failure ## Related Issue(s) Fixes # --- .../life-cycles/tui-summary-life-cycle.ts | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/packages/nx/src/tasks-runner/life-cycles/tui-summary-life-cycle.ts b/packages/nx/src/tasks-runner/life-cycles/tui-summary-life-cycle.ts index 8c82dc96ee..d6d4530524 100644 --- a/packages/nx/src/tasks-runner/life-cycles/tui-summary-life-cycle.ts +++ b/packages/nx/src/tasks-runner/life-cycles/tui-summary-life-cycle.ts @@ -41,11 +41,12 @@ export function getTuiTerminalSummaryLifeCycle({ let totalSuccessfulTasks = 0; let totalFailedTasks = 0; let totalCompletedTasks = 0; - let totalStoppedTasks = 0; let timeTakenText: string; const failedTasks = new Set(); const inProgressTasks = new Set(); + const stoppedTasks = new Set(); + const tasksToTerminalOutputs: Record< string, { terminalOutput: string; taskStatus: TaskStatus } @@ -65,7 +66,8 @@ export function getTuiTerminalSummaryLifeCycle({ lifeCycle.setTaskStatus = (taskId, taskStatus) => { if (taskStatus === NativeTaskStatus.Stopped) { - totalStoppedTasks++; + stoppedTasks.add(taskId); + inProgressTasks.delete(taskId); } }; @@ -118,7 +120,7 @@ export function getTuiTerminalSummaryLifeCycle({ const printRunOneSummary = () => { let lines: string[] = []; - const failure = totalSuccessfulTasks + totalStoppedTasks !== totalTasks; + const failure = totalSuccessfulTasks + stoppedTasks.size !== totalTasks; // Prints task outputs in the order they were completed // above the summary, since run-one should print all task results. @@ -165,7 +167,7 @@ export function getTuiTerminalSummaryLifeCycle({ ); } lines = [output.colors.green(lines.join(EOL))]; - } else if (totalCompletedTasks + totalStoppedTasks === totalTasks) { + } else if (totalCompletedTasks + stoppedTasks.size === totalTasks) { let text = `Ran target ${output.bold( targets[0] )} for project ${output.bold(initiatingProject)}`; @@ -173,7 +175,7 @@ export function getTuiTerminalSummaryLifeCycle({ text += ` and ${output.bold(tasks.length - 1)} task(s) they depend on`; } - const taskOverridesLines = []; + const taskOverridesLines: string[] = []; if (Object.keys(overrides).length > 0) { taskOverridesLines.push(''); taskOverridesLines.push( @@ -189,23 +191,25 @@ export function getTuiTerminalSummaryLifeCycle({ const viewLogs = viewLogsFooterRows(totalFailedTasks); lines = [ - output.colors.red([ - output.applyNxPrefix( - 'red', - output.colors.red(text) + output.dim(` (${timeTakenText})`) - ), - ...taskOverridesLines, - '', - `${LEFT_PAD}${output.colors.red( - figures.cross - )}${SPACER}${totalFailedTasks}${`/${totalCompletedTasks}`} failed`, - `${LEFT_PAD}${output.dim( - figures.tick - )}${SPACER}${totalSuccessfulTasks}${`/${totalCompletedTasks}`} succeeded ${output.dim( - `[${totalCachedTasks} read from cache]` - )}`, - ...viewLogs, - ]), + output.colors.red( + [ + output.applyNxPrefix( + 'red', + output.colors.red(text) + output.dim(` (${timeTakenText})`) + ), + ...taskOverridesLines, + '', + `${LEFT_PAD}${output.colors.red( + figures.cross + )}${SPACER}${totalFailedTasks}${`/${totalCompletedTasks}`} failed`, + `${LEFT_PAD}${output.dim( + figures.tick + )}${SPACER}${totalSuccessfulTasks}${`/${totalCompletedTasks}`} succeeded ${output.dim( + `[${totalCachedTasks} read from cache]` + )}`, + ...viewLogs, + ].join(EOL) + ), ]; } else { lines = [ @@ -231,7 +235,7 @@ export function getTuiTerminalSummaryLifeCycle({ console.log(''); const lines: string[] = []; - const failure = totalSuccessfulTasks + totalStoppedTasks !== totalTasks; + const failure = totalSuccessfulTasks + stoppedTasks.size !== totalTasks; for (const taskId of taskIdsInOrderOfCompletion) { const { terminalOutput, taskStatus } = tasksToTerminalOutputs[taskId]; @@ -253,7 +257,7 @@ export function getTuiTerminalSummaryLifeCycle({ lines.push(...output.getVerticalSeparatorLines(failure ? 'red' : 'green')); - if (totalSuccessfulTasks + totalStoppedTasks === totalTasks) { + if (totalSuccessfulTasks + stoppedTasks.size === totalTasks) { const successSummaryRows = []; const text = `Successfully ran ${formatTargetsAndProjects( projectNames, @@ -294,7 +298,7 @@ export function getTuiTerminalSummaryLifeCycle({ const text = `${ inProgressTasks.size ? 'Cancelled while running' : 'Ran' } ${formatTargetsAndProjects(projectNames, targets, tasks)}`; - const taskOverridesRows = []; + const taskOverridesRows: string[] = []; if (Object.keys(overrides).length > 0) { taskOverridesRows.push(''); taskOverridesRows.push( @@ -312,7 +316,7 @@ export function getTuiTerminalSummaryLifeCycle({ 0, numFailedToPrint ); - const failureSummaryRows = [ + const failureSummaryRows: string[] = [ output.applyNxPrefix( 'red', output.colors.red(text) + output.dim.white(` (${timeTakenText})`)