fix(core): nx migrate should work in encapsulated Nx repos (#15338)

This commit is contained in:
Craigory Coppola 2023-03-03 15:45:42 -05:00 committed by GitHub
parent 17a0d2c085
commit 4a53ace70d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 296 additions and 85 deletions

View File

@ -8,6 +8,8 @@ import {
cleanupProject, cleanupProject,
getPublishedVersion, getPublishedVersion,
uniq, uniq,
readJson,
readFile,
} from '@nrwl/e2e/utils'; } from '@nrwl/e2e/utils';
import { bold } from 'chalk'; import { bold } from 'chalk';
@ -104,6 +106,161 @@ describe('encapsulated nx', () => {
).not.toThrow(); ).not.toThrow();
expect(() => checkFilesExist()); expect(() => checkFilesExist());
}); });
it('should work with migrate', () => {
updateFile(
`.nx/installation/node_modules/migrate-parent-package/package.json`,
JSON.stringify({
version: '1.0.0',
name: 'migrate-parent-package',
'nx-migrations': './migrations.json',
})
);
updateFile(
`.nx/installation/node_modules/migrate-parent-package/migrations.json`,
JSON.stringify({
schematics: {
run11: {
version: '1.1.0',
description: '1.1.0',
factory: './run11',
},
run20: {
version: '2.0.0',
description: '2.0.0',
implementation: './run20',
},
},
})
);
updateFile(
`.nx/installation/node_modules/migrate-parent-package/run11.js`,
`
exports.default = function default_1() {
return function(host) {
host.create('file-11', 'content11')
}
}
`
);
updateFile(
`.nx/installation/node_modules/migrate-parent-package/run20.js`,
`
exports.default = function (host) {
host.write('file-20', 'content20')
}
`
);
updateFile(
`.nx/installation/node_modules/migrate-child-package/package.json`,
JSON.stringify({
name: 'migrate-child-package',
version: '1.0.0',
})
);
/**
* Patches migration fetcher to load in migrations that we are using to test.
*/
updateFile(
'.nx/installation/node_modules/nx/src/command-line/migrate.js',
(content) => {
const start = content.indexOf('// testing-fetch-start');
const end = content.indexOf('// testing-fetch-end');
const before = content.substring(0, start);
const after = content.substring(end);
const newFetch = `
function createFetcher(logger) {
return function fetch(packageName) {
if (packageName === 'migrate-parent-package') {
return Promise.resolve({
version: '2.0.0',
generators: {
'run11': {
version: '1.1.0'
},
'run20': {
version: '2.0.0',
cli: 'nx'
}
},
packageJsonUpdates: {
'run-11': {version: '1.1.0', packages: {
'migrate-child-package': {version: '9.0.0', alwaysAddToPackageJson: false},
}},
}
});
} else {
return Promise.resolve({version: '9.0.0'});
}
}
}
`;
return `${before}${newFetch}${after}`;
}
);
updateJson('nx.json', (j: NxJsonConfiguration) => {
j.installation = {
version: getPublishedVersion(),
plugins: {
'migrate-child-package': '1.0.0',
},
};
return j;
});
runEncapsulatedNx(
'migrate migrate-parent-package@2.0.0 --from="migrate-parent-package@1.0.0"',
{
env: {
...process.env,
NX_MIGRATE_SKIP_INSTALL: 'true',
NX_MIGRATE_USE_LOCAL: 'true',
NX_WRAPPER_SKIP_INSTALL: 'true',
},
}
);
const nxJson: NxJsonConfiguration = readJson(`nx.json`);
expect(nxJson.installation.plugins['migrate-child-package']).toEqual(
'9.0.0'
);
// creates migrations.json
const migrationsJson = readJson(`migrations.json`);
expect(migrationsJson).toEqual({
migrations: [
{
package: 'migrate-parent-package',
version: '1.1.0',
name: 'run11',
},
{
package: 'migrate-parent-package',
version: '2.0.0',
name: 'run20',
cli: 'nx',
},
],
});
// runs migrations
runEncapsulatedNx('migrate --run-migrations=migrations.json', {
env: {
...process.env,
NX_MIGRATE_SKIP_INSTALL: 'true',
NX_MIGRATE_USE_LOCAL: 'true',
NX_WRAPPER_SKIP_INSTALL: 'true',
},
});
expect(readFile('file-11')).toEqual('content11');
expect(readFile('file-20')).toEqual('content20');
});
}); });
function assertNoRootPackages() { function assertNoRootPackages() {

View File

@ -66,19 +66,20 @@ export function setMaxWorkers() {
export function runCommand( export function runCommand(
command: string, command: string,
options?: Partial<ExecSyncOptions> options?: Partial<ExecSyncOptions> & { failOnError?: boolean }
): string { ): string {
const { failOnError, ...childProcessOptions } = options ?? {};
try { try {
const r = execSync(command, { const r = execSync(command, {
cwd: tmpProjPath(), cwd: tmpProjPath(),
stdio: ['pipe', 'pipe', 'pipe'], stdio: ['pipe', 'pipe', 'pipe'],
env: { env: {
...getStrippedEnvironmentVariables(), ...getStrippedEnvironmentVariables(),
...options?.env, ...childProcessOptions?.env,
FORCE_COLOR: 'false', FORCE_COLOR: 'false',
}, },
encoding: 'utf-8', encoding: 'utf-8',
...options, ...childProcessOptions,
}).toString(); }).toString();
if (process.env.NX_VERBOSE_LOGGING) { if (process.env.NX_VERBOSE_LOGGING) {
console.log(r); console.log(r);
@ -87,7 +88,7 @@ export function runCommand(
} catch (e) { } catch (e) {
// this is intentional // this is intentional
// npm ls fails if package is not found // npm ls fails if package is not found
if (e.stdout || e.stderr) { if (!failOnError && (e.stdout || e.stderr)) {
return e.stdout?.toString() + e.stderr?.toString(); return e.stdout?.toString() + e.stderr?.toString();
} }
throw e; throw e;

View File

@ -17,7 +17,7 @@ import * as isCI from 'is-ci';
import { angularCliVersion } from '@nrwl/workspace/src/utils/versions'; import { angularCliVersion } from '@nrwl/workspace/src/utils/versions';
import { dump } from '@zkochan/js-yaml'; import { dump } from '@zkochan/js-yaml';
import { execSync } from 'child_process'; import { execSync, ExecSyncOptions } from 'child_process';
import { isVerbose } from './get-env-info'; import { isVerbose } from './get-env-info';
import { logError, logInfo } from './log-utils'; import { logError, logInfo } from './log-utils';
@ -372,15 +372,15 @@ export function newLernaWorkspace({
export function newEncapsulatedNxWorkspace({ export function newEncapsulatedNxWorkspace({
name = uniq('encapsulated'), name = uniq('encapsulated'),
pmc = getPackageManagerCommand(), pmc = getPackageManagerCommand(),
} = {}): (command: string) => string { } = {}): (command: string, opts?: Partial<ExecSyncOptions>) => string {
projName = name; projName = name;
ensureDirSync(tmpProjPath()); ensureDirSync(tmpProjPath());
runCommand(`${pmc.runUninstalledPackage} nx@latest init --encapsulated`); runCommand(`${pmc.runUninstalledPackage} nx@latest init --encapsulated`);
return (command: string) => { return (command: string, opts: Partial<ExecSyncOptions>) => {
if (process.platform === 'win32') { if (process.platform === 'win32') {
return runCommand(`./nx.bat ${command}`); return runCommand(`./nx.bat ${command}`, { ...opts, failOnError: true });
} else { } else {
return runCommand(`./nx ${command}`); return runCommand(`./nx ${command}`, { ...opts, failOnError: true });
} }
}; };
} }

View File

@ -1,6 +1,6 @@
import type { Tree } from '@nrwl/devkit'; import type { Tree } from '@nrwl/devkit';
import { getPackageManagerCommand } from '@nrwl/devkit'; import { getPackageManagerCommand } from '@nrwl/devkit';
import { execSync } from 'child_process'; import { runNxSync } from 'nx/src/utils/child-process';
export function formatFilesTask(tree: Tree): void { export function formatFilesTask(tree: Tree): void {
if ( if (
@ -11,8 +11,7 @@ export function formatFilesTask(tree: Tree): void {
return; return;
} }
const pmc = getPackageManagerCommand();
try { try {
execSync(`${pmc.exec} nx format`, { cwd: tree.root, stdio: [0, 1, 2] }); runNxSync(`format`, { cwd: tree.root, stdio: [0, 1, 2] });
} catch {} } catch {}
} }

View File

@ -29,6 +29,7 @@ import {
} from '../generators/utils/project-configuration'; } from '../generators/utils/project-configuration';
import { createProjectGraphAsync } from '../project-graph/project-graph'; import { createProjectGraphAsync } from '../project-graph/project-graph';
import { readJsonFile } from '../utils/fileutils'; import { readJsonFile } from '../utils/fileutils';
import { getNxRequirePaths } from '../utils/installation-directory';
import { parseJson } from '../utils/json'; import { parseJson } from '../utils/json';
import { NX_ERROR, NX_PREFIX } from '../utils/logger'; import { NX_ERROR, NX_PREFIX } from '../utils/logger';
import { readModulePackageJson } from '../utils/package-json'; import { readModulePackageJson } from '../utils/package-json';
@ -643,9 +644,10 @@ function resolveMigrationsCollection(name: string): string {
if (extname(name)) { if (extname(name)) {
collectionPath = require.resolve(name); collectionPath = require.resolve(name);
} else { } else {
const { path: packageJsonPath, packageJson } = readModulePackageJson(name, [ const { path: packageJsonPath, packageJson } = readModulePackageJson(
process.cwd(), name,
]); getNxRequirePaths(process.cwd())
);
let pkgJsonSchematics = let pkgJsonSchematics =
packageJson['nx-migrations'] ?? packageJson['ng-update']; packageJson['nx-migrations'] ?? packageJson['ng-update'];

View File

@ -10,6 +10,7 @@ import {
import { existsSync } from 'fs'; import { existsSync } from 'fs';
import { join } from 'path'; import { join } from 'path';
import { workspaceRoot } from '../utils/workspace-root'; import { workspaceRoot } from '../utils/workspace-root';
import { runNxSync } from '../utils/child-process';
export async function connectToNxCloudIfExplicitlyAsked(opts: { export async function connectToNxCloudIfExplicitlyAsked(opts: {
[k: string]: any; [k: string]: any;
@ -24,13 +25,7 @@ export async function connectToNxCloudIfExplicitlyAsked(opts: {
output.log({ output.log({
title: '--cloud requires the workspace to be connected to Nx Cloud.', title: '--cloud requires the workspace to be connected to Nx Cloud.',
}); });
const pmc = getPackageManagerCommand(); runNxSync(`connect-to-nx-cloud`, {
const nxCommand = existsSync(join(workspaceRoot, 'package.json'))
? `${pmc.exec} nx`
: process.platform === 'win32'
? './nx.bat'
: './nx';
execSync(`${nxCommand} connect-to-nx-cloud`, {
stdio: [0, 1, 2], stdio: [0, 1, 2],
}); });
output.success({ output.success({
@ -60,11 +55,6 @@ export async function connectToNxCloudCommand(
const res = await connectToNxCloudPrompt(promptOverride); const res = await connectToNxCloudPrompt(promptOverride);
if (!res) return false; if (!res) return false;
const pmc = getPackageManagerCommand(); const pmc = getPackageManagerCommand();
const nxCommand = pmc
? `${pmc.exec} nx`
: process.platform === 'win32'
? './nx.bat'
: './nx';
if (pmc) { if (pmc) {
execSync(`${pmc.addDev} @nrwl/nx-cloud@latest`); execSync(`${pmc.addDev} @nrwl/nx-cloud@latest`);
} else { } else {
@ -76,7 +66,7 @@ export async function connectToNxCloudCommand(
).toString(); ).toString();
} }
} }
execSync(`${nxCommand} g @nrwl/nx-cloud:init`, { runNxSync(`g @nrwl/nx-cloud:init`, {
stdio: [0, 1, 2], stdio: [0, 1, 2],
}); });
return true; return true;

View File

@ -53,6 +53,9 @@ import { nxVersion } from '../utils/versions';
import { existsSync } from 'fs'; import { existsSync } from 'fs';
import { workspaceRoot } from '../utils/workspace-root'; import { workspaceRoot } from '../utils/workspace-root';
import { isCI } from '../utils/is-ci'; import { isCI } from '../utils/is-ci';
import { getNxRequirePaths } from '../utils/installation-directory';
import { readNxJson } from '../config/configuration';
import { runNxSync } from '../utils/child-process';
export interface ResolvedMigrationConfiguration extends MigrationsJson { export interface ResolvedMigrationConfiguration extends MigrationsJson {
packageGroup?: ArrayPackageGroup; packageGroup?: ArrayPackageGroup;
@ -100,7 +103,8 @@ function normalizeSlashes(packageName: string): string {
} }
export interface MigratorOptions { export interface MigratorOptions {
packageJson: PackageJson; packageJson?: PackageJson;
nxInstallation?: NxJsonConfiguration['installation'];
getInstalledPackageVersion: ( getInstalledPackageVersion: (
pkg: string, pkg: string,
overrides?: Record<string, string> overrides?: Record<string, string>
@ -116,7 +120,7 @@ export interface MigratorOptions {
} }
export class Migrator { export class Migrator {
private readonly packageJson: MigratorOptions['packageJson']; private readonly packageJson?: MigratorOptions['packageJson'];
private readonly getInstalledPackageVersion: MigratorOptions['getInstalledPackageVersion']; private readonly getInstalledPackageVersion: MigratorOptions['getInstalledPackageVersion'];
private readonly fetch: MigratorOptions['fetch']; private readonly fetch: MigratorOptions['fetch'];
private readonly installedPkgVersionOverrides: MigratorOptions['from']; private readonly installedPkgVersionOverrides: MigratorOptions['from'];
@ -126,9 +130,11 @@ export class Migrator {
private readonly packageUpdates: Record<string, PackageUpdate> = {}; private readonly packageUpdates: Record<string, PackageUpdate> = {};
private readonly collectedVersions: Record<string, string> = {}; private readonly collectedVersions: Record<string, string> = {};
private readonly promptAnswers: Record<string, boolean> = {}; private readonly promptAnswers: Record<string, boolean> = {};
private readonly nxInstallation: NxJsonConfiguration['installation'] | null;
constructor(opts: MigratorOptions) { constructor(opts: MigratorOptions) {
this.packageJson = opts.packageJson; this.packageJson = opts.packageJson;
this.nxInstallation = opts.nxInstallation;
this.getInstalledPackageVersion = opts.getInstalledPackageVersion; this.getInstalledPackageVersion = opts.getInstalledPackageVersion;
this.fetch = opts.fetch; this.fetch = opts.fetch;
this.installedPkgVersionOverrides = opts.from; this.installedPkgVersionOverrides = opts.from;
@ -400,33 +406,34 @@ export class Migrator {
continue; continue;
} }
const { dependencies, devDependencies } = this.packageJson; const dependencies: Record<string, string> = {
packageJsonUpdate.packages = Object.entries(packageJsonUpdate.packages) ...this.packageJson?.dependencies,
.filter( ...this.packageJson?.devDependencies,
([packageName, packageUpdate]) => ...this.nxInstallation?.plugins,
(!packageUpdate.ifPackageInstalled || ...(this.nxInstallation && { nx: this.nxInstallation.version }),
this.getPkgVersion(packageUpdate.ifPackageInstalled)) && };
(packageUpdate.alwaysAddToPackageJson ||
packageUpdate.addToPackageJson || const filtered: Record<string, PackageUpdate> = {};
!!dependencies?.[packageName] || for (const [packageName, packageUpdate] of Object.entries(
!!devDependencies?.[packageName]) && packageJsonUpdate.packages
(!this.collectedVersions[packageName] || )) {
this.gt( if (
packageUpdate.version, this.shouldApplyPackageUpdate(
this.collectedVersions[packageName] packageUpdate,
)) packageName,
dependencies
) )
.reduce((acc, [packageName, packageUpdate]) => { ) {
acc[packageName] = { filtered[packageName] = {
version: packageUpdate.version, version: packageUpdate.version,
addToPackageJson: packageUpdate.alwaysAddToPackageJson addToPackageJson: packageUpdate.alwaysAddToPackageJson
? 'dependencies' ? 'dependencies'
: packageUpdate.addToPackageJson || false, : packageUpdate.addToPackageJson || false,
}; };
return acc; }
}, {} as Record<string, PackageUpdate>); }
if (Object.keys(filtered).length) {
if (Object.keys(packageJsonUpdate.packages).length) { packageJsonUpdate.packages = filtered;
filteredPackageJsonUpdates.push(packageJsonUpdate); filteredPackageJsonUpdates.push(packageJsonUpdate);
} }
} }
@ -434,6 +441,22 @@ export class Migrator {
return filteredPackageJsonUpdates; return filteredPackageJsonUpdates;
} }
private shouldApplyPackageUpdate(
packageUpdate: PackageUpdate,
packageName: string,
dependencies: Record<string, string>
) {
return (
(!packageUpdate.ifPackageInstalled ||
this.getPkgVersion(packageUpdate.ifPackageInstalled)) &&
(packageUpdate.alwaysAddToPackageJson ||
packageUpdate.addToPackageJson ||
!!dependencies?.[packageName]) &&
(!this.collectedVersions[packageName] ||
this.gt(packageUpdate.version, this.collectedVersions[packageName]))
);
}
private addPackageUpdate(name: string, packageUpdate: PackageUpdate): void { private addPackageUpdate(name: string, packageUpdate: PackageUpdate): void {
if ( if (
!this.packageUpdates[name] || !this.packageUpdates[name] ||
@ -732,9 +755,10 @@ function createInstalledPackageVersionsResolver(
} }
if (!cache[packageName]) { if (!cache[packageName]) {
const { packageJson, path } = readModulePackageJson(packageName, [ const { packageJson, path } = readModulePackageJson(
root, packageName,
]); getNxRequirePaths()
);
// old workspaces would have the temp installation of nx in the cache, // old workspaces would have the temp installation of nx in the cache,
// so the resolved package is not the one we need // so the resolved package is not the one we need
if (!path.startsWith(workspaceRoot)) { if (!path.startsWith(workspaceRoot)) {
@ -970,7 +994,7 @@ function readPackageMigrationConfig(
): PackageMigrationConfig { ): PackageMigrationConfig {
const { path: packageJsonPath, packageJson: json } = readModulePackageJson( const { path: packageJsonPath, packageJson: json } = readModulePackageJson(
packageName, packageName,
[dir] getNxRequirePaths(dir)
); );
const config = readNxMigrateConfig(json); const config = readNxMigrateConfig(json);
@ -1043,7 +1067,7 @@ function updatePackageJson(
}); });
} }
function updateInstallationDetails( async function updateInstallationDetails(
root: string, root: string,
updatedPackages: Record<string, PackageUpdate> updatedPackages: Record<string, PackageUpdate>
) { ) {
@ -1064,7 +1088,9 @@ function updateInstallationDetails(
for (const dep in nxJson.installation.plugins) { for (const dep in nxJson.installation.plugins) {
const update = updatedPackages[dep]; const update = updatedPackages[dep];
if (update) { if (update) {
nxJson.installation.plugins[dep] = update.version; nxJson.installation.plugins[dep] = valid(update.version)
? update.version
: await resolvePackageVersionUsingRegistry(dep, update.version);
} }
} }
} }
@ -1101,10 +1127,13 @@ async function generateMigrationsJsonAndUpdatePackageJson(
) { ) {
const pmc = getPackageManagerCommand(); const pmc = getPackageManagerCommand();
try { try {
let originalPackageJson = readJsonFile<PackageJson>( const rootPkgJsonPath = join(root, 'package.json');
join(root, 'package.json') let originalPackageJson = existsSync(rootPkgJsonPath)
); ? readJsonFile<PackageJson>(rootPkgJsonPath)
const from = readNxVersion(originalPackageJson); : null;
const originalNxInstallation = readNxJson().installation;
const from =
originalNxInstallation?.version ?? readNxVersion(originalPackageJson);
try { try {
if ( if (
@ -1135,6 +1164,7 @@ async function generateMigrationsJsonAndUpdatePackageJson(
const migrator = new Migrator({ const migrator = new Migrator({
packageJson: originalPackageJson, packageJson: originalPackageJson,
nxInstallation: originalNxInstallation,
getInstalledPackageVersion: createInstalledPackageVersionsResolver(root), getInstalledPackageVersion: createInstalledPackageVersionsResolver(root),
fetch: createFetcher(), fetch: createFetcher(),
from: opts.from, from: opts.from,
@ -1149,7 +1179,7 @@ async function generateMigrationsJsonAndUpdatePackageJson(
); );
updatePackageJson(root, packageUpdates); updatePackageJson(root, packageUpdates);
updateInstallationDetails(root, packageUpdates); await updateInstallationDetails(root, packageUpdates);
if (migrations.length > 0) { if (migrations.length > 0) {
createMigrationsFile(root, [ createMigrationsFile(root, [
@ -1352,8 +1382,7 @@ async function runMigrations(
if (!__dirname.startsWith(workspaceRoot)) { if (!__dirname.startsWith(workspaceRoot)) {
// we are running from a temp installation with nx latest, switch to running // we are running from a temp installation with nx latest, switch to running
// from local installation // from local installation
const pmc = getPackageManagerCommand(); runNxSync(`migrate ${args.join(' ')}`, {
execSync(`${pmc.exec} nx migrate ${args.join(' ')}`, {
stdio: ['inherit', 'inherit', 'inherit'], stdio: ['inherit', 'inherit', 'inherit'],
env: { env: {
...process.env, ...process.env,
@ -1410,11 +1439,17 @@ async function runMigrations(
} }
function getStringifiedPackageJsonDeps(root: string): string { function getStringifiedPackageJsonDeps(root: string): string {
try {
const { dependencies, devDependencies } = readJsonFile<PackageJson>( const { dependencies, devDependencies } = readJsonFile<PackageJson>(
join(root, 'package.json') join(root, 'package.json')
); );
return JSON.stringify([dependencies, devDependencies]); return JSON.stringify([dependencies, devDependencies]);
} catch {
// We don't really care if the .nx/installation property changes,
// whenever nxw is invoked it will handle the dep updates.
return '';
}
} }
function commitChanges(commitMessage: string): string | null { function commitChanges(commitMessage: string): string | null {

View File

@ -8,6 +8,7 @@ import { workspaceRoot } from '../utils/workspace-root';
import { getPackageManagerCommand } from '../utils/package-manager'; import { getPackageManagerCommand } from '../utils/package-manager';
import { writeJsonFile } from '../utils/fileutils'; import { writeJsonFile } from '../utils/fileutils';
import { WatchArguments } from './watch'; import { WatchArguments } from './watch';
import { runNxSync } from '../utils/child-process';
// Ensure that the output takes up the available width of the terminal. // Ensure that the output takes up the available width of the terminal.
yargs.wrap(yargs.terminalWidth()); yargs.wrap(yargs.terminalWidth());
@ -1090,8 +1091,7 @@ function withListOptions(yargs) {
function runMigration() { function runMigration() {
const runLocalMigrate = () => { const runLocalMigrate = () => {
const pmc = getPackageManagerCommand(); runNxSync(`_migrate ${process.argv.slice(3).join(' ')}`, {
execSync(`${pmc.exec} nx _migrate ${process.argv.slice(3).join(' ')}`, {
stdio: ['inherit', 'inherit', 'inherit'], stdio: ['inherit', 'inherit', 'inherit'],
}); });
}; };

View File

@ -2,6 +2,7 @@ import { getPackageManagerCommand } from '../utils/package-manager';
import { execSync } from 'child_process'; import { execSync } from 'child_process';
import { isNxCloudUsed } from '../utils/nx-cloud-utils'; import { isNxCloudUsed } from '../utils/nx-cloud-utils';
import { output } from '../utils/output'; import { output } from '../utils/output';
import { runNxSync } from '../utils/child-process';
export async function viewLogs(): Promise<number> { export async function viewLogs(): Promise<number> {
const pmc = getPackageManagerCommand(); const pmc = getPackageManagerCommand();
@ -48,10 +49,9 @@ export async function viewLogs(): Promise<number> {
output.log({ output.log({
title: 'Connecting to Nx Cloud', title: 'Connecting to Nx Cloud',
}); });
execSync( runNxSync(`g @nrwl/nx-cloud:init --installation-source=view-logs`, {
`${pmc.exec} nx g @nrwl/nx-cloud:init --installation-source=view-logs`, stdio: 'ignore',
{ stdio: 'ignore' } });
);
} catch (e) { } catch (e) {
output.log({ output.log({
title: 'Failed to connect to Nx Cloud', title: 'Failed to connect to Nx Cloud',

View File

@ -99,8 +99,10 @@ function ensureUpToDateInstallation() {
} }
} }
if (require.main === module && !process.env.NX_WRAPPER_SET) { if (require.main === module || !process.env.NX_WRAPPER_SET) {
process.env.NX_WRAPPER_SET = 'true'; if (!process.env.NX_WRAPPER_SKIP_INSTALL) {
ensureUpToDateInstallation(); ensureUpToDateInstallation();
}
process.env.NX_WRAPPER_SET = 'true';
require('./installation/node_modules/nx/bin/nx'); require('./installation/node_modules/nx/bin/nx');
} }

View File

@ -6,6 +6,7 @@ import {
getPackageManagerCommand, getPackageManagerCommand,
PackageManagerCommands, PackageManagerCommands,
} from '../utils/package-manager'; } from '../utils/package-manager';
import { runNxSync } from '../utils/child-process';
export function askAboutNxCloud() { export function askAboutNxCloud() {
return enquirer return enquirer
@ -121,12 +122,8 @@ export function runInstall(
} }
export function initCloud(repoRoot: string) { export function initCloud(repoRoot: string) {
const pmc = getPackageManagerCommand(); runNxSync(`g @nrwl/nx-cloud:init --installationSource=add-nx-to-monorepo`, {
execSync(
`${pmc.exec} nx g @nrwl/nx-cloud:init --installationSource=add-nx-to-monorepo`,
{
stdio: [0, 1, 2], stdio: [0, 1, 2],
cwd: repoRoot, cwd: repoRoot,
} });
);
} }

View File

@ -0,0 +1,28 @@
import { execSync, ExecSyncOptions } from 'child_process';
import { existsSync } from 'fs';
import { join, relative } from 'path';
import { getPackageManagerCommand } from './package-manager';
import { workspaceRoot, workspaceRootInner } from './workspace-root';
export function runNxSync(
cmd: string,
options?: ExecSyncOptions & { cwd?: string }
) {
let baseCmd: string;
if (existsSync(join(workspaceRoot, 'package.json'))) {
baseCmd = `${getPackageManagerCommand().exec} nx`;
} else {
options ??= {};
options.cwd ??= process.cwd();
const offsetFromRoot = relative(
options.cwd,
workspaceRootInner(options.cwd, null)
);
if (process.platform === 'win32') {
baseCmd = '.\\' + join(`${offsetFromRoot}`, 'nx.bat');
} else {
baseCmd = './' + join(`${offsetFromRoot}`, 'nx');
}
}
execSync(`${baseCmd} ${cmd}`, options);
}