From d569434c0b16af17fcef17b09fe80e66facf8053 Mon Sep 17 00:00:00 2001 From: Robin Pellegrims <6053571+robinpellegrims@users.noreply.github.com> Date: Sun, 20 Mar 2022 17:34:27 +0100 Subject: [PATCH] fix(nx-distributed-task): running NX command is not working with pnpm (#44) --- .../nx-distributed-task/src/app/nx.spec.ts | 88 ++++++++++++------- packages/nx-distributed-task/src/app/nx.ts | 13 ++- 2 files changed, 64 insertions(+), 37 deletions(-) diff --git a/packages/nx-distributed-task/src/app/nx.spec.ts b/packages/nx-distributed-task/src/app/nx.spec.ts index 0efc2835..4a710797 100644 --- a/packages/nx-distributed-task/src/app/nx.spec.ts +++ b/packages/nx-distributed-task/src/app/nx.spec.ts @@ -1,12 +1,14 @@ import * as pm from '@nrwl/tao/src/shared/package-manager'; +import * as childProcess from 'child_process'; +import * as fs from 'fs'; import { context } from '@actions/github'; - import { Exec } from '@e-square/utils/exec'; import { logger } from '@e-square/utils/logger'; - import { assertNxInstalled, nxCommand, nxRunMany } from './nx'; jest.mock('@e-square/utils/logger'); +jest.mock('child_process'); +jest.mock('fs'); describe('nx', () => { describe('assertNxInstalled', () => { @@ -35,42 +37,60 @@ describe('nx', () => { jest.spyOn(exec, 'withCommand'); jest.spyOn(exec, 'withArgs'); jest.spyOn(exec, 'withOptions'); - jest.spyOn(pm, 'getPackageManagerVersion').mockReturnValue('6.8.0'); }); - it('should call nxCommand', async () => { - await expect(nxCommand('test', { target: 'build' }, exec)).resolves.toBe(''); - expect(exec.withCommand).toHaveBeenCalledWith(`npx -p @nrwl/cli nx test`); - expect(exec.withArgs).toHaveBeenCalledWith('--target=build'); + const cases: [pm.PackageManager, string, string][] = [ + ['npm', '6.8.0', 'npx -p @nrwl/cli'], + ['npm', '7.0.0', 'npx --no -p @nrwl/cli'], + ['pnpm', '6.12.0', 'pnpx'], + ['pnpm', '6.13.0', 'pnpm exec'], + ['yarn', '1.22.16', 'yarn -p @nrwl/cli'], + ]; - jest.spyOn(pm, 'getPackageManagerVersion').mockReturnValueOnce('7.0.0'); - await expect(nxCommand('test', { target: 'build' }, exec)).resolves.toBe(''); - expect(exec.withCommand).toHaveBeenCalledWith(`npx --no -p @nrwl/cli nx test`); - }); + describe.each(cases)('%s %s', (packageManager, pmVersion, expectedCommand) => { + // pretend lockfile exists for the specific package manager + beforeEach(() => { + jest + .spyOn(fs, 'existsSync') + .mockImplementation( + (file: string) => + (file.endsWith('yarn.lock') && packageManager === 'yarn') || + (file.endsWith('pnpm-lock.yaml') && packageManager === 'pnpm') + ); + // mock return value for [packageManager] --version + jest.spyOn(childProcess, 'execSync').mockReturnValue(Buffer.from(pmVersion, 'utf-8')); + }); - it('should call nxRunMany', async () => { - await expect( - nxRunMany( - context, - { - target: 'test', - projects: ['test'], - scan: true, - parallel: 3, - }, - exec - ) - ).resolves.toBe(''); - expect(exec.withCommand).toHaveBeenCalledWith(`npx -p @nrwl/cli nx run-many`); - expect(exec.withArgs).toHaveBeenCalledWith('--target=test', '--projects=test', '--scan', '--parallel=3'); - expect(exec.withOptions).toHaveBeenCalledWith( - expect.objectContaining({ - env: expect.objectContaining({ - NX_BRANCH: '0', - NX_RUN_GROUP: '0', - }), - }) - ); + it('should call nxCommand', async () => { + await expect(nxCommand('test', { target: 'build' }, exec)).resolves.toBe(''); + expect(exec.withCommand).toHaveBeenCalledWith(`${expectedCommand} nx test`); + expect(exec.withArgs).toHaveBeenCalledWith('--target=build'); + }); + + it('should call nxRunMany', async () => { + await expect( + nxRunMany( + context, + { + target: 'test', + projects: ['test'], + scan: true, + parallel: 3, + }, + exec + ) + ).resolves.toBe(''); + expect(exec.withCommand).toHaveBeenCalledWith(`${expectedCommand} nx run-many`); + expect(exec.withArgs).toHaveBeenCalledWith('--target=test', '--projects=test', '--scan', '--parallel=3'); + expect(exec.withOptions).toHaveBeenCalledWith( + expect.objectContaining({ + env: expect.objectContaining({ + NX_BRANCH: '0', + NX_RUN_GROUP: '0', + }), + }) + ); + }); }); it('should not call nxCommand when in debug mode', async () => { diff --git a/packages/nx-distributed-task/src/app/nx.ts b/packages/nx-distributed-task/src/app/nx.ts index 814e21af..3aa956f9 100644 --- a/packages/nx-distributed-task/src/app/nx.ts +++ b/packages/nx-distributed-task/src/app/nx.ts @@ -18,12 +18,19 @@ export async function assertNxInstalled(exec: Exec) { } export async function nxCommand(nxCommand: string, args: NxArgs, exec: Exec): Promise { - const pmVersion = getPackageManagerVersion().split('.'); + const [pmMajorVersion] = getPackageManagerVersion().split('.'); let command = getPackageManagerCommand().exec; - if (command === 'npx' && Number(pmVersion[0]) > 6) command += ' --no'; + const isNpx = command === 'npx'; + const isYarn = command === 'yarn'; + if (isNpx && Number(pmMajorVersion) > 6) { + command += ' --no'; + } + if (isNpx || isYarn) { + command += ` -p @nrwl/cli`; + } const wrapper = exec - .withCommand(`${command} -p @nrwl/cli nx ${nxCommand}`) + .withCommand(`${command} nx ${nxCommand}`) .withArgs( ...Object.entries(args).map(([k, v]) => typeof v === 'boolean' && v ? `--${names(k).fileName}` : `--${names(k).fileName}=${v}`