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 #
This commit is contained in:
parent
6f9cce78ac
commit
98d3354855
2
packages/nx/src/native/index.d.ts
vendored
2
packages/nx/src/native/index.d.ts
vendored
@ -18,7 +18,7 @@ export declare class AppLifeCycle {
|
|||||||
__init(doneCallback: () => any): void
|
__init(doneCallback: () => any): void
|
||||||
registerRunningTask(taskId: string, parserAndWriter: ExternalObject<[ParserArc, WriterArc]>): void
|
registerRunningTask(taskId: string, parserAndWriter: ExternalObject<[ParserArc, WriterArc]>): void
|
||||||
registerRunningTaskWithEmptyParser(taskId: string): void
|
registerRunningTaskWithEmptyParser(taskId: string): void
|
||||||
appendTaskOutput(taskId: string, output: string): void
|
appendTaskOutput(taskId: string, output: string, isPtyOutput: boolean): void
|
||||||
setTaskStatus(taskId: string, status: TaskStatus): void
|
setTaskStatus(taskId: string, status: TaskStatus): void
|
||||||
registerForcedShutdownCallback(forcedShutdownCallback: () => any): void
|
registerForcedShutdownCallback(forcedShutdownCallback: () => any): void
|
||||||
__setCloudMessage(message: string): Promise<void>
|
__setCloudMessage(message: string): Promise<void>
|
||||||
|
|||||||
@ -260,9 +260,12 @@ impl AppLifeCycle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn append_task_output(&mut self, task_id: String, output: String) {
|
pub fn append_task_output(&mut self, task_id: String, output: String, is_pty_output: bool) {
|
||||||
let mut app = self.app.lock().unwrap();
|
// If its from a pty, we already have it in the parser, so we don't need to append it again
|
||||||
app.append_task_output(task_id, output)
|
if !is_pty_output {
|
||||||
|
let mut app = self.app.lock().unwrap();
|
||||||
|
app.append_task_output(task_id, output)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
|
|||||||
@ -71,7 +71,7 @@ export interface LifeCycle {
|
|||||||
|
|
||||||
registerRunningTaskWithEmptyParser?(taskId: string): void;
|
registerRunningTaskWithEmptyParser?(taskId: string): void;
|
||||||
|
|
||||||
appendTaskOutput?(taskId: string, output: string): void;
|
appendTaskOutput?(taskId: string, output: string, isPtyTask: boolean): void;
|
||||||
|
|
||||||
setTaskStatus?(taskId: string, status: NativeTaskStatus): void;
|
setTaskStatus?(taskId: string, status: NativeTaskStatus): void;
|
||||||
|
|
||||||
@ -175,10 +175,10 @@ export class CompositeLifeCycle implements LifeCycle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appendTaskOutput(taskId: string, output: string): void {
|
appendTaskOutput(taskId: string, output: string, isPtyTask: boolean): void {
|
||||||
for (let l of this.lifeCycles) {
|
for (let l of this.lifeCycles) {
|
||||||
if (l.appendTaskOutput) {
|
if (l.appendTaskOutput) {
|
||||||
l.appendTaskOutput(taskId, output);
|
l.appendTaskOutput(taskId, output, isPtyTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,6 +60,7 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
lifeCycle.startTasks([dep], null);
|
lifeCycle.startTasks([dep], null);
|
||||||
|
lifeCycle.appendTaskOutput(dep.id, 'boom', true);
|
||||||
lifeCycle.endTasks(
|
lifeCycle.endTasks(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -118,6 +119,7 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
lifeCycle.startTasks([dep], null);
|
lifeCycle.startTasks([dep], null);
|
||||||
|
lifeCycle.appendTaskOutput(dep.id, ':)', true);
|
||||||
lifeCycle.endTasks(
|
lifeCycle.endTasks(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -131,6 +133,7 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
|
|||||||
);
|
);
|
||||||
lifeCycle.printTaskTerminalOutput(dep, 'success', ':)');
|
lifeCycle.printTaskTerminalOutput(dep, 'success', ':)');
|
||||||
lifeCycle.startTasks([target], null);
|
lifeCycle.startTasks([target], null);
|
||||||
|
lifeCycle.appendTaskOutput(target.id, "Wait, I'm not done yet", true);
|
||||||
lifeCycle.endCommand();
|
lifeCycle.endCommand();
|
||||||
|
|
||||||
const lines = getOutputLines(printSummary);
|
const lines = getOutputLines(printSummary);
|
||||||
@ -140,6 +143,9 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
|
|||||||
> nx run test:pre-test
|
> nx run test:pre-test
|
||||||
|
|
||||||
:)
|
:)
|
||||||
|
> nx run test:test
|
||||||
|
|
||||||
|
Wait, I'm not done yet
|
||||||
———————————————————————————————————————————————————————————————————————————————
|
———————————————————————————————————————————————————————————————————————————————
|
||||||
|
|
||||||
NX Cancelled running target test for project test (37w)
|
NX Cancelled running target test for project test (37w)
|
||||||
@ -174,6 +180,7 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
lifeCycle.startTasks([dep], null);
|
lifeCycle.startTasks([dep], null);
|
||||||
|
lifeCycle.appendTaskOutput(dep.id, ':)', true);
|
||||||
lifeCycle.endTasks(
|
lifeCycle.endTasks(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -236,6 +243,7 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
lifeCycle.startTasks([target], null);
|
lifeCycle.startTasks([target], null);
|
||||||
|
lifeCycle.appendTaskOutput(target.id, 'I was a happy dev server', true);
|
||||||
lifeCycle.setTaskStatus(target.id, NativeTaskStatus.Stopped);
|
lifeCycle.setTaskStatus(target.id, NativeTaskStatus.Stopped);
|
||||||
lifeCycle.printTaskTerminalOutput(
|
lifeCycle.printTaskTerminalOutput(
|
||||||
target,
|
target,
|
||||||
@ -295,7 +303,9 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
|
|||||||
resolveRenderIsDonePromise: jest.fn().mockResolvedValue(null),
|
resolveRenderIsDonePromise: jest.fn().mockResolvedValue(null),
|
||||||
});
|
});
|
||||||
|
|
||||||
lifeCycle.startTasks([bar, foo], null);
|
lifeCycle.startTasks([foo, bar], null);
|
||||||
|
lifeCycle.appendTaskOutput(foo.id, ':)', true);
|
||||||
|
lifeCycle.appendTaskOutput(bar.id, 'boom', true);
|
||||||
lifeCycle.endTasks(
|
lifeCycle.endTasks(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -378,6 +388,8 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
lifeCycle.startTasks([bar, foo], null);
|
lifeCycle.startTasks([bar, foo], null);
|
||||||
|
lifeCycle.appendTaskOutput(foo.id, 'Stop, in the name of', true);
|
||||||
|
lifeCycle.appendTaskOutput(bar.id, 'Love', true);
|
||||||
lifeCycle.endTasks(
|
lifeCycle.endTasks(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -396,6 +408,11 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
|
|||||||
expect(lines.join('\n')).toMatchInlineSnapshot(`
|
expect(lines.join('\n')).toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
|
|
||||||
|
> nx run bar:test
|
||||||
|
|
||||||
|
Love
|
||||||
|
|
||||||
|
◼ nx run bar:test
|
||||||
✔ nx run foo:test
|
✔ nx run foo:test
|
||||||
|
|
||||||
———————————————————————————————————————————————————————————————————————————————
|
———————————————————————————————————————————————————————————————————————————————
|
||||||
@ -446,7 +463,9 @@ describe('getTuiTerminalSummaryLifeCycle', () => {
|
|||||||
resolveRenderIsDonePromise: jest.fn().mockResolvedValue(null),
|
resolveRenderIsDonePromise: jest.fn().mockResolvedValue(null),
|
||||||
});
|
});
|
||||||
|
|
||||||
lifeCycle.startTasks([bar, foo], null);
|
lifeCycle.startTasks([foo, bar], null);
|
||||||
|
lifeCycle.appendTaskOutput(foo.id, ':)', true);
|
||||||
|
lifeCycle.appendTaskOutput(bar.id, ':)', true);
|
||||||
lifeCycle.endTasks(
|
lifeCycle.endTasks(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import type { TaskStatus } from '../tasks-runner';
|
|||||||
import { formatFlags, formatTargetsAndProjects } from './formatting-utils';
|
import { formatFlags, formatTargetsAndProjects } from './formatting-utils';
|
||||||
import { prettyTime } from './pretty-time';
|
import { prettyTime } from './pretty-time';
|
||||||
import { viewLogsFooterRows } from './view-logs-utils';
|
import { viewLogsFooterRows } from './view-logs-utils';
|
||||||
import figures = require('figures');
|
import * as figures from 'figures';
|
||||||
import { getTasksHistoryLifeCycle } from './task-history-life-cycle';
|
import { getTasksHistoryLifeCycle } from './task-history-life-cycle';
|
||||||
import { getLeafTasks } from '../task-graph-utils';
|
import { getLeafTasks } from '../task-graph-utils';
|
||||||
|
|
||||||
@ -50,23 +50,27 @@ export function getTuiTerminalSummaryLifeCycle({
|
|||||||
const inProgressTasks = new Set<string>();
|
const inProgressTasks = new Set<string>();
|
||||||
const stoppedTasks = new Set<string>();
|
const stoppedTasks = new Set<string>();
|
||||||
|
|
||||||
const tasksToTerminalOutputs: Record<
|
const tasksToTerminalOutputs: Record<string, string> = {};
|
||||||
string,
|
const tasksToTaskStatus: Record<string, TaskStatus> = {};
|
||||||
{ terminalOutput: string; taskStatus: TaskStatus }
|
|
||||||
> = {};
|
const taskIdsInTheOrderTheyStart: string[] = [];
|
||||||
const taskIdsInOrderOfCompletion: string[] = [];
|
|
||||||
|
|
||||||
lifeCycle.startTasks = (tasks) => {
|
lifeCycle.startTasks = (tasks) => {
|
||||||
for (let t of tasks) {
|
for (let t of tasks) {
|
||||||
|
tasksToTerminalOutputs[t.id] ??= '';
|
||||||
|
taskIdsInTheOrderTheyStart.push(t.id);
|
||||||
inProgressTasks.add(t.id);
|
inProgressTasks.add(t.id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
lifeCycle.printTaskTerminalOutput = (task, taskStatus, terminalOutput) => {
|
lifeCycle.appendTaskOutput = (taskId, output) => {
|
||||||
taskIdsInOrderOfCompletion.push(task.id);
|
tasksToTerminalOutputs[taskId] += output;
|
||||||
tasksToTerminalOutputs[task.id] = { terminalOutput, taskStatus };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO(@AgentEnder): The following 2 methods should be one but will need more refactoring
|
||||||
|
lifeCycle.printTaskTerminalOutput = (task, taskStatus) => {
|
||||||
|
tasksToTaskStatus[task.id] = taskStatus;
|
||||||
|
};
|
||||||
lifeCycle.setTaskStatus = (taskId, taskStatus) => {
|
lifeCycle.setTaskStatus = (taskId, taskStatus) => {
|
||||||
if (taskStatus === NativeTaskStatus.Stopped) {
|
if (taskStatus === NativeTaskStatus.Stopped) {
|
||||||
stoppedTasks.add(taskId);
|
stoppedTasks.add(taskId);
|
||||||
@ -149,8 +153,9 @@ export function getTuiTerminalSummaryLifeCycle({
|
|||||||
|
|
||||||
// Prints task outputs in the order they were completed
|
// Prints task outputs in the order they were completed
|
||||||
// above the summary, since run-one should print all task results.
|
// above the summary, since run-one should print all task results.
|
||||||
for (const taskId of taskIdsInOrderOfCompletion) {
|
for (const taskId of taskIdsInTheOrderTheyStart) {
|
||||||
const { terminalOutput, taskStatus } = tasksToTerminalOutputs[taskId];
|
const taskStatus = tasksToTaskStatus[taskId];
|
||||||
|
const terminalOutput = tasksToTerminalOutputs[taskId];
|
||||||
output.logCommandOutput(taskId, taskStatus, terminalOutput);
|
output.logCommandOutput(taskId, taskStatus, terminalOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,9 +271,19 @@ export function getTuiTerminalSummaryLifeCycle({
|
|||||||
|
|
||||||
const lines: string[] = [''];
|
const lines: string[] = [''];
|
||||||
|
|
||||||
for (const taskId of taskIdsInOrderOfCompletion) {
|
for (const taskId of taskIdsInTheOrderTheyStart) {
|
||||||
const { terminalOutput, taskStatus } = tasksToTerminalOutputs[taskId];
|
const taskStatus = tasksToTaskStatus[taskId];
|
||||||
if (taskStatus === 'failure') {
|
const terminalOutput = tasksToTerminalOutputs[taskId];
|
||||||
|
// Task Status is null?
|
||||||
|
if (!taskStatus) {
|
||||||
|
output.logCommandOutput(taskId, taskStatus, terminalOutput);
|
||||||
|
output.addNewline();
|
||||||
|
lines.push(
|
||||||
|
`${LEFT_PAD}${output.colors.cyan(
|
||||||
|
figures.squareSmallFilled
|
||||||
|
)}${SPACER}${output.colors.gray('nx run ')}${taskId}`
|
||||||
|
);
|
||||||
|
} else if (taskStatus === 'failure') {
|
||||||
output.logCommandOutput(taskId, taskStatus, terminalOutput);
|
output.logCommandOutput(taskId, taskStatus, terminalOutput);
|
||||||
output.addNewline();
|
output.addNewline();
|
||||||
lines.push(
|
lines.push(
|
||||||
|
|||||||
@ -568,10 +568,13 @@ export class TaskOrchestrator {
|
|||||||
task.id,
|
task.id,
|
||||||
runningTask.getParserAndWriter()
|
runningTask.getParserAndWriter()
|
||||||
);
|
);
|
||||||
|
runningTask.onOutput((output) => {
|
||||||
|
this.options.lifeCycle.appendTaskOutput(task.id, output, true);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.options.lifeCycle.registerRunningTaskWithEmptyParser(task.id);
|
this.options.lifeCycle.registerRunningTaskWithEmptyParser(task.id);
|
||||||
runningTask.onOutput((output) => {
|
runningTask.onOutput((output) => {
|
||||||
this.options.lifeCycle.appendTaskOutput(task.id, output);
|
this.options.lifeCycle.appendTaskOutput(task.id, output, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -640,10 +643,13 @@ export class TaskOrchestrator {
|
|||||||
task.id,
|
task.id,
|
||||||
runningTask.getParserAndWriter()
|
runningTask.getParserAndWriter()
|
||||||
);
|
);
|
||||||
|
runningTask.onOutput((output) => {
|
||||||
|
this.options.lifeCycle.appendTaskOutput(task.id, output, true);
|
||||||
|
});
|
||||||
} else if ('onOutput' in runningTask) {
|
} else if ('onOutput' in runningTask) {
|
||||||
this.options.lifeCycle.registerRunningTaskWithEmptyParser(task.id);
|
this.options.lifeCycle.registerRunningTaskWithEmptyParser(task.id);
|
||||||
runningTask.onOutput((output) => {
|
runningTask.onOutput((output) => {
|
||||||
this.options.lifeCycle.appendTaskOutput(task.id, output);
|
this.options.lifeCycle.appendTaskOutput(task.id, output, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user