feat(repo): support dynamic package manager for e2e tests

This commit is contained in:
Tasos Bekos 2021-01-16 15:44:10 +02:00
parent 659eb12047
commit c92f4ba96b
4 changed files with 106 additions and 53 deletions

View File

@ -12,6 +12,7 @@ import {
removeSync,
} from 'fs-extra';
import * as path from 'path';
import { detectPackageManager } from '@nrwl/tao/src/shared/package-manager';
interface RunCmdOpts {
silenceError?: boolean;
@ -26,11 +27,6 @@ export function currentCli() {
let projName: string;
function setCurrentProjName(name: string) {
projName = name;
return name;
}
export function uniq(prefix: string) {
return `${prefix}${Math.floor(Math.random() * 10000000)}`;
}
@ -54,18 +50,18 @@ export function runCreateWorkspace(
appName?: string;
style?: string;
base?: string;
packageManager?: string;
packageManager?: 'npm' | 'yarn' | 'pnpm';
cli?: string;
extraArgs?: string;
}
) {
setCurrentProjName(name);
projName = name;
const pm = getPackageManagerCommand({ packageManager });
const linterArg =
preset === 'angular' || preset === 'angular-nest' ? ' --linter=tslint' : '';
let command = `npx create-nx-workspace@${
process.env.PUBLISHED_VERSION
} ${name} --cli=${
let command = `${pm.createWorkspace} ${name} --cli=${
cli || currentCli()
} --preset=${preset} ${linterArg} --no-nxCloud --no-interactive`;
if (appName) {
@ -97,7 +93,8 @@ export function runCreateWorkspace(
export function packageInstall(pkg: string, projName?: string) {
const cwd = projName ? `./tmp/${currentCli()}/${projName}` : tmpProjPath();
const install = execSync(`npm i ${pkg}`, {
const pm = getPackageManagerCommand({ path: cwd });
const install = execSync(`${pm.add} ${pkg}`, {
cwd,
// ...{ stdio: ['pipe', 'pipe', 'pipe'] },
...{ stdio: [0, 1, 2] },
@ -118,9 +115,15 @@ export function runNgNew(): string {
* for the currently selected CLI.
*/
export function newProject(): string {
const packageManager = process.env.SELECTED_PM as any;
try {
if (!directoryExists(tmpBackupProjPath())) {
runCreateWorkspace('proj', { preset: 'empty' });
const newProjName = uniq('proj');
const useBackupProject = packageManager !== 'pnpm';
const projScope = useBackupProject ? 'proj' : newProjName;
if (!useBackupProject || !directoryExists(tmpBackupProjPath())) {
runCreateWorkspace(projScope, { preset: 'empty', packageManager });
const packages = [
`@nrwl/angular`,
`@nrwl/express`,
@ -131,12 +134,16 @@ export function newProject(): string {
`@nrwl/nx-plugin`,
`@nrwl/eslint-plugin-nx`,
];
packageInstall(packages.join(` `), 'proj');
moveSync(`./tmp/${currentCli()}/proj`, `${tmpBackupProjPath()}`);
packageInstall(packages.join(` `), projScope);
if (useBackupProject) {
moveSync(`./tmp/${currentCli()}/proj`, `${tmpBackupProjPath()}`);
}
}
projName = uniq('proj');
copySync(`${tmpBackupProjPath()}`, `${tmpProjPath()}`);
return 'proj';
projName = newProjName;
if (useBackupProject) {
copySync(`${tmpBackupProjPath()}`, `${tmpProjPath()}`);
}
return projScope;
} catch (e) {
console.log(`Failed to set up project for e2e tests.`);
console.log(e.message);
@ -178,7 +185,8 @@ export function runCommandUntil(
criteria: (output: string) => boolean,
{ kill = true } = {}
): Promise<{ process: ChildProcess }> {
const p = exec(`npm run nx --scripts-prepend-node-path -- ${command}`, {
const pm = getPackageManagerCommand();
const p = exec(`${pm.runNx} ${command}`, {
cwd: tmpProjPath(),
env: { ...process.env, FORCE_COLOR: 'false' },
});
@ -217,10 +225,9 @@ export function runCLIAsync(
silent: false,
}
): Promise<{ stdout: string; stderr: string; combinedOutput: string }> {
const pm = getPackageManagerCommand();
return runCommandAsync(
`npm run nx ${
opts.silent ? '--silent' : ''
} --scripts-prepend-node-path -- ${command}`,
`${opts.silent ? pm.runNxSilent : pm.runNx} ${command}`,
opts
);
}
@ -265,9 +272,10 @@ export function runCLI(
}
): string {
try {
let r = execSync(`npm run nx --scripts-prepend-node-path -- ${command}`, {
const pm = getPackageManagerCommand();
let r = execSync(`${pm.runNx} ${command}`, {
cwd: opts.cwd || tmpProjPath(),
env: opts.env as any,
env: opts.env,
}).toString();
r = r.replace(
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
@ -448,3 +456,40 @@ function tmpBackupProjPath(path?: string) {
? `./tmp/${currentCli()}/proj-backup/${path}`
: `./tmp/${currentCli()}/proj-backup`;
}
export function getPackageManagerCommand({
path = tmpProjPath(),
packageManager = detectPackageManager(path),
scriptsPrependNodePath = true,
} = {}): {
createWorkspace: string;
runNx: string;
runNxSilent: string;
add: string;
} {
const scriptsPrependNodePathFlag = scriptsPrependNodePath
? ' --scripts-prepend-node-path '
: '';
return {
npm: {
createWorkspace: `npx create-nx-workspace@${process.env.PUBLISHED_VERSION}`,
runNx: `npm run nx${scriptsPrependNodePathFlag} --`,
runNxSilent: `npm run nx --silent${scriptsPrependNodePathFlag} --`,
add: `npm install`,
},
yarn: {
// `yarn create nx-workspace` is failing due to wrong global path
createWorkspace: `yarn global add create-nx-workspace@${process.env.PUBLISHED_VERSION} && create-nx-workspace`,
runNx: `yarn nx`,
runNxSilent: `yarn --silent nx`,
add: `yarn add`,
},
pnpm: {
createWorkspace: `pnpx create-nx-workspace@${process.env.PUBLISHED_VERSION}`,
runNx: `pnpm run nx --`,
runNxSilent: `pnpm run nx --silent --`,
add: `pnpm add`,
},
}[packageManager];
}

View File

@ -1,5 +1,6 @@
import { NxJson } from '@nrwl/workspace';
import {
getPackageManagerCommand,
listFiles,
newProject,
readFile,
@ -194,7 +195,7 @@ describe('run-many', () => {
});
describe('affected:*', () => {
it('should print, build, and test affected apps', () => {
it('should print, build, and test affected apps', async () => {
const proj = newProject();
const myapp = uniq('myapp');
const myapp2 = uniq('myapp2');
@ -232,9 +233,12 @@ describe('affected:*', () => {
`
);
expect(
runCLI(
`affected:apps --files="libs/${mylib}/src/index.ts" --plain`
).split('\n')[4]
(
await runCLIAsync(
`affected:apps --files="libs/${mylib}/src/index.ts" --plain`,
{ silent: true }
)
).stdout.trim()
).toEqual(myapp);
const affectedApps = runCLI(
@ -255,9 +259,12 @@ describe('affected:*', () => {
expect(noAffectedApps).not.toContain(myapp2);
expect(
runCLI(
`affected:libs --files="libs/${mylib}/src/index.ts" --plain`
).split('\n')[4]
(
await runCLIAsync(
`affected:libs --files="libs/${mylib}/src/index.ts" --plain`,
{ silent: true }
)
).stdout.trim()
).toEqual(`${mylib} ${mypublishablelib}`);
const affectedLibs = runCLI(
@ -341,7 +348,7 @@ describe('affected:*', () => {
expect(isolatedTests).toContain(`- ${myapp}`);
const interpolatedTests = runCLI(
`affected --target test --files="libs/${mylib}/src/index.ts" -- --jest-config {project.root}/jest.config.js`
`affected --target test --files="libs/${mylib}/src/index.ts" --jest-config {project.root}/jest.config.js`
);
expect(interpolatedTests).toContain(`Running target \"test\" succeeded`);
}, 1000000);
@ -480,6 +487,9 @@ describe('print-affected', () => {
).stdout.trim()
);
const { runNx } = getPackageManagerCommand({
scriptsPrependNodePath: false,
});
expect(resWithTarget.tasks[0]).toMatchObject({
id: `${myapp}:test`,
overrides: {},
@ -487,7 +497,7 @@ describe('print-affected', () => {
project: myapp,
target: 'test',
},
command: `npm run nx -- test ${myapp}`,
command: `${runNx} test ${myapp}`,
outputs: [`coverage/apps/${myapp}`],
});
expect(resWithTarget.tasks[0].hash).toBeDefined();
@ -509,7 +519,7 @@ describe('print-affected', () => {
project: myapp,
target: 'build',
},
command: `npm run nx -- build ${myapp}`,
command: `${runNx} build ${myapp}`,
outputs: [`dist/apps/${myapp}`],
});
expect(resWithDeps.tasks[0].hash).toBeDefined();
@ -521,7 +531,7 @@ describe('print-affected', () => {
project: mypublishablelib,
target: 'build',
},
command: `npm run nx -- build ${mypublishablelib}`,
command: `${runNx} build ${mypublishablelib}`,
outputs: [`dist/libs/${mypublishablelib}`],
});
expect(resWithDeps.tasks[1].hash).toBeDefined();

View File

@ -1,9 +1,10 @@
import { existsSync } from 'fs';
import { join } from 'path';
export function detectPackageManager() {
return existsSync('yarn.lock')
export function detectPackageManager(dir = '') {
return existsSync(join(dir, 'yarn.lock'))
? 'yarn'
: existsSync('pnpm-lock.yaml')
: existsSync(join(dir, 'pnpm-lock.yaml'))
? 'pnpm'
: 'npm';
}

View File

@ -3,36 +3,33 @@ storage: ../../tmp/local-registry/storage
auth:
htpasswd:
file: ./htpasswd
max_users: 1
# a list of other known repositories we can talk to
uplinks:
npmjs:
url: https://registry.npmjs.org/
cache: true
yarn:
url: https://registry.yarnpkg.com
cache: true
max_fails: 100
maxage: 30m
fail_timeout: 10m
timeout: 600s
agent_options:
keepAlive: true
maxSockets: 40
maxFreeSockets: 10
cache: false
packages:
'@*/*':
# scoped packages
'@nrwl/*':
access: $all
publish: $all
unpublish: $all
proxy: npmjs
'**':
# allow all users (including non-authenticated users) to read and
# publish all packages
access: $all
# allow all users (including non-authenticated users) to publish/publish packages
publish: $all
unpublish: $all
# if package is not available locally, proxy requests to 'yarn' registry
proxy: npmjs
# log settings
logs:
- { type: stdout, format: pretty, level: error }
- { type: stdout, format: pretty, level: warn }