From 53a648390717eb56b23599079496b166ceb1eda8 Mon Sep 17 00:00:00 2001 From: Kyle Welch Date: Mon, 13 Aug 2018 17:04:00 -0500 Subject: [PATCH] Added ability to run script on all workspaces (#6244) * Added ability to run script on all workspaces * Makes the execution synchronous --- __tests__/commands/workspaces.js | 19 ++++++++++++++++++ src/cli/commands/workspaces.js | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/__tests__/commands/workspaces.js b/__tests__/commands/workspaces.js index 3b8254dc2a..ad81f2df76 100644 --- a/__tests__/commands/workspaces.js +++ b/__tests__/commands/workspaces.js @@ -1,12 +1,17 @@ // @flow +jest.mock('../../src/util/child'); import {BufferReporter} from '../../src/reporters/index.js'; import {run as workspace} from '../../src/cli/commands/workspaces.js'; import * as reporters from '../../src/reporters/index.js'; import Config from '../../src/config.js'; import path from 'path'; +import {NODE_BIN_PATH, YARN_BIN_PATH} from '../../src/constants'; const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'workspace'); +const spawn: $FlowFixMe = require('../../src/util/child').spawn; + +beforeEach(() => spawn.mockClear()); async function runWorkspaces( flags: Object, @@ -42,3 +47,17 @@ test('workspaces info should list the workspaces', (): Promise => { }); }); }); + +test('workspaces run should spawn command for each workspace', (): Promise => { + const originalArgs = ['run', 'script', 'arg1', '--flag1']; + return runWorkspaces({originalArgs}, ['run', 'script', 'arg1', '--flag1'], 'run-basic', config => { + expect(spawn).toHaveBeenCalledWith(NODE_BIN_PATH, [YARN_BIN_PATH, 'script', 'arg1', '--flag1'], { + stdio: 'inherit', + cwd: path.join(fixturesLoc, 'run-basic', 'packages', 'workspace-child-1'), + }); + expect(spawn).toHaveBeenCalledWith(NODE_BIN_PATH, [YARN_BIN_PATH, 'script', 'arg1', '--flag1'], { + stdio: 'inherit', + cwd: path.join(fixturesLoc, 'run-basic', 'packages', 'workspace-child-2'), + }); + }); +}); diff --git a/src/cli/commands/workspaces.js b/src/cli/commands/workspaces.js index 03e4313b9f..616cffe041 100644 --- a/src/cli/commands/workspaces.js +++ b/src/cli/commands/workspaces.js @@ -5,6 +5,8 @@ import {MessageError} from '../../errors.js'; import type {Reporter} from '../../reporters/index.js'; import buildSubCommands from './_build-sub-commands.js'; import {DEPENDENCY_TYPES} from '../../constants.js'; +import * as child from '../../util/child.js'; +import {NODE_BIN_PATH, YARN_BIN_PATH} from '../../constants'; const invariant = require('invariant'); const path = require('path'); @@ -60,10 +62,41 @@ export async function info(config: Config, reporter: Reporter, flags: Object, ar reporter.log(JSON.stringify(publicData, null, 2), {force: true}); } +export async function runScript(config: Config, reporter: Reporter, flags: Object, args: Array): Promise { + const {workspaceRootFolder} = config; + + if (!workspaceRootFolder) { + throw new MessageError(reporter.lang('workspaceRootNotFound', config.cwd)); + } + + const manifest = await config.findManifest(workspaceRootFolder, false); + invariant(manifest && manifest.workspaces, 'We must find a manifest with a "workspaces" property'); + + const workspaces = await config.resolveWorkspaces(workspaceRootFolder, manifest); + + try { + const [_, ...rest] = flags.originalArgs || []; + + for (const workspaceName of Object.keys(workspaces)) { + const {loc} = workspaces[workspaceName]; + + await child.spawn(NODE_BIN_PATH, [YARN_BIN_PATH, ...rest], { + stdio: 'inherit', + cwd: loc, + }); + } + } catch (err) { + throw err; + } +} + const {run, setFlags, examples} = buildSubCommands('workspaces', { async info(config: Config, reporter: Reporter, flags: Object, args: Array): Promise { await info(config, reporter, flags, args); }, + async run(config: Config, reporter: Reporter, flags: Object, args: Array): Promise { + await runScript(config, reporter, flags, args); + }, }); export {run, setFlags, examples};