From 12528e0ef93fac46ca66f844edc929f7584d14cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Fri, 2 Feb 2024 17:52:05 +0100 Subject: [PATCH] feat(core): add log lines grouping for GH Actions (#21357) (cherry picked from commit 7739ce013bb916870a0b6aac3b9a530a21a7b3f1) --- ...amic-run-one-terminal-output-life-cycle.ts | 10 ++-- .../empty-terminal-output-life-cycle.ts | 3 +- ...nvoke-runner-terminal-output-life-cycle.ts | 3 +- ...tic-run-many-terminal-output-life-cycle.ts | 3 +- ...atic-run-one-terminal-output-life-cycle.ts | 3 +- packages/nx/src/utils/output.ts | 52 +++++++++++++++++-- 6 files changed, 57 insertions(+), 17 deletions(-) diff --git a/packages/nx/src/tasks-runner/life-cycles/dynamic-run-one-terminal-output-life-cycle.ts b/packages/nx/src/tasks-runner/life-cycles/dynamic-run-one-terminal-output-life-cycle.ts index c9352d772dda79..d4d135f62092ee 100644 --- a/packages/nx/src/tasks-runner/life-cycles/dynamic-run-one-terminal-output-life-cycle.ts +++ b/packages/nx/src/tasks-runner/life-cycles/dynamic-run-one-terminal-output-life-cycle.ts @@ -223,8 +223,7 @@ export async function createRunOneDynamicOutputRenderer({ lifeCycle.printTaskTerminalOutput = (task, cacheStatus, terminalOutput) => { if (task.target.project === initiatingProject) { - output.logCommand(task.id, cacheStatus); - process.stdout.write(terminalOutput); + output.logCommandOutput(task.id, cacheStatus, terminalOutput); } else { tasksToTerminalOutputs[task.id] = terminalOutput; } @@ -254,8 +253,11 @@ export async function createRunOneDynamicOutputRenderer({ clearRenderInterval(); renderDependentTargets(false); output.addVerticalSeparator('red'); - output.logCommand(t.task.id, t.status); - process.stdout.write(tasksToTerminalOutputs[t.task.id]); + output.logCommandOutput( + t.task.id, + t.status, + tasksToTerminalOutputs[t.task.id] + ); } break; } diff --git a/packages/nx/src/tasks-runner/life-cycles/empty-terminal-output-life-cycle.ts b/packages/nx/src/tasks-runner/life-cycles/empty-terminal-output-life-cycle.ts index d719e9082b0774..1069551105b67d 100644 --- a/packages/nx/src/tasks-runner/life-cycles/empty-terminal-output-life-cycle.ts +++ b/packages/nx/src/tasks-runner/life-cycles/empty-terminal-output-life-cycle.ts @@ -15,8 +15,7 @@ export class EmptyTerminalOutputLifeCycle implements LifeCycle { cacheStatus === 'skipped' ) { const args = getPrintableCommandArgsForTask(task); - output.logCommand(args.join(' '), cacheStatus); - process.stdout.write(terminalOutput); + output.logCommandOutput(args.join(' '), cacheStatus, terminalOutput); } } } diff --git a/packages/nx/src/tasks-runner/life-cycles/invoke-runner-terminal-output-life-cycle.ts b/packages/nx/src/tasks-runner/life-cycles/invoke-runner-terminal-output-life-cycle.ts index ba9c5e007163a2..c859a1228f856c 100644 --- a/packages/nx/src/tasks-runner/life-cycles/invoke-runner-terminal-output-life-cycle.ts +++ b/packages/nx/src/tasks-runner/life-cycles/invoke-runner-terminal-output-life-cycle.ts @@ -76,7 +76,6 @@ export class InvokeRunnerTerminalOutputLifeCycle implements LifeCycle { terminalOutput: string ) { const args = getPrintableCommandArgsForTask(task); - output.logCommand(args.join(' '), cacheStatus); - process.stdout.write(terminalOutput); + output.logCommandOutput(args.join(' '), cacheStatus, terminalOutput); } } diff --git a/packages/nx/src/tasks-runner/life-cycles/static-run-many-terminal-output-life-cycle.ts b/packages/nx/src/tasks-runner/life-cycles/static-run-many-terminal-output-life-cycle.ts index a2ac5d6ad1b117..5445a5d20b8686 100644 --- a/packages/nx/src/tasks-runner/life-cycles/static-run-many-terminal-output-life-cycle.ts +++ b/packages/nx/src/tasks-runner/life-cycles/static-run-many-terminal-output-life-cycle.ts @@ -149,7 +149,6 @@ export class StaticRunManyTerminalOutputLifeCycle implements LifeCycle { terminalOutput: string ) { const args = getPrintableCommandArgsForTask(task); - output.logCommand(args.join(' '), cacheStatus); - process.stdout.write(terminalOutput); + output.logCommandOutput(args.join(' '), cacheStatus, terminalOutput); } } diff --git a/packages/nx/src/tasks-runner/life-cycles/static-run-one-terminal-output-life-cycle.ts b/packages/nx/src/tasks-runner/life-cycles/static-run-one-terminal-output-life-cycle.ts index 66c3b1046051c2..d456889afe2c37 100644 --- a/packages/nx/src/tasks-runner/life-cycles/static-run-one-terminal-output-life-cycle.ts +++ b/packages/nx/src/tasks-runner/life-cycles/static-run-one-terminal-output-life-cycle.ts @@ -116,8 +116,7 @@ export class StaticRunOneTerminalOutputLifeCycle implements LifeCycle { task.target.project === this.initiatingProject ) { const args = getPrintableCommandArgsForTask(task); - output.logCommand(args.join(' '), status); - process.stdout.write(terminalOutput); + output.logCommandOutput(args.join(' '), status, terminalOutput); } } } diff --git a/packages/nx/src/utils/output.ts b/packages/nx/src/utils/output.ts index ec0b9971aadf34..a3e525f4f35202 100644 --- a/packages/nx/src/utils/output.ts +++ b/packages/nx/src/utils/output.ts @@ -4,6 +4,9 @@ import * as readline from 'readline'; import { isCI } from './is-ci'; import { TaskStatus } from '../tasks-runner/tasks-runner'; +const GH_GROUP_PREFIX = '::group::'; +const GH_GROUP_SUFFIX = '::endgroup::'; + export interface CLIErrorMessageConfig { title: string; bodyLines?: string[]; @@ -228,15 +231,54 @@ class CLIOutput { logCommand(message: string, taskStatus?: TaskStatus) { this.addNewline(); - const commandOutput = - chalk.dim('> ') + this.formatCommand(this.normalizeMessage(message)); - const commandOutputWithStatus = this.addTaskStatus( - taskStatus, - commandOutput + this.writeToStdOut(this.getCommandWithStatus(message, taskStatus)); + this.addNewline(); + this.addNewline(); + } + + logCommandOutput(message: string, taskStatus: TaskStatus, output: string) { + let commandOutputWithStatus = this.getCommandWithStatus( + message, + taskStatus ); + if (process.env.GITHUB_ACTIONS) { + const icon = this.getStatusIcon(taskStatus); + commandOutputWithStatus = `${GH_GROUP_PREFIX}${icon} ${commandOutputWithStatus}`; + } + + this.addNewline(); this.writeToStdOut(commandOutputWithStatus); this.addNewline(); this.addNewline(); + this.writeToStdOut(output); + + if (process.env.GITHUB_ACTIONS) { + this.writeToStdOut(GH_GROUP_SUFFIX); + } + } + + private getCommandWithStatus( + message: string, + taskStatus: TaskStatus + ): string { + const commandOutput = + chalk.dim('> ') + this.formatCommand(this.normalizeMessage(message)); + return this.addTaskStatus(taskStatus, commandOutput); + } + + private getStatusIcon(taskStatus: TaskStatus) { + switch (taskStatus) { + case 'success': + return '✔️'; + case 'failure': + return '❌'; + case 'skipped': + case 'local-cache-kept-existing': + return '⏩'; + case 'local-cache': + case 'remote-cache': + return '🔁'; + } } private normalizeMessage(message: string) {