chore(node): decrease e2e times (#20666)

This commit is contained in:
Jason Jean 2023-12-08 16:19:47 -05:00 committed by GitHub
parent 5a305d41de
commit 4ec134f9d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 202 additions and 121 deletions

View File

@ -6,20 +6,21 @@ import {
promisifiedTreeKill,
readFile,
runCLI,
runCLIAsync,
runCommandUntil,
setMaxWorkers,
tmpProjPath,
uniq,
updateFile,
} from '@nx/e2e/utils';
import { execSync } from 'child_process';
import { join } from 'path';
describe('Node Applications + esbuild', () => {
beforeEach(() => newProject());
beforeAll(() =>
newProject({
packages: ['@nx/node'],
})
);
afterEach(() => cleanupProject());
afterAll(() => cleanupProject());
it('should generate an app using esbuild', async () => {
const app = uniq('nodeapp');

View File

@ -17,11 +17,13 @@ import { join } from 'path';
describe('Node Applications + webpack', () => {
let proj: string;
beforeEach(() => {
proj = newProject();
beforeAll(() => {
proj = newProject({
packages: ['@nx/node'],
});
});
afterEach(() => cleanupProject());
afterAll(() => cleanupProject());
function addLibImport(appName: string, libName: string, importPath?: string) {
const content = readFile(`apps/${appName}/src/main.ts`);

View File

@ -17,9 +17,13 @@ import { execSync } from 'child_process';
import { join } from 'path';
describe('Node Applications + webpack', () => {
beforeEach(() => newProject());
beforeAll(() =>
newProject({
packages: ['@nx/node'],
})
);
afterEach(() => cleanupProject());
afterAll(() => cleanupProject());
it('should generate an app using webpack', async () => {
const app = uniq('nodeapp');

View File

@ -50,9 +50,13 @@ function getData(port, path = '/api'): Promise<any> {
}
describe('Node Applications', () => {
beforeEach(() => newProject());
beforeAll(() =>
newProject({
packages: ['@nx/node', '@nx/express', '@nx/nest'],
})
);
afterEach(() => cleanupProject());
afterAll(() => cleanupProject());
it('should be able to generate an empty application', async () => {
const nodeapp = uniq('nodeapp');
@ -331,12 +335,16 @@ describe('Node Applications', () => {
});
describe('Build Node apps', () => {
beforeEach(() => newProject());
let scope: string;
beforeAll(() => {
scope = newProject({
packages: ['@nx/node', '@nx/express', '@nx/nest'],
});
});
afterEach(() => cleanupProject());
afterAll(() => cleanupProject());
it('should generate a package.json with the `--generatePackageJson` flag', async () => {
const scope = newProject();
const packageManager = detectPackageManager(tmpProjPath());
const nestapp = uniq('nestapp');
runCLI(`generate @nx/nest:app ${nestapp} --linter=eslint`);
@ -523,7 +531,6 @@ ${jslib}();
describe('NestJS', () => {
it('should have plugin output if specified in `tsPlugins`', async () => {
newProject();
const nestapp = uniq('nestapp');
runCLI(`generate @nx/nest:app ${nestapp} --linter=eslint`);
setMaxWorkers(join('apps', nestapp, 'project.json'));
@ -576,11 +583,8 @@ ${jslib}();
expect(mainJs).toContain('_OPENAPI_METADATA_FACTORY');
}, 300000);
});
});
describe('nest libraries', function () {
beforeEach(() => newProject());
it('should be able to generate a nest library', async () => {
const nestlib = uniq('nestlib');
runCLI(`generate @nx/nest:lib ${nestlib}`);
@ -637,7 +641,6 @@ describe('nest libraries', function () {
}, 200000);
it('should have plugin output if specified in `transformers`', async () => {
newProject();
const nestlib = uniq('nestlib');
runCLI(`generate @nx/nest:lib ${nestlib} --buildable`);
@ -688,3 +691,4 @@ exports.FooModel = FooModel;
await expectJestTestsToPass('@nx/node:lib');
}, 100000);
});
});

View File

@ -21,6 +21,7 @@ import { angularCliVersion as defaultAngularCliVersion } from '@nx/workspace/src
import { dump } from '@zkochan/js-yaml';
import { execSync, ExecSyncOptions } from 'child_process';
import { performance, PerformanceMeasure } from 'perf_hooks';
import { logError, logInfo } from './log-utils';
import {
getPackageManagerCommand,
@ -28,49 +29,15 @@ import {
RunCmdOpts,
runCommand,
} from './command-utils';
import { NxJsonConfiguration, output } from '@nx/devkit';
import { output } from '@nx/devkit';
import { readFileSync } from 'fs';
import { join } from 'path';
import { resetWorkspaceContext } from 'nx/src/utils/workspace-context';
let projName: string;
/**
* Sets up a new project in the temporary project path
* for the currently selected CLI.
*/
export function newProject({
name = uniq('proj'),
packageManager = getSelectedPackageManager(),
unsetProjectNameAndRootFormat = true,
} = {}): string {
try {
const projScope = 'proj';
if (!directoryExists(tmpBackupProjPath())) {
runCreateWorkspace(projScope, {
preset: 'apps',
packageManager,
});
if (unsetProjectNameAndRootFormat) {
console.warn(
'ATTENTION: The workspace generated for this e2e test does not use the new as-provided project name/root format. Please update this test'
);
createFile('apps/.gitkeep');
createFile('libs/.gitkeep');
}
// Temporary hack to prevent installing with `--frozen-lockfile`
if (isCI && packageManager === 'pnpm') {
updateFile(
'.npmrc',
'prefer-frozen-lockfile=false\nstrict-peer-dependencies=false\nauto-install-peers=true'
);
}
// TODO(jack): we should tag the projects (e.g. tags: ['package']) and filter from that rather than hard-code packages.
const packages = [
const nxPackages = [
`@nx/angular`,
`@nx/eslint-plugin`,
`@nx/express`,
@ -93,9 +60,76 @@ export function newProject({
`@nx/webpack`,
`@nx/react-native`,
`@nx/expo`,
];
packageInstall(packages.join(` `), projScope);
] as const;
type NxPackage = typeof nxPackages[number];
/**
* Sets up a new project in the temporary project path
* for the currently selected CLI.
*/
export function newProject({
name = uniq('proj'),
packageManager = getSelectedPackageManager(),
unsetProjectNameAndRootFormat = true,
packages,
}: {
name?: string;
packageManager?: 'npm' | 'yarn' | 'pnpm';
unsetProjectNameAndRootFormat?: boolean;
readonly packages?: Array<NxPackage>;
} = {}): string {
const newProjectStart = performance.mark('new-project:start');
try {
const projScope = 'proj';
let createNxWorkspaceMeasure: PerformanceMeasure;
let packageInstallMeasure: PerformanceMeasure;
if (!directoryExists(tmpBackupProjPath())) {
const createNxWorkspaceStart = performance.mark(
'create-nx-workspace:start'
);
runCreateWorkspace(projScope, {
preset: 'apps',
packageManager,
});
const createNxWorkspaceEnd = performance.mark('create-nx-workspace:end');
createNxWorkspaceMeasure = performance.measure(
'create-nx-workspace',
createNxWorkspaceStart.name,
createNxWorkspaceEnd.name
);
if (unsetProjectNameAndRootFormat) {
console.warn(
'ATTENTION: The workspace generated for this e2e test does not use the new as-provided project name/root format. Please update this test'
);
createFile('apps/.gitkeep');
createFile('libs/.gitkeep');
}
// Temporary hack to prevent installing with `--frozen-lockfile`
if (isCI && packageManager === 'pnpm') {
updateFile(
'.npmrc',
'prefer-frozen-lockfile=false\nstrict-peer-dependencies=false\nauto-install-peers=true'
);
}
if (!packages) {
console.warn(
'ATTENTION: All packages are installed into the new workspace. To make this test faster, please pass the subset of packages that this test needs by passing a packages array in the options'
);
}
const packageInstallStart = performance.mark('packageInstall:start');
packageInstall((packages ?? nxPackages).join(` `), projScope);
const packageInstallEnd = performance.mark('packageInstall:end');
packageInstallMeasure = performance.measure(
'packageInstall',
packageInstallStart.name,
packageInstallEnd.name
);
// stop the daemon
execSync(`${getPackageManagerCommand().runNx} reset`, {
cwd: `${e2eCwd}/proj`,
@ -105,19 +139,55 @@ export function newProject({
moveSync(`${e2eCwd}/proj`, `${tmpBackupProjPath()}`);
}
projName = name;
copySync(`${tmpBackupProjPath()}`, `${tmpProjPath()}`);
if (isVerbose()) {
logInfo(`NX`, `E2E created a project: ${tmpProjPath()}`);
}
const projectDirectory = tmpProjPath();
copySync(`${tmpBackupProjPath()}`, `${projectDirectory}`);
// TODO: What is this for?
if (packageManager === 'pnpm') {
execSync(getPackageManagerCommand().install, {
cwd: tmpProjPath(),
cwd: projectDirectory,
stdio: 'pipe',
env: { CI: 'true', ...process.env },
encoding: 'utf-8',
});
}
const newProjectEnd = performance.mark('new-project:end');
const perfMeasure = performance.measure(
'newProject',
newProjectStart.name,
newProjectEnd.name
);
if (isVerbose()) {
logInfo(
`NX`,
`E2E created a project: ${projectDirectory} in ${
perfMeasure.duration / 1000
} seconds
${
createNxWorkspaceMeasure
? `create-nx-workspace: ${
createNxWorkspaceMeasure.duration / 1000
} seconds\n`
: ''
}${
packageInstallMeasure
? `packageInstall: ${
packageInstallMeasure.duration / 1000
} seconds\n`
: ''
}`
);
}
if (process.env.NX_E2E_EDITOR) {
const editor = process.env.NX_E2E_EDITOR;
execSync(`${editor} ${projectDirectory}`, {
stdio: 'inherit',
});
}
return projScope;
} catch (e) {
logError(`Failed to set up project for e2e tests.`, e.message);