fix(misc): nx version should report global version outside of an nx repo (#16918)

This commit is contained in:
Craigory Coppola 2023-05-10 18:09:19 -04:00 committed by GitHub
parent 548f8d7fb1
commit 09525e8b30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 146 additions and 99 deletions

View File

@ -1,6 +1,7 @@
import type { NxJsonConfiguration } from '@nx/devkit'; import type { NxJsonConfiguration } from '@nx/devkit';
import { import {
cleanupProject, cleanupProject,
createNonNxProjectDirectory,
e2eCwd, e2eCwd,
getPackageManagerCommand, getPackageManagerCommand,
getPublishedVersion, getPublishedVersion,
@ -588,8 +589,6 @@ describe('global installation', () => {
let oldPath: string; let oldPath: string;
beforeAll(() => { beforeAll(() => {
newProject();
ensureDirSync(globalsPath); ensureDirSync(globalsPath);
writeFileSync( writeFileSync(
path.join(path.dirname(path.dirname(globalsPath)), 'package.json'), path.join(path.dirname(path.dirname(globalsPath)), 'package.json'),
@ -618,66 +617,95 @@ describe('global installation', () => {
process.env.PATH = oldPath; process.env.PATH = oldPath;
}); });
it('should invoke Nx commands from local repo', () => { describe('inside nx directory', () => {
const nxJsContents = readFile('node_modules/nx/bin/nx.js'); beforeAll(() => {
updateFile('node_modules/nx/bin/nx.js', `console.log('local install');`); newProject();
let output: string; });
expect(() => {
output = runCommand(`nx show projects`); it('should invoke Nx commands from local repo', () => {
}).not.toThrow(); const nxJsContents = readFile('node_modules/nx/bin/nx.js');
expect(output).toContain('local install'); updateFile('node_modules/nx/bin/nx.js', `console.log('local install');`);
updateFile('node_modules/nx/bin/nx.js', nxJsContents); let output: string;
expect(() => {
output = runCommand(`nx show projects`);
}).not.toThrow();
expect(output).toContain('local install');
updateFile('node_modules/nx/bin/nx.js', nxJsContents);
});
it('should warn if local Nx has higher major version', () => {
const packageJsonContents = readFile('node_modules/nx/package.json');
updateJson('node_modules/nx/package.json', (json) => {
json.version = `${major(getPublishedVersion()) + 2}.0.0`;
return json;
});
let output: string;
expect(() => {
output = runCommand(`nx show projects`);
}).not.toThrow();
expect(output).toContain('Its time to update Nx');
updateFile('node_modules/nx/package.json', packageJsonContents);
});
it('--version should display global installs version', () => {
const packageJsonContents = readFile('node_modules/nx/package.json');
const localVersion = `${major(getPublishedVersion()) + 2}.0.0`;
updateJson('node_modules/nx/package.json', (json) => {
json.version = localVersion;
return json;
});
let output: string;
expect(() => {
output = runCommand(`nx --version`);
}).not.toThrow();
expect(output).toContain(`- Local: v${localVersion}`);
expect(output).toContain(`- Global: v${getPublishedVersion()}`);
updateFile('node_modules/nx/package.json', packageJsonContents);
});
it('report should display global installs version', () => {
const packageJsonContents = readFile('node_modules/nx/package.json');
const localVersion = `${major(getPublishedVersion()) + 2}.0.0`;
updateJson('node_modules/nx/package.json', (json) => {
json.version = localVersion;
return json;
});
let output: string;
expect(() => {
output = runCommand(`nx report`);
}).not.toThrow();
expect(output).toEqual(
expect.stringMatching(new RegExp(`nx.*:.*${localVersion}`))
);
expect(output).toEqual(
expect.stringMatching(
new RegExp(`nx \\(global\\).*:.*${getPublishedVersion()}`)
)
);
updateFile('node_modules/nx/package.json', packageJsonContents);
});
}); });
it('should warn if local Nx has higher major version', () => { describe('non-nx directory', () => {
const packageJsonContents = readFile('node_modules/nx/package.json'); beforeAll(() => {
updateJson('node_modules/nx/package.json', (json) => { createNonNxProjectDirectory();
json.version = `${major(getPublishedVersion()) + 2}.0.0`;
return json;
}); });
let output: string;
expect(() => {
output = runCommand(`nx show projects`);
}).not.toThrow();
expect(output).toContain('Its time to update Nx');
updateFile('node_modules/nx/package.json', packageJsonContents);
});
it('--version should display global installs version', () => { it('--version should report global version and local not found', () => {
const packageJsonContents = readFile('node_modules/nx/package.json'); let output: string;
const localVersion = `${major(getPublishedVersion()) + 2}.0.0`; expect(() => {
updateJson('node_modules/nx/package.json', (json) => { output = runCommand(`nx --version`);
json.version = localVersion; }).not.toThrow();
return json; expect(output).toContain(`- Local: Not found`);
expect(output).toContain(`- Global: v${getPublishedVersion()}`);
}); });
let output: string;
expect(() => {
output = runCommand(`nx --version`);
}).not.toThrow();
expect(output).toContain(`- Local: v${localVersion}`);
expect(output).toContain(`- Global: v${getPublishedVersion()}`);
updateFile('node_modules/nx/package.json', packageJsonContents);
});
it('report should display global installs version', () => { it('graph should work in npm workspaces repo', () => {
const packageJsonContents = readFile('node_modules/nx/package.json'); expect(() => {
const localVersion = `${major(getPublishedVersion()) + 2}.0.0`; runCommand(`nx graph --file graph.json`);
updateJson('node_modules/nx/package.json', (json) => { }).not.toThrow();
json.version = localVersion; const { graph } = readJson('graph.json');
return json; expect(graph).toHaveProperty('nodes');
}); });
let output: string;
expect(() => {
output = runCommand(`nx report`);
}).not.toThrow();
expect(output).toEqual(
expect.stringMatching(new RegExp(`nx.*:.*${localVersion}`))
);
expect(output).toEqual(
expect.stringMatching(
new RegExp(`nx \\(global\\).*:.*${getPublishedVersion()}`)
)
);
updateFile('node_modules/nx/package.json', packageJsonContents);
}); });
}); });

View File

@ -35,47 +35,27 @@ function main() {
if (!(Symbol as any).observable) if (!(Symbol as any).observable)
(Symbol as any).observable = Symbol('observable polyfill'); (Symbol as any).observable = Symbol('observable polyfill');
if (!workspace) {
output.log({
title: `The current directory isn't part of an Nx workspace.`,
bodyLines: [
`To create a workspace run:`,
chalk.bold.white(`npx create-nx-workspace@latest <workspace name>`),
'',
`To add Nx to an existing workspace with a workspace-specific nx.json, run:`,
chalk.bold.white(`npx nx@latest init`),
],
});
output.note({
title: `For more information please visit https://nx.dev/`,
});
process.exit(1);
}
// Make sure that a local copy of Nx exists in workspace // Make sure that a local copy of Nx exists in workspace
let localNx: string; let localNx: string;
try { try {
localNx = resolveNx(workspace); localNx = workspace && resolveNx(workspace);
} catch { } catch {
localNx = null; localNx = null;
} }
const isLocalInstall = localNx === resolveNx(null); const isLocalInstall = localNx === resolveNx(null);
const LOCAL_NX_VERSION: string | null = localNx const { LOCAL_NX_VERSION, GLOBAL_NX_VERSION } = determineNxVersions(
? getLocalNxVersion(workspace) localNx,
: null; workspace,
const GLOBAL_NX_VERSION: string | null = isLocalInstall isLocalInstall
? null );
: require('../package.json').version;
globalThis.GLOBAL_NX_VERSION ??= GLOBAL_NX_VERSION;
if (process.argv[2] === '--version') { if (process.argv[2] === '--version') {
console.log(stripIndents`Nx Version: handleNxVersionCommand(LOCAL_NX_VERSION, GLOBAL_NX_VERSION);
- Local: ${LOCAL_NX_VERSION ? 'v' + LOCAL_NX_VERSION : 'Not found'} }
- Global: ${GLOBAL_NX_VERSION ? 'v' + GLOBAL_NX_VERSION : 'Not found'}`);
process.exit(0); if (!workspace) {
handleNoWorkspace();
} }
if (!localNx) { if (!localNx) {
@ -98,6 +78,50 @@ function main() {
} }
} }
function handleNoWorkspace() {
output.log({
title: `The current directory isn't part of an Nx workspace.`,
bodyLines: [
`To create a workspace run:`,
chalk.bold.white(`npx create-nx-workspace@latest <workspace name>`),
'',
`To add Nx to an existing workspace with a workspace-specific nx.json, run:`,
chalk.bold.white(`npx nx@latest init`),
],
});
output.note({
title: `For more information please visit https://nx.dev/`,
});
process.exit(1);
}
function handleNxVersionCommand(
LOCAL_NX_VERSION: string,
GLOBAL_NX_VERSION: string
) {
console.log(stripIndents`Nx Version:
- Local: ${LOCAL_NX_VERSION ? 'v' + LOCAL_NX_VERSION : 'Not found'}
- Global: ${GLOBAL_NX_VERSION ? 'v' + GLOBAL_NX_VERSION : 'Not found'}`);
process.exit(0);
}
function determineNxVersions(
localNx: string,
workspace: WorkspaceTypeAndRoot,
isLocalInstall: boolean
) {
const LOCAL_NX_VERSION: string | null = localNx
? getLocalNxVersion(workspace)
: null;
const GLOBAL_NX_VERSION: string | null = isLocalInstall
? null
: require('../package.json').version;
globalThis.GLOBAL_NX_VERSION ??= GLOBAL_NX_VERSION;
return { LOCAL_NX_VERSION, GLOBAL_NX_VERSION };
}
function resolveNx(workspace: WorkspaceTypeAndRoot | null) { function resolveNx(workspace: WorkspaceTypeAndRoot | null) {
// prefer Nx installed in .nx/installation // prefer Nx installed in .nx/installation
try { try {
@ -167,17 +191,13 @@ function warnIfUsingOutdatedGlobalInstall(
} }
function getLocalNxVersion(workspace: WorkspaceTypeAndRoot): string | null { function getLocalNxVersion(workspace: WorkspaceTypeAndRoot): string | null {
// TODO(v17): Remove @nrwl/cli from this list try {
const localNxPackages = ['nx', '@nrwl/tao', '@nrwl/cli']; const { packageJson } = readModulePackageJson(
for (const pkg of localNxPackages) { 'nx',
try { getNxRequirePaths(workspace.dir)
const { packageJson } = readModulePackageJson( );
'nx', return packageJson.version;
getNxRequirePaths(workspace.dir) } catch {}
);
return packageJson.version;
} catch {}
}
} }
function _getLatestVersionOfNx(): string { function _getLatestVersionOfNx(): string {

View File

@ -6,7 +6,6 @@ import {
} from '../config/workspace-json-project-json'; } from '../config/workspace-json-project-json';
import { readJsonFile } from './fileutils'; import { readJsonFile } from './fileutils';
import { getNxRequirePaths } from './installation-directory'; import { getNxRequirePaths } from './installation-directory';
import { workspaceRoot } from './workspace-root';
export type PackageJsonTargetConfiguration = Omit< export type PackageJsonTargetConfiguration = Omit<
TargetConfiguration, TargetConfiguration,