fix(js): node executor should always log error (#17622)
This commit is contained in:
parent
bfe8e47d23
commit
36838d6211
50
e2e/js/src/js-node.test.ts
Normal file
50
e2e/js/src/js-node.test.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import {
|
||||
cleanupProject,
|
||||
newProject,
|
||||
runCLI,
|
||||
uniq,
|
||||
updateFile,
|
||||
updateProjectConfig,
|
||||
} from '@nx/e2e/utils';
|
||||
|
||||
describe('js:node error handling', () => {
|
||||
let scope: string;
|
||||
|
||||
beforeEach(() => {
|
||||
scope = newProject();
|
||||
});
|
||||
|
||||
afterEach(() => cleanupProject());
|
||||
|
||||
it('should log out the error', () => {
|
||||
const esbuildLib = uniq('esbuildlib');
|
||||
|
||||
runCLI(
|
||||
`generate @nx/js:lib ${esbuildLib} --bundler=esbuild --no-interactive`
|
||||
);
|
||||
|
||||
updateFile(`libs/${esbuildLib}/src/index.ts`, () => {
|
||||
return `
|
||||
console.log('Hello from my library!');
|
||||
throw new Error('This is an error');
|
||||
`;
|
||||
});
|
||||
|
||||
updateProjectConfig(esbuildLib, (config) => {
|
||||
config.targets['run-node'] = {
|
||||
executor: '@nx/js:node',
|
||||
options: {
|
||||
buildTarget: `${esbuildLib}:build`,
|
||||
watch: false,
|
||||
},
|
||||
};
|
||||
return config;
|
||||
});
|
||||
|
||||
const output = runCLI(`run ${esbuildLib}:run-node`, {
|
||||
redirectStderr: true,
|
||||
});
|
||||
expect(output).toContain('Hello from my library!');
|
||||
expect(output).toContain('This is an error');
|
||||
}, 240_000);
|
||||
});
|
||||
@ -23,6 +23,7 @@ export interface RunCmdOpts {
|
||||
cwd?: string;
|
||||
silent?: boolean;
|
||||
verbose?: boolean;
|
||||
redirectStderr?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -325,26 +326,25 @@ export function runCLI(
|
||||
silenceError: false,
|
||||
env: undefined,
|
||||
verbose: undefined,
|
||||
redirectStderr: undefined,
|
||||
}
|
||||
): string {
|
||||
try {
|
||||
const pm = getPackageManagerCommand();
|
||||
const logs = execSync(
|
||||
`${pm.runNxSilent} ${command} ${
|
||||
opts.verbose ?? isVerboseE2ERun() ? ' --verbose' : ''
|
||||
}`,
|
||||
{
|
||||
cwd: opts.cwd || tmpProjPath(),
|
||||
env: {
|
||||
CI: 'true',
|
||||
...getStrippedEnvironmentVariables(),
|
||||
...opts.env,
|
||||
},
|
||||
encoding: 'utf-8',
|
||||
stdio: 'pipe',
|
||||
maxBuffer: 50 * 1024 * 1024,
|
||||
}
|
||||
);
|
||||
const commandToRun = `${pm.runNxSilent} ${command} ${
|
||||
opts.verbose ?? isVerboseE2ERun() ? ' --verbose' : ''
|
||||
}${opts.redirectStderr ? ' 2>&1' : ''}`;
|
||||
const logs = execSync(commandToRun, {
|
||||
cwd: opts.cwd || tmpProjPath(),
|
||||
env: {
|
||||
CI: 'true',
|
||||
...getStrippedEnvironmentVariables(),
|
||||
...opts.env,
|
||||
},
|
||||
encoding: 'utf-8',
|
||||
stdio: 'pipe',
|
||||
maxBuffer: 50 * 1024 * 1024,
|
||||
});
|
||||
|
||||
if (opts.verbose ?? isVerboseE2ERun()) {
|
||||
output.log({
|
||||
|
||||
@ -10,11 +10,13 @@ import {
|
||||
import { daemonClient } from 'nx/src/daemon/client/client';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { join } from 'path';
|
||||
import * as path from 'path';
|
||||
|
||||
import { InspectType, NodeExecutorOptions } from './schema';
|
||||
import { createAsyncIterable } from '@nx/devkit/src/utils/async-iterable';
|
||||
import { calculateProjectDependencies } from '../../utils/buildable-libs-utils';
|
||||
import { killTree } from './lib/kill-tree';
|
||||
import { fileExists } from 'nx/src/utils/fileutils';
|
||||
|
||||
interface ActiveTask {
|
||||
id: string;
|
||||
@ -71,12 +73,11 @@ export async function* nodeExecutor(
|
||||
|
||||
// Re-map buildable workspace projects to their output directory.
|
||||
const mappings = calculateResolveMappings(context, options);
|
||||
const fileToRun = join(
|
||||
context.root,
|
||||
buildOptions.outputPath,
|
||||
buildOptions.outputFileName ?? 'main.js'
|
||||
);
|
||||
|
||||
const outputFileName =
|
||||
buildOptions.outputFileName ?? `${path.parse(buildOptions.main).name}.js`;
|
||||
|
||||
const fileToRun = join(context.root, buildOptions.outputPath, outputFileName);
|
||||
const tasks: ActiveTask[] = [];
|
||||
let currentTask: ActiveTask = null;
|
||||
|
||||
@ -159,7 +160,7 @@ export async function* nodeExecutor(
|
||||
stdio: [0, 1, 'pipe', 'ipc'],
|
||||
env: {
|
||||
...process.env,
|
||||
NX_FILE_TO_RUN: fileToRun,
|
||||
NX_FILE_TO_RUN: fileToRunCorrectPath(fileToRun),
|
||||
NX_MAPPINGS: JSON.stringify(mappings),
|
||||
},
|
||||
}
|
||||
@ -168,7 +169,8 @@ export async function* nodeExecutor(
|
||||
task.childProcess.stderr.on('data', (data) => {
|
||||
// Don't log out error if task is killed and new one has started.
|
||||
// This could happen if a new build is triggered while new process is starting, since the operation is not atomic.
|
||||
if (options.watch && !task.killed) {
|
||||
// Log the error in normal mode
|
||||
if (!options.watch || !task.killed) {
|
||||
logger.error(data.toString());
|
||||
}
|
||||
});
|
||||
@ -304,4 +306,23 @@ function runWaitUntilTargets(
|
||||
);
|
||||
}
|
||||
|
||||
function fileToRunCorrectPath(fileToRun: string): string {
|
||||
if (!fileExists(fileToRun)) {
|
||||
const cjsFile = fileToRun.replace(/\.js$/, '.cjs');
|
||||
if (fileExists(cjsFile)) {
|
||||
fileToRun = cjsFile;
|
||||
} else {
|
||||
const mjsFile = fileToRun.replace(/\.js$/, '.mjs');
|
||||
if (fileExists(mjsFile)) {
|
||||
fileToRun = mjsFile;
|
||||
} else {
|
||||
throw new Error(
|
||||
`Could not find ${fileToRun}. Make sure your build succeeded.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileToRun;
|
||||
}
|
||||
|
||||
export default nodeExecutor;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user