feat(core): support yarn berry in CNW (#11528)

This commit is contained in:
Miroslav Jonaš 2022-08-11 19:37:53 +02:00 committed by GitHub
parent 164111b793
commit 36213b71fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 113 additions and 26 deletions

View File

@ -70,7 +70,37 @@ To publish packages to a local registry, do the following:
- Run `cd ./tmp` in Terminal 2
- Run `npx create-nx-workspace@999.9.9` in Terminal 2
If you have problems publishing, make sure you use Node 14 and NPM 6 instead of Node 15 and NPM 7.
If you have problems publishing, make sure you use Node 16 and NPM 6 or 8.
### Publishing for Yarn 2+ (Berry)
Yarn Berry operates slightly differently than Yarn Classic. In order to publish packages for Berry follow next steps:
- Run `yarn set version berry` to switch to latest Yarn version.
- Create `.yarnrc.yml` in root with following contents:
```yml
nodeLinker: node-modules
npmRegistryServer: 'http://localhost:4873'
unsafeHttpWhitelist:
- localhost
```
- Run `yarn local-registry start` in Terminal 1 (keep it running)
- If you are creating nx workspace outside of your nx repo, make sure to add npm registry info to your root yarnrc (usually in ~/.yarnrc.yml). The file should look something like this:
```yml
npmRegistries:
'https://registry.yarnpkg.com':
npmAuthToken: npm_******************
yarnPath: .yarn/releases/yarn-3.2.2.cjs
npmRegistryServer: 'http://localhost:4873'
unsafeHttpWhitelist:
- localhost
```
- Run `yarn nx-release --local` in Terminal 2 to publish next minor version. If this version already exists, you can bump the minor version in `lerna.json` to toggle the next minor. The output will report the version of published packages.
- Go to your target folder (e.g. `cd ./tmp`) in Terminal 2
- Run `yarn dlx create-nx-workspace@123.4.5` in Terminal 2 (replace `123.4.5` with the version that got published).
### Running Unit Tests

View File

@ -13,6 +13,7 @@ import {
getPackageManagerVersion,
PackageManager,
packageManagerList,
generatePackageManagerFiles,
} from './package-manager';
import { validateNpmPackage } from './validate-npm-package';
import { deduceDefaultBase } from './default-base';
@ -720,8 +721,9 @@ async function createSandbox(packageManager: PackageManager) {
license: 'MIT',
})
);
generatePackageManagerFiles(tmpDir, packageManager);
await execAndWait(`${install} --silent --ignore-scripts`, tmpDir);
await execAndWait(install, tmpDir);
installSpinner.succeed();
} catch (e) {

View File

@ -1,5 +1,5 @@
import { execSync } from 'child_process';
import { existsSync } from 'fs';
import { existsSync, writeFileSync } from 'fs';
import { join } from 'path';
/*
@ -37,21 +37,27 @@ export function getPackageManagerCommand(
install: string;
exec: string;
} {
const [pmMajor, pmMinor] =
getPackageManagerVersion(packageManager).split('.');
switch (packageManager) {
case 'yarn':
const useBerry = +pmMajor >= 2;
const installCommand = 'yarn install --silent';
return {
install: 'yarn',
install: useBerry
? installCommand
: `${installCommand} --ignore-scripts`,
exec: 'yarn',
};
case 'pnpm':
const [major, minor] = getPackageManagerVersion('pnpm').split('.');
let useExec = false;
if ((+major >= 6 && +minor >= 13) || +major >= 7) {
if ((+pmMajor >= 6 && +pmMinor >= 13) || +pmMajor >= 7) {
useExec = true;
}
return {
install: 'pnpm install --no-frozen-lockfile', // explicitly disable in case of CI
install: 'pnpm install --no-frozen-lockfile --silent --ignore-scripts',
exec: useExec ? 'pnpm exec' : 'pnpx',
};
@ -59,12 +65,29 @@ export function getPackageManagerCommand(
process.env.npm_config_legacy_peer_deps =
process.env.npm_config_legacy_peer_deps ?? 'true';
return {
install: 'npm install',
install: 'npm install --silent --ignore-scripts',
exec: 'npx',
};
}
}
export function generatePackageManagerFiles(
root: string,
packageManager: PackageManager = detectPackageManager()
) {
const [pmMajor] = getPackageManagerVersion(packageManager).split('.');
switch (packageManager) {
case 'yarn':
if (+pmMajor >= 2) {
writeFileSync(
join(root, '.yarnrc.yml'),
'nodeLinker: node-modules\nenableScripts: false'
);
}
break;
}
}
export function getPackageManagerVersion(
packageManager: PackageManager
): string {

View File

@ -13,7 +13,17 @@ import { ProjectConverter } from './project-converter';
/**
* Don't run actual child_process implementation of installPackagesTask()
*/
jest.mock('child_process');
jest.mock('child_process', () => {
return {
...jest.requireActual<any>('child_process'),
execSync: jest.fn((command: string) => {
if (command.includes('yarn --version')) {
return '1.22.0';
}
return;
}),
};
});
/**
* Don't run the conversion util, it touches the file system and has its own tests

View File

@ -4,8 +4,8 @@ import { remove } from 'fs-extra';
import { dirname, join } from 'path';
import { dirSync } from 'tmp';
import { promisify } from 'util';
import { readJsonFile, writeJsonFile } from './fileutils';
import { PackageJson, readModulePackageJson } from './package-json';
import { writeJsonFile } from './fileutils';
import { readModulePackageJson } from './package-json';
import { gte, lt } from 'semver';
const execAsync = promisify(exec);
@ -49,16 +49,23 @@ export function getPackageManagerCommand(
packageManager: PackageManager = detectPackageManager()
): PackageManagerCommands {
const commands: { [pm in PackageManager]: () => PackageManagerCommands } = {
yarn: () => ({
yarn: () => {
const yarnVersion = getPackageManagerVersion('yarn');
const useBerry = gte(yarnVersion, '2.0.0');
return {
install: 'yarn',
ciInstall: 'yarn --frozen-lockfile',
add: 'yarn add -W',
addDev: 'yarn add -D -W',
ciInstall: useBerry
? 'yarn install --immutable'
: 'yarn install --frozen-lockfile',
add: useBerry ? 'yarn add' : 'yarn add -W',
addDev: useBerry ? 'yarn add -D' : 'yarn add -D -W',
rm: 'yarn remove',
exec: 'yarn',
exec: useBerry ? 'yarn exec' : 'yarn',
run: (script: string, args: string) => `yarn ${script} ${args}`,
list: 'yarn list',
}),
list: useBerry ? 'yarn info --name-only' : 'yarn list',
};
},
pnpm: () => {
const pnpmVersion = getPackageManagerVersion('pnpm');
const useExec = gte(pnpmVersion, '6.13.0');

View File

@ -28,7 +28,7 @@ jobs:
pool:
vmImage: 'ubuntu-latest'
steps:
- script: yarn --frozen-lockfile
- script: yarn install --frozen-lockfile
displayName: NPM Install Dependencies
- script: npx nx-cloud start-agent
displayName: Start Nx-Cloud agent
@ -38,7 +38,7 @@ jobs:
pool:
vmImage: 'ubuntu-latest'
steps:
- script: yarn --frozen-lockfile
- script: yarn install --frozen-lockfile
displayName: NPM Install Dependencies
- script: yarn nx-cloud start-ci-run
displayName: Start CI run
@ -75,7 +75,7 @@ jobs:
- checkout
- run:
name: Install dependencies
command: yarn --frozen-lockfile
command: yarn install --frozen-lockfile
- run:
name: Start the agent << parameters.ordinal >>
command: yarn nx-cloud start-agent
@ -89,7 +89,7 @@ jobs:
- checkout
- run:
name: Install dependencies
command: yarn --frozen-lockfile
command: yarn install --frozen-lockfile
- nx/set-shas:
main-branch-name: 'main'
- run:

View File

@ -6,6 +6,8 @@ import {
names,
writeJson,
formatFiles,
getPackageManagerVersion,
PackageManager,
} from '@nrwl/devkit';
import { Schema } from './schema';
import {
@ -94,6 +96,14 @@ function createNpmrc(host: Tree, options: Schema) {
);
}
// ensure that yarn (berry) install uses classic node linker
function createYarnrcYml(host: Tree, options: Schema) {
host.write(
join(options.directory, '.yarnrc.yml'),
'nodeLinker: node-modules\n'
);
}
function formatWorkspaceJson(host: Tree, options: Schema) {
const path = join(
options.directory,
@ -151,8 +161,13 @@ export async function workspaceGenerator(host: Tree, options: Schema) {
if (options.cli === 'angular') {
decorateAngularClI(host, options);
}
if (options.packageManager === 'pnpm') {
const [packageMajor] = getPackageManagerVersion(
options.packageManager as PackageManager
).split('.');
if (options.packageManager === 'pnpm' && +packageMajor >= 7) {
createNpmrc(host, options);
} else if (options.packageManager === 'yarn' && +packageMajor >= 2) {
createYarnrcYml(host, options);
}
setPresetProperty(host, options);
addNpmScripts(host, options);