feat(core): nx report should support encapsulated installs (#15032)

This commit is contained in:
Craigory Coppola 2023-02-15 16:29:31 -05:00 committed by GitHub
parent b0f68aa0d7
commit 56289555fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 163 additions and 72 deletions

View File

@ -1,19 +1,13 @@
import { NxJsonConfiguration } from '@nrwl/devkit';
import {
checkFilesDoNotExist,
checkFilesExist,
cleanupProject,
createNonNxProjectDirectory,
getPackageManagerCommand,
getPublishedVersion,
getSelectedPackageManager,
newEncapsulatedNxWorkspace,
removeFile,
renameFile,
runCLI,
runCommand,
updateFile,
updateJson,
} from '@nrwl/e2e/utils';
describe('nx init', () => {
@ -102,60 +96,4 @@ describe('nx init', () => {
expect(output).not.toContain('HELLO COMPOUND');
cleanupProject();
});
describe('encapsulated', () => {
it('should support running targets in a encapsulated repo', () => {
const runEncapsulatedNx = newEncapsulatedNxWorkspace();
updateFile(
'projects/a/project.json',
JSON.stringify({
name: 'a',
targets: {
echo: {
command: `echo 'Hello from A'`,
},
},
})
);
updateJson<NxJsonConfiguration>('nx.json', (json) => ({
...json,
tasksRunnerOptions: {
default: {
...json.tasksRunnerOptions['default'],
options: {
...json.tasksRunnerOptions['default'].options,
cacheableOperations: ['echo'],
},
},
},
}));
expect(runEncapsulatedNx('echo a')).toContain('Hello from A');
expect(runEncapsulatedNx('echo a')).toContain(
'Nx read the output from the cache instead of running the command for 1 out of 1 tasks'
);
expect(() =>
checkFilesDoNotExist(
'node_modules',
'package.json',
'package-lock.json',
'yarn-lock.json',
'pnpm-lock.yaml'
)
).not.toThrow();
expect(() =>
checkFilesExist(
'.nx/installation/package.json',
'.nx/installation/package-lock.json',
'.nx/cache/terminalOutputs'
)
).not.toThrow();
});
cleanupProject({
skipReset: true,
});
});
});

View File

@ -0,0 +1,84 @@
import type { NxJsonConfiguration } from '@nrwl/devkit';
import {
newEncapsulatedNxWorkspace,
updateFile,
updateJson,
checkFilesDoNotExist,
checkFilesExist,
cleanupProject,
getPublishedVersion,
} from '@nrwl/e2e/utils';
describe('encapsulated nx', () => {
let runEncapsulatedNx: ReturnType<typeof newEncapsulatedNxWorkspace>;
beforeAll(() => {
runEncapsulatedNx = newEncapsulatedNxWorkspace();
});
afterAll(() => {
cleanupProject({
skipReset: true,
});
});
it('should support running targets in a encapsulated repo', () => {
updateFile(
'projects/a/project.json',
JSON.stringify({
name: 'a',
targets: {
echo: {
command: `echo 'Hello from A'`,
},
},
})
);
updateJson<NxJsonConfiguration>('nx.json', (json) => ({
...json,
tasksRunnerOptions: {
default: {
...json.tasksRunnerOptions['default'],
options: {
...json.tasksRunnerOptions['default'].options,
cacheableOperations: ['echo'],
},
},
},
}));
expect(runEncapsulatedNx('echo a')).toContain('Hello from A');
expect(runEncapsulatedNx('echo a')).toContain(
'Nx read the output from the cache instead of running the command for 1 out of 1 tasks'
);
assertNoRootPackages();
expect(() =>
checkFilesExist(
'.nx/installation/package.json',
'.nx/installation/package-lock.json',
'.nx/cache/terminalOutputs'
)
).not.toThrow();
});
it('should work with nx report', () => {
expect(runEncapsulatedNx('report')).toMatch(
new RegExp(`nx.*:.*${getPublishedVersion()}`)
);
});
});
function assertNoRootPackages() {
expect(() =>
checkFilesDoNotExist(
'node_modules',
'package.json',
'package-lock.json',
'yarn-lock.json',
'pnpm-lock.yaml'
)
).not.toThrow();
}

View File

@ -22,7 +22,6 @@ describe('report', () => {
it('should read angular-devkit plugins', () => {
jest.spyOn(fileUtils, 'readJsonFile').mockImplementation((path) => {
console.log(path);
if (path === 'package.json') {
return {
dependencies: {
@ -32,6 +31,8 @@ describe('report', () => {
'plugin-two': '2.0.0',
},
};
} else if (path === 'nx.json') {
return {};
}
});
jest.spyOn(packageJsonUtils, 'readModulePackageJson').mockImplementation(
@ -64,6 +65,8 @@ describe('report', () => {
'plugin-two': '2.0.0',
},
};
} else if (path === 'nx.json') {
return {};
}
});
jest.spyOn(packageJsonUtils, 'readModulePackageJson').mockImplementation(
@ -91,6 +94,8 @@ describe('report', () => {
'plugin-two': '2.0.0',
},
};
} else if (path === 'nx.json') {
return {};
}
});
jest.spyOn(packageJsonUtils, 'readModulePackageJson').mockImplementation(
@ -112,6 +117,47 @@ describe('report', () => {
]);
});
it('should read nx plugins from installations', () => {
jest.spyOn(fileUtils, 'readJsonFile').mockImplementation((path) => {
if (path === 'package.json') {
return {
dependencies: {},
devDependencies: {
'plugin-two': '2.0.0',
},
};
} else if (path === 'nx.json') {
return {
installation: {
version: '1.12.0',
plugins: {
'plugin-one': '1.0.0',
},
},
};
}
});
jest.spyOn(packageJsonUtils, 'readModulePackageJson').mockImplementation(
provideMockPackages({
'plugin-one': {
'nx-migrations': {},
version: '1.0.0',
},
'plugin-two': {
generators: '',
version: '2.0.0',
},
})
);
const plugins = findInstalledCommunityPlugins();
expect(plugins).toEqual(
expect.arrayContaining([
expect.objectContaining({ package: 'plugin-one', version: '1.0.0' }),
expect.objectContaining({ package: 'plugin-two', version: '2.0.0' }),
])
);
});
it('should not include non-plugins', () => {
jest.spyOn(fileUtils, 'readJsonFile').mockImplementation((path) => {
if (path === 'package.json') {
@ -124,6 +170,8 @@ describe('report', () => {
'other-package': '1.44.0',
},
};
} else if (path === 'nx.json') {
return {};
}
});
jest.spyOn(packageJsonUtils, 'readModulePackageJson').mockImplementation(

View File

@ -19,6 +19,7 @@ import {
readProjectsConfigurationFromProjectGraph,
} from '../project-graph/project-graph';
import { gt, valid } from 'semver';
import { NxJsonConfiguration } from '../config/nx-json';
const nxPackageJson = readJsonFile<typeof import('../../package.json')>(
join(__dirname, '../../package.json')
@ -190,7 +191,10 @@ async function findLocalPlugins() {
function readPackageJson(p: string): PackageJson | null {
try {
return readModulePackageJson(p).packageJson;
return readModulePackageJson(p, [
workspaceRoot,
join(workspaceRoot, '.nx', 'installation'),
]).packageJson;
} catch {
return null;
}
@ -248,14 +252,9 @@ export function findMisalignedPackagesForPackage(
export function findInstalledCommunityPlugins(): (PackageJson & {
package: string;
})[] {
const { dependencies, devDependencies } = readJsonFile(
join(workspaceRoot, 'package.json')
);
const deps = [
Object.keys(dependencies || {}),
Object.keys(devDependencies || {}),
].flat();
const packageJsonDeps = getDependenciesFromPackageJson();
const nxJsonDeps = getDependenciesFromNxJson();
const deps = packageJsonDeps.concat(nxJsonDeps);
return deps.reduce(
(arr: any[], nextDep: string): { project: string; version: string }[] => {
if (
@ -302,3 +301,25 @@ export function findInstalledPackagesWeCareAbout() {
return acc;
}, [] as { package: string; version: string }[]);
}
function getDependenciesFromPackageJson(
packageJsonPath = 'package.json'
): string[] {
try {
const { dependencies, devDependencies } = readJsonFile(
join(workspaceRoot, packageJsonPath)
);
return Object.keys({ ...dependencies, ...devDependencies });
} catch {}
return [];
}
function getDependenciesFromNxJson(): string[] {
const { installation } = readJsonFile<NxJsonConfiguration>(
join(workspaceRoot, 'nx.json')
);
if (!installation) {
return [];
}
return ['nx', ...Object.keys(installation.plugins || {})];
}