From 14f471adc60d03c1ab9470c78b123c6226ab6f95 Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Fri, 31 Mar 2023 12:15:46 +0200 Subject: [PATCH 1/7] fix(core): remove and join e2e cnw tests --- e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts | 3 +++ e2e/workspace-create/src/create-nx-workspace.test.ts | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts b/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts index bde47d6f419db..e4f642e05bc2b 100644 --- a/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts +++ b/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts @@ -1,6 +1,7 @@ import { checkFilesExist, cleanupProject, + getSelectedPackageManager, packageInstall, readJson, runCLI, @@ -10,11 +11,13 @@ import { describe('create-nx-workspace --preset=npm', () => { let wsName; + const packageManager = getSelectedPackageManager() || 'pnpm'; beforeEach(() => { wsName = uniq('npm'); runCreateWorkspace(wsName, { preset: 'npm', + packageManager, }); }); diff --git a/e2e/workspace-create/src/create-nx-workspace.test.ts b/e2e/workspace-create/src/create-nx-workspace.test.ts index cd9a09a3763cc..bfa8a0b90edee 100644 --- a/e2e/workspace-create/src/create-nx-workspace.test.ts +++ b/e2e/workspace-create/src/create-nx-workspace.test.ts @@ -319,7 +319,7 @@ describe('create-nx-workspace', () => { it('should return error when ci workflow is selected but no cloud is set up', () => { const wsName = uniq('github'); runCreateWorkspace(wsName, { - preset: 'apps', + preset: 'empty', packageManager, ci: 'circleci', }); @@ -387,7 +387,7 @@ describe('create-nx-workspace custom parent folder', () => { mkdirSync(tmpDir, { recursive: true }); runCreateWorkspace(wsName, { - preset: 'apps', + preset: 'empty', packageManager, cwd: tmpDir, }); From f88399c2140a1e5b8ca1d86e69e298ba1c27ff9e Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Fri, 31 Mar 2023 12:19:00 +0200 Subject: [PATCH 2/7] fix(core): reuse the workspace for cnw-npm tests --- .../src/create-nx-workspace-npm.test.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts b/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts index e4f642e05bc2b..1fdcf0f87538d 100644 --- a/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts +++ b/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts @@ -5,23 +5,27 @@ import { packageInstall, readJson, runCLI, + runCommand, runCreateWorkspace, uniq, } from '@nrwl/e2e/utils'; describe('create-nx-workspace --preset=npm', () => { - let wsName; + const wsName = uniq('npm'); const packageManager = getSelectedPackageManager() || 'pnpm'; - beforeEach(() => { - wsName = uniq('npm'); + beforeAll(() => { runCreateWorkspace(wsName, { preset: 'npm', packageManager, }); }); - afterEach(() => cleanupProject()); + beforeEach(() => { + runCommand(`git reset --hard`); + }); + + afterAll(() => cleanupProject()); it('should add angular application', () => { packageInstall('@nrwl/angular', wsName); From ef639c87d9ad225f4b09e838d34e704f7af8c6cb Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Fri, 31 Mar 2023 12:23:50 +0200 Subject: [PATCH 3/7] fix(core): replace empty preset with apps --- e2e/utils/command-utils.ts | 8 +++++--- e2e/workspace-create/src/create-nx-workspace.test.ts | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/e2e/utils/command-utils.ts b/e2e/utils/command-utils.ts index e38bde3e83680..2c59edda9fe0b 100644 --- a/e2e/utils/command-utils.ts +++ b/e2e/utils/command-utils.ts @@ -13,8 +13,9 @@ import { ChildProcess, exec, execSync, ExecSyncOptions } from 'child_process'; import { join } from 'path'; import * as isCI from 'is-ci'; import { Workspaces } from '../../packages/nx/src/config/workspaces'; -import { updateFile } from './file-utils'; +import { exists, updateFile } from './file-utils'; import { logError, stripConsoleColors } from './log-utils'; +import { existsSync } from 'fs-extra'; export interface RunCmdOpts { silenceError?: boolean; @@ -118,6 +119,7 @@ export function getPackageManagerCommand({ } { const npmMajorVersion = getNpmMajorVersion(); const publishedVersion = getPublishedVersion(); + const isPnpmWorkspace = existsSync(join(path, 'pnpm-workspace.yaml')); return { npm: { @@ -158,8 +160,8 @@ export function getPackageManagerCommand({ runUninstalledPackage: 'pnpm dlx', install: 'pnpm i', ciInstall: 'pnpm install --frozen-lockfile', - addProd: `pnpm add`, - addDev: `pnpm add -D`, + addProd: isPnpmWorkspace ? 'pnpm add -w' : 'pnpm add', + addDev: isPnpmWorkspace ? 'pnpm add -Dw' : 'pnpm add -D', list: 'npm ls --depth 10', runLerna: `pnpm exec lerna`, }, diff --git a/e2e/workspace-create/src/create-nx-workspace.test.ts b/e2e/workspace-create/src/create-nx-workspace.test.ts index bfa8a0b90edee..cd9a09a3763cc 100644 --- a/e2e/workspace-create/src/create-nx-workspace.test.ts +++ b/e2e/workspace-create/src/create-nx-workspace.test.ts @@ -319,7 +319,7 @@ describe('create-nx-workspace', () => { it('should return error when ci workflow is selected but no cloud is set up', () => { const wsName = uniq('github'); runCreateWorkspace(wsName, { - preset: 'empty', + preset: 'apps', packageManager, ci: 'circleci', }); @@ -387,7 +387,7 @@ describe('create-nx-workspace custom parent folder', () => { mkdirSync(tmpDir, { recursive: true }); runCreateWorkspace(wsName, { - preset: 'empty', + preset: 'apps', packageManager, cwd: tmpDir, }); From dbcc2c6136634c3d2b604d00381c21264742f67b Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Mon, 3 Apr 2023 11:00:36 +0200 Subject: [PATCH 4/7] chore(core): check for failures --- e2e/workspace-create-npm/jest.config.ts | 4 +- .../src/create-nx-workspace-npm.test.ts | 39 ++++++++----------- packages/devkit/src/utils/package-json.ts | 3 +- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/e2e/workspace-create-npm/jest.config.ts b/e2e/workspace-create-npm/jest.config.ts index 893e2c7c9ff5f..577af9c54737b 100644 --- a/e2e/workspace-create-npm/jest.config.ts +++ b/e2e/workspace-create-npm/jest.config.ts @@ -1,11 +1,11 @@ /* eslint-disable */ export default { transform: { - '^.+\\.[tj]sx?$': 'ts-jest', + '^.+\\.[tj]sx?$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], }, moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'], maxWorkers: 1, - globals: { 'ts-jest': { tsconfig: '/tsconfig.spec.json' } }, + globals: {}, displayName: 'e2e-workspace-create-npm', preset: '../../jest.preset.js', }; diff --git a/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts b/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts index 1fdcf0f87538d..2bda0d9fecd00 100644 --- a/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts +++ b/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts @@ -1,6 +1,8 @@ import { checkFilesExist, cleanupProject, + e2eCwd, + getPackageManagerCommand, getSelectedPackageManager, packageInstall, readJson, @@ -9,23 +11,33 @@ import { runCreateWorkspace, uniq, } from '@nrwl/e2e/utils'; +import { execSync } from 'child_process'; describe('create-nx-workspace --preset=npm', () => { const wsName = uniq('npm'); - const packageManager = getSelectedPackageManager() || 'pnpm'; + let originalVerbose; beforeAll(() => { + originalVerbose = process.env.NX_VERBOSE_LOGGING; + process.env.NX_VERBOSE_LOGGING = 'true'; runCreateWorkspace(wsName, { preset: 'npm', - packageManager, + packageManager: getSelectedPackageManager(), }); }); - beforeEach(() => { - runCommand(`git reset --hard`); + afterEach(() => { + runCommand(`git reset --hard HEAD`); + execSync(`${getPackageManagerCommand().runNx} reset`, { + cwd: `${e2eCwd}/${wsName}`, + stdio: 'pipe', + }); }); - afterAll(() => cleanupProject()); + afterAll(() => { + process.env.NX_VERBOSE_LOGGING = originalVerbose; + cleanupProject({ skipReset: true }); + }); it('should add angular application', () => { packageInstall('@nrwl/angular', wsName); @@ -55,23 +67,6 @@ describe('create-nx-workspace --preset=npm', () => { }); }, 1_000_000); - it('should add workspace library', () => { - packageInstall('@nrwl/workspace', wsName); - - const libName = uniq('lib'); - - expect(() => - runCLI( - `generate @nrwl/workspace:library ${libName} --skipPackageJson --no-interactive` - ) - ).not.toThrowError(); - checkFilesExist('tsconfig.base.json'); - const tsconfig = readJson(`tsconfig.base.json`); - expect(tsconfig.compilerOptions.paths).toEqual({ - [libName]: [`packages/${libName}/src/index.ts`], - }); - }); - it('should add js library', () => { packageInstall('@nrwl/js', wsName); diff --git a/packages/devkit/src/utils/package-json.ts b/packages/devkit/src/utils/package-json.ts index d78cba3e7b7a3..a5fbceba8fda9 100644 --- a/packages/devkit/src/utils/package-json.ts +++ b/packages/devkit/src/utils/package-json.ts @@ -448,9 +448,10 @@ export function ensurePackage( const tempDir = dirSync().name; console.log(`Fetching ${pkg}...`); + const isVerbose = process.env.NX_VERBOSE_LOGGING === 'true'; execSync(`${getPackageManagerCommand().addDev} ${pkg}@${requiredVersion}`, { cwd: tempDir, - stdio: 'ignore', + stdio: isVerbose ? 'inherit' : 'ignore', }); addToNodePath(join(workspaceRoot, 'node_modules')); From 37582994616f87270ef1dd8fb8b29f64578c3504 Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Mon, 3 Apr 2023 14:47:41 +0200 Subject: [PATCH 5/7] fix(core): make ensurePackage work with pnpm workspaces --- docs/generated/devkit/nrwl_devkit.md | 9 ++++---- .../packages/devkit/documents/nrwl_devkit.md | 9 ++++---- e2e/storybook/src/storybook-nested.test.ts | 1 + .../src/create-nx-workspace.test.ts | 2 ++ packages/devkit/src/utils/package-json.ts | 22 ++++++++++++++----- packages/nx/src/utils/package-manager.ts | 6 +++-- 6 files changed, 33 insertions(+), 16 deletions(-) diff --git a/docs/generated/devkit/nrwl_devkit.md b/docs/generated/devkit/nrwl_devkit.md index a253317955679..71c85e0c724a1 100644 --- a/docs/generated/devkit/nrwl_devkit.md +++ b/docs/generated/devkit/nrwl_devkit.md @@ -1433,7 +1433,7 @@ Returns the list of outputs that will be cached. ### getPackageManagerCommand -▸ **getPackageManagerCommand**(`packageManager?`): `PackageManagerCommands` +▸ **getPackageManagerCommand**(`packageManager?`, `root?`): `PackageManagerCommands` Returns commands for the package manager used in the workspace. By default, the package manager is derived based on the lock file, @@ -1447,9 +1447,10 @@ execSync(`${getPackageManagerCommand().addDev} my-dev-package`); #### Parameters -| Name | Type | -| :--------------- | :-------------------------------------------------------------------- | -| `packageManager` | [`PackageManager`](../../devkit/documents/nrwl_devkit#packagemanager) | +| Name | Type | Default value | +| :--------------- | :-------------------------------------------------------------------- | :-------------- | +| `packageManager` | [`PackageManager`](../../devkit/documents/nrwl_devkit#packagemanager) | `undefined` | +| `root` | `string` | `workspaceRoot` | #### Returns diff --git a/docs/generated/packages/devkit/documents/nrwl_devkit.md b/docs/generated/packages/devkit/documents/nrwl_devkit.md index a253317955679..71c85e0c724a1 100644 --- a/docs/generated/packages/devkit/documents/nrwl_devkit.md +++ b/docs/generated/packages/devkit/documents/nrwl_devkit.md @@ -1433,7 +1433,7 @@ Returns the list of outputs that will be cached. ### getPackageManagerCommand -▸ **getPackageManagerCommand**(`packageManager?`): `PackageManagerCommands` +▸ **getPackageManagerCommand**(`packageManager?`, `root?`): `PackageManagerCommands` Returns commands for the package manager used in the workspace. By default, the package manager is derived based on the lock file, @@ -1447,9 +1447,10 @@ execSync(`${getPackageManagerCommand().addDev} my-dev-package`); #### Parameters -| Name | Type | -| :--------------- | :-------------------------------------------------------------------- | -| `packageManager` | [`PackageManager`](../../devkit/documents/nrwl_devkit#packagemanager) | +| Name | Type | Default value | +| :--------------- | :-------------------------------------------------------------------- | :-------------- | +| `packageManager` | [`PackageManager`](../../devkit/documents/nrwl_devkit#packagemanager) | `undefined` | +| `root` | `string` | `workspaceRoot` | #### Returns diff --git a/e2e/storybook/src/storybook-nested.test.ts b/e2e/storybook/src/storybook-nested.test.ts index 51e93312212fd..812b5f1ac81ab 100644 --- a/e2e/storybook/src/storybook-nested.test.ts +++ b/e2e/storybook/src/storybook-nested.test.ts @@ -17,6 +17,7 @@ describe('Storybook generators and executors for standalone workspaces - using R beforeAll(() => { // create a workspace with a single react app at the root + // TODO @meeroslav: we always need to pass in `packageManager` here, otherwise `runCreateWorkspace` will use `npm` by default runCreateWorkspace(wsName, { preset: 'react-standalone', appName, diff --git a/e2e/workspace-create/src/create-nx-workspace.test.ts b/e2e/workspace-create/src/create-nx-workspace.test.ts index cd9a09a3763cc..398654a0f870b 100644 --- a/e2e/workspace-create/src/create-nx-workspace.test.ts +++ b/e2e/workspace-create/src/create-nx-workspace.test.ts @@ -247,6 +247,7 @@ describe('create-nx-workspace', () => { it('should be able to create react-native workspace', () => { const wsName = uniq('react-native'); const appName = uniq('app'); + // TODO @meeroslav: let's run those only on macos or only if the `packageManager` is `npm` runCreateWorkspace(wsName, { preset: 'react-native', appName, @@ -260,6 +261,7 @@ describe('create-nx-workspace', () => { it('should be able to create an expo workspace', () => { const wsName = uniq('expo'); const appName = uniq('app'); + // TODO @meeroslav: let's run those only on macos or only if the `packageManager` is `npm` runCreateWorkspace(wsName, { preset: 'expo', appName, diff --git a/packages/devkit/src/utils/package-json.ts b/packages/devkit/src/utils/package-json.ts index a5fbceba8fda9..8a427e627975c 100644 --- a/packages/devkit/src/utils/package-json.ts +++ b/packages/devkit/src/utils/package-json.ts @@ -11,8 +11,13 @@ import { requireNx } from '../../nx'; import { dirSync } from 'tmp'; import { join } from 'path'; -const { readJson, updateJson, getPackageManagerCommand, workspaceRoot } = - requireNx(); +const { + readJson, + updateJson, + getPackageManagerCommand, + workspaceRoot, + detectPackageManager, +} = requireNx(); const UNIDENTIFIED_VERSION = 'UNIDENTIFIED_VERSION'; const NON_SEMVER_TAGS = { @@ -449,10 +454,15 @@ export function ensurePackage( console.log(`Fetching ${pkg}...`); const isVerbose = process.env.NX_VERBOSE_LOGGING === 'true'; - execSync(`${getPackageManagerCommand().addDev} ${pkg}@${requiredVersion}`, { - cwd: tempDir, - stdio: isVerbose ? 'inherit' : 'ignore', - }); + execSync( + `${ + getPackageManagerCommand(detectPackageManager(), tempDir).addDev + } ${pkg}@${requiredVersion}`, + { + cwd: tempDir, + stdio: isVerbose ? 'inherit' : 'ignore', + } + ); addToNodePath(join(workspaceRoot, 'node_modules')); addToNodePath(join(tempDir, 'node_modules')); diff --git a/packages/nx/src/utils/package-manager.ts b/packages/nx/src/utils/package-manager.ts index c41165b979aee..6156b422de490 100644 --- a/packages/nx/src/utils/package-manager.ts +++ b/packages/nx/src/utils/package-manager.ts @@ -7,6 +7,7 @@ import { promisify } from 'util'; import { writeJsonFile } from './fileutils'; import { readModulePackageJson } from './package-json'; import { gte, lt } from 'semver'; +import { workspaceRoot } from './workspace-root'; const execAsync = promisify(exec); @@ -46,7 +47,8 @@ export function detectPackageManager(dir: string = ''): PackageManager { * ``` */ export function getPackageManagerCommand( - packageManager: PackageManager = detectPackageManager() + packageManager: PackageManager = detectPackageManager(), + root: string = workspaceRoot ): PackageManagerCommands { const commands: { [pm in PackageManager]: () => PackageManagerCommands } = { yarn: () => { @@ -70,7 +72,7 @@ export function getPackageManagerCommand( const pnpmVersion = getPackageManagerVersion('pnpm'); const useExec = gte(pnpmVersion, '6.13.0'); const includeDoubleDashBeforeArgs = lt(pnpmVersion, '7.0.0'); - const isPnpmWorkspace = existsSync('pnpm-workspace.yaml'); + const isPnpmWorkspace = existsSync(join(root, 'pnpm-workspace.yaml')); return { install: 'pnpm install --no-frozen-lockfile', // explicitly disable in case of CI From 7fc2e8a824c3c4d38662b1369a9a49cf70b1eda2 Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Mon, 3 Apr 2023 15:02:02 +0200 Subject: [PATCH 6/7] chore(repo): revert changes to cnw tests --- e2e/utils/create-project-utils.ts | 19 +++-- .../src/create-nx-workspace.test.ts | 71 +++++++++++++++---- 2 files changed, 70 insertions(+), 20 deletions(-) diff --git a/e2e/utils/create-project-utils.ts b/e2e/utils/create-project-utils.ts index c4f8e79a6ff00..f89dabaf6aa45 100644 --- a/e2e/utils/create-project-utils.ts +++ b/e2e/utils/create-project-utils.ts @@ -47,7 +47,7 @@ export function newProject({ if (!directoryExists(tmpBackupProjPath())) { runCreateWorkspace(projScope, { - preset: 'apps', + preset: 'empty', packageManager, }); @@ -287,12 +287,17 @@ export function packageInstall( } ${pkgsWithVersions}${isVerbose() ? ' --verbose' : ''}`; try { - const install = execSync(command, { - cwd, - stdio: 'pipe', - env: process.env, - encoding: 'utf-8', - }); + const install = execSync( + `${mode === 'dev' ? pm.addDev : pm.addProd} ${pkgsWithVersions}${ + isVerbose() ? ' --verbose' : '' + }`, + { + cwd, + stdio: 'pipe', + env: process.env, + encoding: 'utf-8', + } + ); if (isVerbose()) { output.log({ diff --git a/e2e/workspace-create/src/create-nx-workspace.test.ts b/e2e/workspace-create/src/create-nx-workspace.test.ts index 398654a0f870b..76fe6a4b90eca 100644 --- a/e2e/workspace-create/src/create-nx-workspace.test.ts +++ b/e2e/workspace-create/src/create-nx-workspace.test.ts @@ -19,7 +19,7 @@ describe('create-nx-workspace', () => { afterEach(() => cleanupProject()); - it('should create a workspace with a single angular app at the root without routing', () => { + it('should create a workspace with a single angular app at the root with routing', () => { const wsName = uniq('angular'); runCreateWorkspace(wsName, { @@ -28,6 +28,24 @@ describe('create-nx-workspace', () => { style: 'css', packageManager, standaloneApi: false, + routing: true, + }); + + checkFilesExist('package.json'); + checkFilesExist('src/app/app.routes.ts'); + checkFilesDoNotExist('tsconfig.base.json'); + checkFilesExist('project.json'); + expectCodeIsFormatted(); + }); + + it('should create a workspace with a single angular app at the root without routing', () => { + const wsName = uniq('angular'); + + runCreateWorkspace(wsName, { + preset: 'angular-standalone', + appName: wsName, + style: 'css', + packageManager, routing: false, }); @@ -52,7 +70,6 @@ describe('create-nx-workspace', () => { checkFilesExist('package.json'); checkFilesExist('project.json'); - checkFilesExist('src/app/app.routes.ts'); checkFilesDoNotExist('src/app/app.module.ts'); expectCodeIsFormatted(); }); @@ -96,7 +113,7 @@ describe('create-nx-workspace', () => { it('should be able to create an empty workspace built for apps', () => { const wsName = uniq('apps'); runCreateWorkspace(wsName, { - preset: 'apps', + preset: 'empty', packageManager, }); @@ -106,6 +123,9 @@ describe('create-nx-workspace', () => { 'apps/.gitkeep', 'libs/.gitkeep' ); + const foreignLockFiles = Object.keys(packageManagerLockFile) + .filter((pm) => pm !== packageManager) + .map((pm) => packageManagerLockFile[pm]); expectNoAngularDevkit(); }); @@ -159,7 +179,7 @@ describe('create-nx-workspace', () => { appName, packageManager, standaloneApi: false, - routing: false, + routing: true, }) ).toThrow(); }); @@ -247,7 +267,6 @@ describe('create-nx-workspace', () => { it('should be able to create react-native workspace', () => { const wsName = uniq('react-native'); const appName = uniq('app'); - // TODO @meeroslav: let's run those only on macos or only if the `packageManager` is `npm` runCreateWorkspace(wsName, { preset: 'react-native', appName, @@ -261,7 +280,6 @@ describe('create-nx-workspace', () => { it('should be able to create an expo workspace', () => { const wsName = uniq('expo'); const appName = uniq('app'); - // TODO @meeroslav: let's run those only on macos or only if the `packageManager` is `npm` runCreateWorkspace(wsName, { preset: 'expo', appName, @@ -275,7 +293,7 @@ describe('create-nx-workspace', () => { it('should be able to create a workspace with a custom base branch and HEAD', () => { const wsName = uniq('branch'); runCreateWorkspace(wsName, { - preset: 'apps', + preset: 'empty', base: 'main', packageManager, }); @@ -284,7 +302,7 @@ describe('create-nx-workspace', () => { it('should be able to create a workspace with custom commit information', () => { const wsName = uniq('branch'); runCreateWorkspace(wsName, { - preset: 'apps', + preset: 'empty', extraArgs: '--commit.name="John Doe" --commit.email="myemail@test.com" --commit.message="Custom commit message!"', packageManager, @@ -304,24 +322,51 @@ describe('create-nx-workspace', () => { it('should respect package manager preference', () => { const wsName = uniq('pm'); + const appName = uniq('app'); process.env.YARN_REGISTRY = `http://localhost:4872`; process.env.SELECTED_PM = 'npm'; runCreateWorkspace(wsName, { - preset: 'apps', + preset: 'react-monorepo', + style: 'css', + appName, packageManager: 'npm', + bundler: 'webpack', }); checkFilesDoNotExist('yarn.lock'); checkFilesExist('package-lock.json'); + expectCodeIsFormatted(); + process.env.SELECTED_PM = packageManager; + }); + + it('should store package manager preference for angular', () => { + const wsName = uniq('pm'); + const appName = uniq('app'); + + process.env.YARN_REGISTRY = `http://localhost:4872`; + process.env.SELECTED_PM = 'npm'; + + runCreateWorkspace(wsName, { + preset: 'angular-monorepo', + appName, + style: 'css', + packageManager: 'npm', + routing: true, + standaloneApi: false, + }); + + checkFilesDoNotExist('yarn.lock'); + checkFilesExist('package-lock.json'); + expectCodeIsFormatted(); process.env.SELECTED_PM = packageManager; }); it('should return error when ci workflow is selected but no cloud is set up', () => { const wsName = uniq('github'); - runCreateWorkspace(wsName, { - preset: 'apps', + const create = runCreateWorkspace(wsName, { + preset: 'npm', packageManager, ci: 'circleci', }); @@ -333,7 +378,7 @@ describe('create-nx-workspace', () => { function setupProject(envPm: 'npm' | 'yarn' | 'pnpm') { process.env.SELECTED_PM = envPm; runCreateWorkspace(uniq('pm'), { - preset: 'apps', + preset: 'empty', packageManager: envPm, useDetectedPm: true, }); @@ -380,7 +425,7 @@ describe('create-nx-workspace', () => { describe('create-nx-workspace custom parent folder', () => { const tmpDir = `${e2eCwd}/${uniq('with space')}`; - const wsName = uniq('parent'); + const wsName = uniq('empty'); const packageManager = getSelectedPackageManager() || 'pnpm'; afterEach(() => cleanupProject({ cwd: `${tmpDir}/${wsName}` })); From ff14335e95733d70a0ddda768b036cb8cc2d4706 Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Mon, 3 Apr 2023 17:53:02 +0200 Subject: [PATCH 7/7] feat(core): include PR review notes --- docs/generated/devkit/nrwl_devkit.md | 9 +-- .../packages/devkit/documents/nrwl_devkit.md | 9 +-- e2e/storybook/src/storybook-nested.test.ts | 1 - .../src/create-nx-workspace-npm.test.ts | 80 ++++++------------- .../src/create-nx-workspace.test.ts | 69 +++------------- packages/devkit/src/utils/package-json.ts | 19 ++--- packages/nx/src/utils/package-manager.ts | 6 +- 7 files changed, 56 insertions(+), 137 deletions(-) diff --git a/docs/generated/devkit/nrwl_devkit.md b/docs/generated/devkit/nrwl_devkit.md index 71c85e0c724a1..a253317955679 100644 --- a/docs/generated/devkit/nrwl_devkit.md +++ b/docs/generated/devkit/nrwl_devkit.md @@ -1433,7 +1433,7 @@ Returns the list of outputs that will be cached. ### getPackageManagerCommand -▸ **getPackageManagerCommand**(`packageManager?`, `root?`): `PackageManagerCommands` +▸ **getPackageManagerCommand**(`packageManager?`): `PackageManagerCommands` Returns commands for the package manager used in the workspace. By default, the package manager is derived based on the lock file, @@ -1447,10 +1447,9 @@ execSync(`${getPackageManagerCommand().addDev} my-dev-package`); #### Parameters -| Name | Type | Default value | -| :--------------- | :-------------------------------------------------------------------- | :-------------- | -| `packageManager` | [`PackageManager`](../../devkit/documents/nrwl_devkit#packagemanager) | `undefined` | -| `root` | `string` | `workspaceRoot` | +| Name | Type | +| :--------------- | :-------------------------------------------------------------------- | +| `packageManager` | [`PackageManager`](../../devkit/documents/nrwl_devkit#packagemanager) | #### Returns diff --git a/docs/generated/packages/devkit/documents/nrwl_devkit.md b/docs/generated/packages/devkit/documents/nrwl_devkit.md index 71c85e0c724a1..a253317955679 100644 --- a/docs/generated/packages/devkit/documents/nrwl_devkit.md +++ b/docs/generated/packages/devkit/documents/nrwl_devkit.md @@ -1433,7 +1433,7 @@ Returns the list of outputs that will be cached. ### getPackageManagerCommand -▸ **getPackageManagerCommand**(`packageManager?`, `root?`): `PackageManagerCommands` +▸ **getPackageManagerCommand**(`packageManager?`): `PackageManagerCommands` Returns commands for the package manager used in the workspace. By default, the package manager is derived based on the lock file, @@ -1447,10 +1447,9 @@ execSync(`${getPackageManagerCommand().addDev} my-dev-package`); #### Parameters -| Name | Type | Default value | -| :--------------- | :-------------------------------------------------------------------- | :-------------- | -| `packageManager` | [`PackageManager`](../../devkit/documents/nrwl_devkit#packagemanager) | `undefined` | -| `root` | `string` | `workspaceRoot` | +| Name | Type | +| :--------------- | :-------------------------------------------------------------------- | +| `packageManager` | [`PackageManager`](../../devkit/documents/nrwl_devkit#packagemanager) | #### Returns diff --git a/e2e/storybook/src/storybook-nested.test.ts b/e2e/storybook/src/storybook-nested.test.ts index 812b5f1ac81ab..51e93312212fd 100644 --- a/e2e/storybook/src/storybook-nested.test.ts +++ b/e2e/storybook/src/storybook-nested.test.ts @@ -17,7 +17,6 @@ describe('Storybook generators and executors for standalone workspaces - using R beforeAll(() => { // create a workspace with a single react app at the root - // TODO @meeroslav: we always need to pass in `packageManager` here, otherwise `runCreateWorkspace` will use `npm` by default runCreateWorkspace(wsName, { preset: 'react-standalone', appName, diff --git a/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts b/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts index 2bda0d9fecd00..850e2d7c6023a 100644 --- a/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts +++ b/e2e/workspace-create-npm/src/create-nx-workspace-npm.test.ts @@ -1,8 +1,6 @@ import { checkFilesExist, cleanupProject, - e2eCwd, - getPackageManagerCommand, getSelectedPackageManager, packageInstall, readJson, @@ -11,15 +9,18 @@ import { runCreateWorkspace, uniq, } from '@nrwl/e2e/utils'; -import { execSync } from 'child_process'; describe('create-nx-workspace --preset=npm', () => { const wsName = uniq('npm'); - let originalVerbose; + let orginalGlobCache; + beforeAll(() => { - originalVerbose = process.env.NX_VERBOSE_LOGGING; - process.env.NX_VERBOSE_LOGGING = 'true'; + orginalGlobCache = process.env.NX_PROJECT_GLOB_CACHE; + // glob cache is causing previous projects to show in Workspace for maxWorkers overrides + // which fails due to files no longer being available + process.env.NX_PROJECT_GLOB_CACHE = 'false'; + runCreateWorkspace(wsName, { preset: 'npm', packageManager: getSelectedPackageManager(), @@ -27,15 +28,12 @@ describe('create-nx-workspace --preset=npm', () => { }); afterEach(() => { - runCommand(`git reset --hard HEAD`); - execSync(`${getPackageManagerCommand().runNx} reset`, { - cwd: `${e2eCwd}/${wsName}`, - stdio: 'pipe', - }); + // cleanup previous projects + runCommand(`rm -rf packages/** tsconfig.base.json`); }); afterAll(() => { - process.env.NX_VERBOSE_LOGGING = originalVerbose; + process.env.NX_PROJECT_GLOB_CACHE = orginalGlobCache; cleanupProject({ skipReset: true }); }); @@ -44,9 +42,7 @@ describe('create-nx-workspace --preset=npm', () => { const appName = uniq('my-app'); expect(() => { - runCLI( - `generate @nrwl/angular:app ${appName} --skipPackageJson --no-interactive` - ); + runCLI(`generate @nrwl/angular:app ${appName} --no-interactive`); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); }, 1_000_000); @@ -56,9 +52,7 @@ describe('create-nx-workspace --preset=npm', () => { const libName = uniq('lib'); expect(() => { - runCLI( - `generate @nrwl/angular:lib ${libName} --skipPackageJson --no-interactive` - ); + runCLI(`generate @nrwl/angular:lib ${libName} --no-interactive`); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); const tsconfig = readJson(`tsconfig.base.json`); @@ -73,9 +67,7 @@ describe('create-nx-workspace --preset=npm', () => { const libName = uniq('lib'); expect(() => - runCLI( - `generate @nrwl/js:library ${libName} --skipPackageJson --no-interactive` - ) + runCLI(`generate @nrwl/js:library ${libName} --no-interactive`) ).not.toThrowError(); checkFilesExist('tsconfig.base.json'); const tsconfig = readJson(`tsconfig.base.json`); @@ -90,9 +82,7 @@ describe('create-nx-workspace --preset=npm', () => { const appName = uniq('my-app'); expect(() => - runCLI( - `generate @nrwl/web:app ${appName} --skipPackageJson --no-interactive` - ) + runCLI(`generate @nrwl/web:app ${appName} --no-interactive`) ).not.toThrowError(); checkFilesExist('tsconfig.base.json'); }); @@ -103,9 +93,7 @@ describe('create-nx-workspace --preset=npm', () => { const appName = uniq('my-app'); expect(() => { - runCLI( - `generate @nrwl/react:app ${appName} --skipPackageJson --no-interactive` - ); + runCLI(`generate @nrwl/react:app ${appName} --no-interactive`); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); }); @@ -116,9 +104,7 @@ describe('create-nx-workspace --preset=npm', () => { const libName = uniq('lib'); expect(() => { - runCLI( - `generate @nrwl/react:lib ${libName} --skipPackageJson --no-interactive` - ); + runCLI(`generate @nrwl/react:lib ${libName} --no-interactive`); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); const tsconfig = readJson(`tsconfig.base.json`); @@ -133,9 +119,7 @@ describe('create-nx-workspace --preset=npm', () => { const appName = uniq('my-app'); expect(() => { - runCLI( - `generate @nrwl/next:app ${appName} --skipPackageJson --no-interactive` - ); + runCLI(`generate @nrwl/next:app ${appName} --no-interactive`); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); }); @@ -146,9 +130,7 @@ describe('create-nx-workspace --preset=npm', () => { const libName = uniq('lib'); expect(() => { - runCLI( - `generate @nrwl/next:lib ${libName} --skipPackageJson --no-interactive` - ); + runCLI(`generate @nrwl/next:lib ${libName} --no-interactive`); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); const tsconfig = readJson(`tsconfig.base.json`); @@ -164,7 +146,7 @@ describe('create-nx-workspace --preset=npm', () => { expect(() => { runCLI( - `generate @nrwl/react-native:app ${appName} --install=false --skipPackageJson --no-interactive` + `generate @nrwl/react-native:app ${appName} --install=false --no-interactive` ); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); @@ -176,9 +158,7 @@ describe('create-nx-workspace --preset=npm', () => { const libName = uniq('lib'); expect(() => { - runCLI( - `generate @nrwl/react-native:lib ${libName} --skipPackageJson --no-interactive` - ); + runCLI(`generate @nrwl/react-native:lib ${libName} --no-interactive`); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); const tsconfig = readJson(`tsconfig.base.json`); @@ -193,9 +173,7 @@ describe('create-nx-workspace --preset=npm', () => { const appName = uniq('my-app'); expect(() => { - runCLI( - `generate @nrwl/node:app ${appName} --skipPackageJson --no-interactive` - ); + runCLI(`generate @nrwl/node:app ${appName} --no-interactive`); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); }); @@ -206,9 +184,7 @@ describe('create-nx-workspace --preset=npm', () => { const libName = uniq('lib'); expect(() => { - runCLI( - `generate @nrwl/node:lib ${libName} --skipPackageJson --no-interactive` - ); + runCLI(`generate @nrwl/node:lib ${libName} --no-interactive`); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); const tsconfig = readJson(`tsconfig.base.json`); @@ -223,9 +199,7 @@ describe('create-nx-workspace --preset=npm', () => { const appName = uniq('my-app'); expect(() => { - runCLI( - `generate @nrwl/nest:app ${appName} --skipPackageJson --no-interactive` - ); + runCLI(`generate @nrwl/nest:app ${appName} --no-interactive`); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); }); @@ -236,9 +210,7 @@ describe('create-nx-workspace --preset=npm', () => { const libName = uniq('lib'); expect(() => { - runCLI( - `generate @nrwl/nest:lib ${libName} --skipPackageJson --no-interactive` - ); + runCLI(`generate @nrwl/nest:lib ${libName} --no-interactive`); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); const tsconfig = readJson(`tsconfig.base.json`); @@ -253,9 +225,7 @@ describe('create-nx-workspace --preset=npm', () => { const appName = uniq('my-app'); expect(() => { - runCLI( - `generate @nrwl/express:app ${appName} --skipPackageJson --no-interactive` - ); + runCLI(`generate @nrwl/express:app ${appName} --no-interactive`); }).not.toThrowError(); checkFilesExist('tsconfig.base.json'); }); diff --git a/e2e/workspace-create/src/create-nx-workspace.test.ts b/e2e/workspace-create/src/create-nx-workspace.test.ts index 76fe6a4b90eca..cd9a09a3763cc 100644 --- a/e2e/workspace-create/src/create-nx-workspace.test.ts +++ b/e2e/workspace-create/src/create-nx-workspace.test.ts @@ -19,25 +19,6 @@ describe('create-nx-workspace', () => { afterEach(() => cleanupProject()); - it('should create a workspace with a single angular app at the root with routing', () => { - const wsName = uniq('angular'); - - runCreateWorkspace(wsName, { - preset: 'angular-standalone', - appName: wsName, - style: 'css', - packageManager, - standaloneApi: false, - routing: true, - }); - - checkFilesExist('package.json'); - checkFilesExist('src/app/app.routes.ts'); - checkFilesDoNotExist('tsconfig.base.json'); - checkFilesExist('project.json'); - expectCodeIsFormatted(); - }); - it('should create a workspace with a single angular app at the root without routing', () => { const wsName = uniq('angular'); @@ -46,6 +27,7 @@ describe('create-nx-workspace', () => { appName: wsName, style: 'css', packageManager, + standaloneApi: false, routing: false, }); @@ -70,6 +52,7 @@ describe('create-nx-workspace', () => { checkFilesExist('package.json'); checkFilesExist('project.json'); + checkFilesExist('src/app/app.routes.ts'); checkFilesDoNotExist('src/app/app.module.ts'); expectCodeIsFormatted(); }); @@ -113,7 +96,7 @@ describe('create-nx-workspace', () => { it('should be able to create an empty workspace built for apps', () => { const wsName = uniq('apps'); runCreateWorkspace(wsName, { - preset: 'empty', + preset: 'apps', packageManager, }); @@ -123,9 +106,6 @@ describe('create-nx-workspace', () => { 'apps/.gitkeep', 'libs/.gitkeep' ); - const foreignLockFiles = Object.keys(packageManagerLockFile) - .filter((pm) => pm !== packageManager) - .map((pm) => packageManagerLockFile[pm]); expectNoAngularDevkit(); }); @@ -179,7 +159,7 @@ describe('create-nx-workspace', () => { appName, packageManager, standaloneApi: false, - routing: true, + routing: false, }) ).toThrow(); }); @@ -293,7 +273,7 @@ describe('create-nx-workspace', () => { it('should be able to create a workspace with a custom base branch and HEAD', () => { const wsName = uniq('branch'); runCreateWorkspace(wsName, { - preset: 'empty', + preset: 'apps', base: 'main', packageManager, }); @@ -302,7 +282,7 @@ describe('create-nx-workspace', () => { it('should be able to create a workspace with custom commit information', () => { const wsName = uniq('branch'); runCreateWorkspace(wsName, { - preset: 'empty', + preset: 'apps', extraArgs: '--commit.name="John Doe" --commit.email="myemail@test.com" --commit.message="Custom commit message!"', packageManager, @@ -322,51 +302,24 @@ describe('create-nx-workspace', () => { it('should respect package manager preference', () => { const wsName = uniq('pm'); - const appName = uniq('app'); - - process.env.YARN_REGISTRY = `http://localhost:4872`; - process.env.SELECTED_PM = 'npm'; - - runCreateWorkspace(wsName, { - preset: 'react-monorepo', - style: 'css', - appName, - packageManager: 'npm', - bundler: 'webpack', - }); - - checkFilesDoNotExist('yarn.lock'); - checkFilesExist('package-lock.json'); - expectCodeIsFormatted(); - process.env.SELECTED_PM = packageManager; - }); - - it('should store package manager preference for angular', () => { - const wsName = uniq('pm'); - const appName = uniq('app'); process.env.YARN_REGISTRY = `http://localhost:4872`; process.env.SELECTED_PM = 'npm'; runCreateWorkspace(wsName, { - preset: 'angular-monorepo', - appName, - style: 'css', + preset: 'apps', packageManager: 'npm', - routing: true, - standaloneApi: false, }); checkFilesDoNotExist('yarn.lock'); checkFilesExist('package-lock.json'); - expectCodeIsFormatted(); process.env.SELECTED_PM = packageManager; }); it('should return error when ci workflow is selected but no cloud is set up', () => { const wsName = uniq('github'); - const create = runCreateWorkspace(wsName, { - preset: 'npm', + runCreateWorkspace(wsName, { + preset: 'apps', packageManager, ci: 'circleci', }); @@ -378,7 +331,7 @@ describe('create-nx-workspace', () => { function setupProject(envPm: 'npm' | 'yarn' | 'pnpm') { process.env.SELECTED_PM = envPm; runCreateWorkspace(uniq('pm'), { - preset: 'empty', + preset: 'apps', packageManager: envPm, useDetectedPm: true, }); @@ -425,7 +378,7 @@ describe('create-nx-workspace', () => { describe('create-nx-workspace custom parent folder', () => { const tmpDir = `${e2eCwd}/${uniq('with space')}`; - const wsName = uniq('empty'); + const wsName = uniq('parent'); const packageManager = getSelectedPackageManager() || 'pnpm'; afterEach(() => cleanupProject({ cwd: `${tmpDir}/${wsName}` })); diff --git a/packages/devkit/src/utils/package-json.ts b/packages/devkit/src/utils/package-json.ts index 8a427e627975c..b2726a34f9609 100644 --- a/packages/devkit/src/utils/package-json.ts +++ b/packages/devkit/src/utils/package-json.ts @@ -453,16 +453,17 @@ export function ensurePackage( const tempDir = dirSync().name; console.log(`Fetching ${pkg}...`); + const packageManager = detectPackageManager(); + let addCommand = getPackageManagerCommand(packageManager).addDev; + if (packageManager === 'pnpm') { + addCommand = 'pnpm add -D'; // we need to ensure that we are not using workspace command + } + const isVerbose = process.env.NX_VERBOSE_LOGGING === 'true'; - execSync( - `${ - getPackageManagerCommand(detectPackageManager(), tempDir).addDev - } ${pkg}@${requiredVersion}`, - { - cwd: tempDir, - stdio: isVerbose ? 'inherit' : 'ignore', - } - ); + execSync(`${addCommand} ${pkg}@${requiredVersion}`, { + cwd: tempDir, + stdio: isVerbose ? 'inherit' : 'ignore', + }); addToNodePath(join(workspaceRoot, 'node_modules')); addToNodePath(join(tempDir, 'node_modules')); diff --git a/packages/nx/src/utils/package-manager.ts b/packages/nx/src/utils/package-manager.ts index 6156b422de490..c41165b979aee 100644 --- a/packages/nx/src/utils/package-manager.ts +++ b/packages/nx/src/utils/package-manager.ts @@ -7,7 +7,6 @@ import { promisify } from 'util'; import { writeJsonFile } from './fileutils'; import { readModulePackageJson } from './package-json'; import { gte, lt } from 'semver'; -import { workspaceRoot } from './workspace-root'; const execAsync = promisify(exec); @@ -47,8 +46,7 @@ export function detectPackageManager(dir: string = ''): PackageManager { * ``` */ export function getPackageManagerCommand( - packageManager: PackageManager = detectPackageManager(), - root: string = workspaceRoot + packageManager: PackageManager = detectPackageManager() ): PackageManagerCommands { const commands: { [pm in PackageManager]: () => PackageManagerCommands } = { yarn: () => { @@ -72,7 +70,7 @@ export function getPackageManagerCommand( const pnpmVersion = getPackageManagerVersion('pnpm'); const useExec = gte(pnpmVersion, '6.13.0'); const includeDoubleDashBeforeArgs = lt(pnpmVersion, '7.0.0'); - const isPnpmWorkspace = existsSync(join(root, 'pnpm-workspace.yaml')); + const isPnpmWorkspace = existsSync('pnpm-workspace.yaml'); return { install: 'pnpm install --no-frozen-lockfile', // explicitly disable in case of CI