Skip to content

Commit 98d3354

Browse files
authored
fix(core): tui summary should capture more terminal outputs (#31113)
## Current Behavior Some task outputs are missing in terminal outputs ## Expected Behavior Task outputs are present ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
1 parent 6f9cce7 commit 98d3354

File tree

6 files changed

+68
-25
lines changed

6 files changed

+68
-25
lines changed

packages/nx/src/native/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export declare class AppLifeCycle {
1818
__init(doneCallback: () => any): void
1919
registerRunningTask(taskId: string, parserAndWriter: ExternalObject<[ParserArc, WriterArc]>): void
2020
registerRunningTaskWithEmptyParser(taskId: string): void
21-
appendTaskOutput(taskId: string, output: string): void
21+
appendTaskOutput(taskId: string, output: string, isPtyOutput: boolean): void
2222
setTaskStatus(taskId: string, status: TaskStatus): void
2323
registerForcedShutdownCallback(forcedShutdownCallback: () => any): void
2424
__setCloudMessage(message: string): Promise<void>

packages/nx/src/native/tui/lifecycle.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,12 @@ impl AppLifeCycle {
260260
}
261261

262262
#[napi]
263-
pub fn append_task_output(&mut self, task_id: String, output: String) {
264-
let mut app = self.app.lock().unwrap();
265-
app.append_task_output(task_id, output)
263+
pub fn append_task_output(&mut self, task_id: String, output: String, is_pty_output: bool) {
264+
// If its from a pty, we already have it in the parser, so we don't need to append it again
265+
if !is_pty_output {
266+
let mut app = self.app.lock().unwrap();
267+
app.append_task_output(task_id, output)
268+
}
266269
}
267270

268271
#[napi]

packages/nx/src/tasks-runner/life-cycle.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export interface LifeCycle {
7171

7272
registerRunningTaskWithEmptyParser?(taskId: string): void;
7373

74-
appendTaskOutput?(taskId: string, output: string): void;
74+
appendTaskOutput?(taskId: string, output: string, isPtyTask: boolean): void;
7575

7676
setTaskStatus?(taskId: string, status: NativeTaskStatus): void;
7777

@@ -175,10 +175,10 @@ export class CompositeLifeCycle implements LifeCycle {
175175
}
176176
}
177177

178-
appendTaskOutput(taskId: string, output: string): void {
178+
appendTaskOutput(taskId: string, output: string, isPtyTask: boolean): void {
179179
for (let l of this.lifeCycles) {
180180
if (l.appendTaskOutput) {
181-
l.appendTaskOutput(taskId, output);
181+
l.appendTaskOutput(taskId, output, isPtyTask);
182182
}
183183
}
184184
}

packages/nx/src/tasks-runner/life-cycles/tui-summary-life-cycle.spec.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
6060
});
6161

6262
lifeCycle.startTasks([dep], null);
63+
lifeCycle.appendTaskOutput(dep.id, 'boom', true);
6364
lifeCycle.endTasks(
6465
[
6566
{
@@ -118,6 +119,7 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
118119
});
119120

120121
lifeCycle.startTasks([dep], null);
122+
lifeCycle.appendTaskOutput(dep.id, ':)', true);
121123
lifeCycle.endTasks(
122124
[
123125
{
@@ -131,6 +133,7 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
131133
);
132134
lifeCycle.printTaskTerminalOutput(dep, 'success', ':)');
133135
lifeCycle.startTasks([target], null);
136+
lifeCycle.appendTaskOutput(target.id, "Wait, I'm not done yet", true);
134137
lifeCycle.endCommand();
135138

136139
const lines = getOutputLines(printSummary);
@@ -140,6 +143,9 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
140143
> nx run test:pre-test
141144
142145
:)
146+
> nx run test:test
147+
148+
Wait, I'm not done yet
143149
———————————————————————————————————————————————————————————————————————————————
144150
145151
NX Cancelled running target test for project test (37w)
@@ -174,6 +180,7 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
174180
});
175181

176182
lifeCycle.startTasks([dep], null);
183+
lifeCycle.appendTaskOutput(dep.id, ':)', true);
177184
lifeCycle.endTasks(
178185
[
179186
{
@@ -236,6 +243,7 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
236243
});
237244

238245
lifeCycle.startTasks([target], null);
246+
lifeCycle.appendTaskOutput(target.id, 'I was a happy dev server', true);
239247
lifeCycle.setTaskStatus(target.id, NativeTaskStatus.Stopped);
240248
lifeCycle.printTaskTerminalOutput(
241249
target,
@@ -295,7 +303,9 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
295303
resolveRenderIsDonePromise: jest.fn().mockResolvedValue(null),
296304
});
297305

298-
lifeCycle.startTasks([bar, foo], null);
306+
lifeCycle.startTasks([foo, bar], null);
307+
lifeCycle.appendTaskOutput(foo.id, ':)', true);
308+
lifeCycle.appendTaskOutput(bar.id, 'boom', true);
299309
lifeCycle.endTasks(
300310
[
301311
{
@@ -378,6 +388,8 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
378388
});
379389

380390
lifeCycle.startTasks([bar, foo], null);
391+
lifeCycle.appendTaskOutput(foo.id, 'Stop, in the name of', true);
392+
lifeCycle.appendTaskOutput(bar.id, 'Love', true);
381393
lifeCycle.endTasks(
382394
[
383395
{
@@ -396,6 +408,11 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
396408
expect(lines.join('\n')).toMatchInlineSnapshot(`
397409
"
398410
411+
> nx run bar:test
412+
413+
Love
414+
415+
◼ nx run bar:test
399416
✔ nx run foo:test
400417
401418
———————————————————————————————————————————————————————————————————————————————
@@ -446,7 +463,9 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
446463
resolveRenderIsDonePromise: jest.fn().mockResolvedValue(null),
447464
});
448465

449-
lifeCycle.startTasks([bar, foo], null);
466+
lifeCycle.startTasks([foo, bar], null);
467+
lifeCycle.appendTaskOutput(foo.id, ':)', true);
468+
lifeCycle.appendTaskOutput(bar.id, ':)', true);
450469
lifeCycle.endTasks(
451470
[
452471
{

packages/nx/src/tasks-runner/life-cycles/tui-summary-life-cycle.ts

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type { TaskStatus } from '../tasks-runner';
77
import { formatFlags, formatTargetsAndProjects } from './formatting-utils';
88
import { prettyTime } from './pretty-time';
99
import { viewLogsFooterRows } from './view-logs-utils';
10-
import figures = require('figures');
10+
import * as figures from 'figures';
1111
import { getTasksHistoryLifeCycle } from './task-history-life-cycle';
1212
import { getLeafTasks } from '../task-graph-utils';
1313

@@ -50,23 +50,27 @@ export function getTuiTerminalSummaryLifeCycle({
5050
const inProgressTasks = new Set<string>();
5151
const stoppedTasks = new Set<string>();
5252

53-
const tasksToTerminalOutputs: Record<
54-
string,
55-
{ terminalOutput: string; taskStatus: TaskStatus }
56-
> = {};
57-
const taskIdsInOrderOfCompletion: string[] = [];
53+
const tasksToTerminalOutputs: Record<string, string> = {};
54+
const tasksToTaskStatus: Record<string, TaskStatus> = {};
55+
56+
const taskIdsInTheOrderTheyStart: string[] = [];
5857

5958
lifeCycle.startTasks = (tasks) => {
6059
for (let t of tasks) {
60+
tasksToTerminalOutputs[t.id] ??= '';
61+
taskIdsInTheOrderTheyStart.push(t.id);
6162
inProgressTasks.add(t.id);
6263
}
6364
};
6465

65-
lifeCycle.printTaskTerminalOutput = (task, taskStatus, terminalOutput) => {
66-
taskIdsInOrderOfCompletion.push(task.id);
67-
tasksToTerminalOutputs[task.id] = { terminalOutput, taskStatus };
66+
lifeCycle.appendTaskOutput = (taskId, output) => {
67+
tasksToTerminalOutputs[taskId] += output;
6868
};
6969

70+
// TODO(@AgentEnder): The following 2 methods should be one but will need more refactoring
71+
lifeCycle.printTaskTerminalOutput = (task, taskStatus) => {
72+
tasksToTaskStatus[task.id] = taskStatus;
73+
};
7074
lifeCycle.setTaskStatus = (taskId, taskStatus) => {
7175
if (taskStatus === NativeTaskStatus.Stopped) {
7276
stoppedTasks.add(taskId);
@@ -149,8 +153,9 @@ export function getTuiTerminalSummaryLifeCycle({
149153

150154
// Prints task outputs in the order they were completed
151155
// above the summary, since run-one should print all task results.
152-
for (const taskId of taskIdsInOrderOfCompletion) {
153-
const { terminalOutput, taskStatus } = tasksToTerminalOutputs[taskId];
156+
for (const taskId of taskIdsInTheOrderTheyStart) {
157+
const taskStatus = tasksToTaskStatus[taskId];
158+
const terminalOutput = tasksToTerminalOutputs[taskId];
154159
output.logCommandOutput(taskId, taskStatus, terminalOutput);
155160
}
156161

@@ -266,9 +271,19 @@ export function getTuiTerminalSummaryLifeCycle({
266271

267272
const lines: string[] = [''];
268273

269-
for (const taskId of taskIdsInOrderOfCompletion) {
270-
const { terminalOutput, taskStatus } = tasksToTerminalOutputs[taskId];
271-
if (taskStatus === 'failure') {
274+
for (const taskId of taskIdsInTheOrderTheyStart) {
275+
const taskStatus = tasksToTaskStatus[taskId];
276+
const terminalOutput = tasksToTerminalOutputs[taskId];
277+
// Task Status is null?
278+
if (!taskStatus) {
279+
output.logCommandOutput(taskId, taskStatus, terminalOutput);
280+
output.addNewline();
281+
lines.push(
282+
`${LEFT_PAD}${output.colors.cyan(
283+
figures.squareSmallFilled
284+
)}${SPACER}${output.colors.gray('nx run ')}${taskId}`
285+
);
286+
} else if (taskStatus === 'failure') {
272287
output.logCommandOutput(taskId, taskStatus, terminalOutput);
273288
output.addNewline();
274289
lines.push(

packages/nx/src/tasks-runner/task-orchestrator.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,10 +568,13 @@ export class TaskOrchestrator {
568568
task.id,
569569
runningTask.getParserAndWriter()
570570
);
571+
runningTask.onOutput((output) => {
572+
this.options.lifeCycle.appendTaskOutput(task.id, output, true);
573+
});
571574
} else {
572575
this.options.lifeCycle.registerRunningTaskWithEmptyParser(task.id);
573576
runningTask.onOutput((output) => {
574-
this.options.lifeCycle.appendTaskOutput(task.id, output);
577+
this.options.lifeCycle.appendTaskOutput(task.id, output, false);
575578
});
576579
}
577580
}
@@ -640,10 +643,13 @@ export class TaskOrchestrator {
640643
task.id,
641644
runningTask.getParserAndWriter()
642645
);
646+
runningTask.onOutput((output) => {
647+
this.options.lifeCycle.appendTaskOutput(task.id, output, true);
648+
});
643649
} else if ('onOutput' in runningTask) {
644650
this.options.lifeCycle.registerRunningTaskWithEmptyParser(task.id);
645651
runningTask.onOutput((output) => {
646-
this.options.lifeCycle.appendTaskOutput(task.id, output);
652+
this.options.lifeCycle.appendTaskOutput(task.id, output, false);
647653
});
648654
}
649655
}

0 commit comments

Comments
 (0)