diff --git a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts index 047fbfe24..ffb9ab06e 100644 --- a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts @@ -192,6 +192,7 @@ describe('executor command', () => { `${project}:code-pushup`, 'collect', '--persist.filename=terminal-report', + '--verbose', ], cwd, }); diff --git a/e2e/nx-plugin-e2e/tests/plugin-create-nodes.e2e.test.ts b/e2e/nx-plugin-e2e/tests/plugin-create-nodes.e2e.test.ts index 43257d570..c7f911a2e 100644 --- a/e2e/nx-plugin-e2e/tests/plugin-create-nodes.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/plugin-create-nodes.e2e.test.ts @@ -173,13 +173,14 @@ describe('nx-plugin', () => { }); const cleanStdout = removeColorCodes(stdout); + // Nx command - expect(cleanStdout).toContain('nx run my-lib:code-pushup'); + expect(cleanStdout).toContain('nx run my-lib:code-pushup --dryRun'); // Run CLI executor - expect(cleanStdout).toContain('Command:'); + expect(cleanStdout).toContain('DryRun execution of:'); expect(cleanStdout).toContain('npx @code-pushup/cli'); - expect(cleanStdout).toContain('--verbose'); - expect(cleanStdout).toContain('--dryRun '); + expect(cleanStdout).not.toContain('--verbose'); + expect(cleanStdout).toContain('CP_VERBOSE="true"'); }); it('should consider plugin option bin in executor target', async () => { diff --git a/packages/nx-plugin/src/executors/cli/executor.int.test.ts b/packages/nx-plugin/src/executors/cli/executor.int.test.ts index fee1e59d8..eaa7f1777 100644 --- a/packages/nx-plugin/src/executors/cli/executor.int.test.ts +++ b/packages/nx-plugin/src/executors/cli/executor.int.test.ts @@ -27,6 +27,7 @@ describe('runAutorunExecutor', () => { }); it('should normalize context, parse CLI options and execute command', async () => { + expect(process.env).not.toHaveProperty('CP_VERBOSE', 'true'); const output = await runAutorunExecutor( { verbose: true }, executorContext('utils'), @@ -48,5 +49,7 @@ describe('runAutorunExecutor', () => { args: expect.arrayContaining(['@code-pushup/cli']), cwd: process.cwd(), }); + + expect(process.env).toHaveProperty('CP_VERBOSE', 'true'); }); }); diff --git a/packages/nx-plugin/src/executors/cli/executor.ts b/packages/nx-plugin/src/executors/cli/executor.ts index a29ab0cbf..066119213 100644 --- a/packages/nx-plugin/src/executors/cli/executor.ts +++ b/packages/nx-plugin/src/executors/cli/executor.ts @@ -1,4 +1,4 @@ -import { type ExecutorContext, logger } from '@nx/devkit'; +import type { ExecutorContext } from '@nx/devkit'; import { executeProcess } from '../../internal/execute-process.js'; import { normalizeContext } from '../internal/context.js'; import type { AutorunCommandExecutorOptions } from './schema.js'; @@ -15,44 +15,43 @@ export default async function runAutorunExecutor( terminalAndExecutorOptions: AutorunCommandExecutorOptions, context: ExecutorContext, ): Promise { - const { objectToCliArgs, formatCommandStatus } = await import( - '@code-pushup/utils' - ); + const { objectToCliArgs, formatCommandStatus, logger, stringifyError } = + await import('@code-pushup/utils'); const normalizedContext = normalizeContext(context); const cliArgumentObject = parseAutorunExecutorOptions( terminalAndExecutorOptions, normalizedContext, ); - const { - dryRun, - verbose, - command: cliCommand, - bin, - } = terminalAndExecutorOptions; + const { command: cliCommand } = terminalAndExecutorOptions; + const { verbose = false, dryRun, bin, ...restArgs } = cliArgumentObject; + logger.setVerbose(verbose); + const command = bin ? `node` : 'npx'; const positionals = [ bin ?? '@code-pushup/cli', ...(cliCommand ? [cliCommand] : []), ]; - const args = [...positionals, ...objectToCliArgs(cliArgumentObject)]; + const args = [...positionals, ...objectToCliArgs(restArgs)]; + const executorEnvVariables = { + ...(verbose && { CP_VERBOSE: 'true' }), + }; const commandString = formatCommandStatus([command, ...args].join(' '), { cwd: context.cwd, + env: executorEnvVariables, }); - if (verbose) { - logger.info(`Run CLI executor ${command ?? ''}`); - logger.info(`Command: ${commandString}`); - } + if (dryRun) { logger.warn(`DryRun execution of: ${commandString}`); } else { try { + logger.debug(`With env vars: ${executorEnvVariables}`); await executeProcess({ command, args, ...(context.cwd ? { cwd: context.cwd } : {}), }); } catch (error) { - logger.error(error); + logger.error(stringifyError(error)); return { success: false, command: commandString, diff --git a/packages/nx-plugin/src/executors/cli/executor.unit.test.ts b/packages/nx-plugin/src/executors/cli/executor.unit.test.ts index 3c9d3d1c3..4736f8196 100644 --- a/packages/nx-plugin/src/executors/cli/executor.unit.test.ts +++ b/packages/nx-plugin/src/executors/cli/executor.unit.test.ts @@ -1,4 +1,3 @@ -import { logger } from '@nx/devkit'; import { afterAll, afterEach, beforeEach, expect, vi } from 'vitest'; import { executorContext } from '@code-pushup/test-nx-utils'; import { MEMFS_VOLUME } from '@code-pushup/test-utils'; @@ -9,9 +8,8 @@ describe('runAutorunExecutor', () => { const processEnvCP = Object.fromEntries( Object.entries(process.env).filter(([k]) => k.startsWith('CP_')), ); - const loggerInfoSpy = vi.spyOn(logger, 'info'); - const loggerWarnSpy = vi.spyOn(logger, 'warn'); const executeProcessSpy = vi.spyOn(executeProcessModule, 'executeProcess'); + let logger: import('@code-pushup/utils').Logger; beforeAll(() => { Object.entries(process.env) @@ -25,7 +23,9 @@ describe('runAutorunExecutor', () => { ); }); - beforeEach(() => { + beforeEach(async () => { + const utils = await import('@code-pushup/utils'); + logger = utils.logger; vi.unstubAllEnvs(); executeProcessSpy.mockResolvedValue({ bin: 'npx ...', @@ -37,8 +37,6 @@ describe('runAutorunExecutor', () => { }); afterEach(() => { - loggerWarnSpy.mockReset(); - loggerInfoSpy.mockReset(); executeProcessSpy.mockReset(); }); @@ -108,30 +106,55 @@ describe('runAutorunExecutor', () => { expect(output.command).toMatch('--upload.project="CLI"'); }); - it('should log information if verbose is set', async () => { + it('should set env var information if verbose is set', async () => { const output = await runAutorunExecutor( - { verbose: true }, + { + verbose: true, + }, { ...executorContext('github-action'), cwd: '' }, ); + expect(executeProcessSpy).toHaveBeenCalledTimes(1); + expect(executeProcessSpy).toHaveBeenCalledWith({ + command: 'npx', + args: expect.arrayContaining(['@code-pushup/cli']), + cwd: '', + }); - expect(output.command).toMatch('--verbose'); - expect(loggerWarnSpy).toHaveBeenCalledTimes(0); - expect(loggerInfoSpy).toHaveBeenCalledTimes(2); - expect(loggerInfoSpy).toHaveBeenCalledWith( - expect.stringContaining(`Run CLI executor`), + expect(process.env).toStrictEqual( + expect.objectContaining({ + CP_VERBOSE: 'true', + }), ); - expect(loggerInfoSpy).toHaveBeenCalledWith( - expect.stringContaining('Command:'), + + expect(output.command).not.toContain('--verbose'); + expect(logger.warn).toHaveBeenCalledTimes(0); + }); + + it('should log env var in dryRun information if verbose is set', async () => { + const output = await runAutorunExecutor( + { + dryRun: true, + verbose: true, + }, + { ...executorContext('github-action'), cwd: '' }, + ); + + expect(executeProcessSpy).toHaveBeenCalledTimes(0); + + expect(output.command).not.toContain('--verbose'); + expect(logger.warn).toHaveBeenCalledTimes(1); + expect(logger.warn).toHaveBeenCalledWith( + expect.stringContaining('CP_VERBOSE="true"'), ); }); it('should log command if dryRun is set', async () => { await runAutorunExecutor({ dryRun: true }, executorContext('utils')); - expect(loggerInfoSpy).toHaveBeenCalledTimes(0); - expect(loggerWarnSpy).toHaveBeenCalledTimes(1); - expect(loggerWarnSpy).toHaveBeenCalledWith( + expect(logger.command).toHaveBeenCalledTimes(0); + expect(logger.warn).toHaveBeenCalledTimes(1); + expect(logger.warn).toHaveBeenCalledWith( expect.stringContaining('DryRun execution of'), ); });