Skip to content

Commit 5fbb74c

Browse files
leosvelperezFrozenPandaz
authored andcommitted
fix(core): resolve published nx migrate package resolution (#35013)
## Current Behavior When `nx migrate latest` runs, it installs the target version of `nx` into a temporary directory and executes that published CLI. During migration, Nx checks whether `nx` is already installed in the workspace by resolving `nx/package.json`. This used to resolve through the workspace-oriented lookup paths, so migrate correctly detected the workspace-installed `nx` package and expanded the first-party Nx package group. That changed recently with `chore(core): build nx to local dist and use nodenext (#34111)`. As part of that work, the published `nx` package gained an `exports` map. In Node, a package with `name: "nx"` and `exports` can self-reference by package name. As a result, when code running inside the temporary published `nx` package resolves `nx/package.json`, Node now resolves that request back to the temporary package itself. The resolved path points outside the workspace root, so migrate's existing safety check treats `nx` as not installed in the workspace. Once that happens, migrate only updates `nx` and never expands the rest of the first-party Nx package group. Separately, provenance package-group lookup assumes a source-layout-relative path to `package.json`, which does not hold for published artifacts built into local `dist/`. ## Expected Behavior Published temporary migrate CLIs should still resolve the workspace-installed `nx` package when migrate determines what is installed in the workspace. That preserves the existing package-group migration behavior even after the recent `exports`-based packaging change. Provenance package-group lookup should resolve the manifest of the currently running `nx` package in a way that works for published artifacts as well as source checkouts. (cherry picked from commit 0a38129)
1 parent 1beaac7 commit 5fbb74c

2 files changed

Lines changed: 33 additions & 13 deletions

File tree

packages/nx/src/command-line/migrate/migrate.ts

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as pc from 'picocolors';
22
import { exec, execSync, type StdioOptions } from 'child_process';
33
import { prompt } from 'enquirer';
44
import { dirname, join } from 'path';
5+
import { createRequire } from 'module';
56
import { joinPathFragments } from '../../utils/path';
67
import {
78
clean,
@@ -897,20 +898,46 @@ function createInstalledPackageVersionsResolver(
897898
root: string
898899
): MigratorOptions['getInstalledPackageVersion'] {
899900
const cache: Record<string, string> = {};
901+
const nxRequires = getNxRequirePaths(root).map((path) =>
902+
createRequire(join(path, 'package.json'))
903+
);
900904

901905
function getInstalledPackageVersion(
902906
packageName: string,
903907
overrides?: Record<string, string>
904908
): string | null {
905-
try {
906-
if (overrides?.[packageName]) {
907-
return overrides[packageName];
909+
if (overrides?.[packageName]) {
910+
return overrides[packageName];
911+
}
912+
913+
if (packageName === 'nx') {
914+
const nxVersion =
915+
cache[packageName] ??
916+
(() => {
917+
for (const req of nxRequires) {
918+
try {
919+
const packageJsonPath = req.resolve('nx/package.json');
920+
if (packageJsonPath.startsWith(workspaceRoot)) {
921+
return readJsonFile<PackageJson>(packageJsonPath).version;
922+
}
923+
} catch {}
924+
}
925+
926+
return getInstalledPackageVersion('@nrwl/workspace', overrides);
927+
})();
928+
929+
if (nxVersion) {
930+
cache[packageName] = nxVersion;
908931
}
909932

933+
return nxVersion;
934+
}
935+
936+
try {
910937
if (!cache[packageName]) {
911938
const { packageJson, path } = readModulePackageJson(
912939
packageName,
913-
getNxRequirePaths()
940+
getNxRequirePaths(root)
914941
);
915942
// old workspaces would have the temp installation of nx in the cache,
916943
// so the resolved package is not the one we need
@@ -922,14 +949,6 @@ function createInstalledPackageVersionsResolver(
922949

923950
return cache[packageName];
924951
} catch {
925-
// Support migrating old workspaces without nx package
926-
if (packageName === 'nx') {
927-
cache[packageName] = getInstalledPackageVersion(
928-
'@nrwl/workspace',
929-
overrides
930-
);
931-
return cache[packageName];
932-
}
933952
return null;
934953
}
935954
}

packages/nx/src/utils/provenance.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { execSync } from 'child_process';
2+
import { createRequire } from 'module';
23
import { join } from 'path';
34
import { promisify } from 'util';
45
import { readJsonFile } from './fileutils';
@@ -168,7 +169,7 @@ export class ProvenanceError extends Error {
168169
}
169170

170171
export function getNxPackageGroup(): string[] {
171-
const packageJsonPath = join(__dirname, '../../package.json');
172+
const packageJsonPath = createRequire(__filename).resolve('nx/package.json');
172173
const packageJson = readJsonFile(packageJsonPath);
173174

174175
if (!packageJson['nx-migrations']?.packageGroup) {

0 commit comments

Comments
 (0)