diff --git a/CHANGELOG.md b/CHANGELOG.md index 5eb68a8014..d7b29a05f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa ## Master +- Passes arguments following `--` when running a workspace script (`yarn workspace pkg run command -- arg`) + + [#7776](https://github.com/yarnpkg/yarn/pull/7776) - [**Jeff Valore**](https://twitter.com/rally25rs) + - Prints workspace names with `yarn workspaces` (silence with `-s`) [#7722](https://github.com/yarnpkg/yarn/pull/7722) - [**Orta**](https://twitter.com/orta) diff --git a/__tests__/commands/workspace.js b/__tests__/commands/workspace.js index a50442d22e..17d5c66d0c 100644 --- a/__tests__/commands/workspace.js +++ b/__tests__/commands/workspace.js @@ -38,12 +38,8 @@ async function runWorkspace( } } -// The unit tests don't use commander.js for argument parsing. -// `originalArgs` is normally passed by index.js so we just simulate it in the tests. - test('workspace run command', (): Promise => { - const originalArgs = ['workspace-1', 'run', 'script']; - return runWorkspace({originalArgs}, ['workspace-1', 'run', 'script'], 'run-basic', config => { + return runWorkspace({}, ['workspace-1', 'run', 'script'], 'run-basic', config => { expect(spawn).toHaveBeenCalledWith(NODE_BIN_PATH, [YARN_BIN_PATH, 'run', 'script'], { stdio: 'inherit', cwd: path.join(fixturesLoc, 'run-basic', 'packages', 'workspace-child-1'), @@ -52,8 +48,7 @@ test('workspace run command', (): Promise => { }); test('workspace run command forwards raw arguments', (): Promise => { - const originalArgs = ['workspace-1', 'run', 'script', 'arg1', '--flag1']; - return runWorkspace({originalArgs}, ['workspace-1', 'run', 'script'], 'run-basic', config => { + return runWorkspace({}, ['workspace-1', 'run', 'script', 'arg1', '--flag1'], 'run-basic', config => { expect(spawn).toHaveBeenCalledWith(NODE_BIN_PATH, [YARN_BIN_PATH, 'run', 'script', 'arg1', '--flag1'], { stdio: 'inherit', cwd: path.join(fixturesLoc, 'run-basic', 'packages', 'workspace-child-1'), diff --git a/__tests__/commands/workspaces.js b/__tests__/commands/workspaces.js index ad81f2df76..6a7ba993c1 100644 --- a/__tests__/commands/workspaces.js +++ b/__tests__/commands/workspaces.js @@ -49,13 +49,12 @@ 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'], { + return runWorkspaces({}, ['run', 'script', 'arg1', '--flag1'], 'run-basic', config => { + expect(spawn).toHaveBeenCalledWith(NODE_BIN_PATH, [YARN_BIN_PATH, 'run', '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'], { + expect(spawn).toHaveBeenCalledWith(NODE_BIN_PATH, [YARN_BIN_PATH, 'run', 'script', 'arg1', '--flag1'], { stdio: 'inherit', cwd: path.join(fixturesLoc, 'run-basic', 'packages', 'workspace-child-2'), }); diff --git a/__tests__/fixtures/index/run-workspace/packages/workspace-child-1/package.json b/__tests__/fixtures/index/run-workspace/packages/workspace-child-1/package.json index ad2acf109c..3bc59de531 100644 --- a/__tests__/fixtures/index/run-workspace/packages/workspace-child-1/package.json +++ b/__tests__/fixtures/index/run-workspace/packages/workspace-child-1/package.json @@ -5,6 +5,6 @@ "prescript": "echo workspace-1 prescript", "script": "echo workspace-1 script", "postscript": "echo workspace-1 postscript", - "check": "echo $1" + "check": "echo ARGS:" } } diff --git a/__tests__/fixtures/index/run-workspace/packages/workspace-child-2/package.json b/__tests__/fixtures/index/run-workspace/packages/workspace-child-2/package.json index 9d5534e885..6fff5b5006 100644 --- a/__tests__/fixtures/index/run-workspace/packages/workspace-child-2/package.json +++ b/__tests__/fixtures/index/run-workspace/packages/workspace-child-2/package.json @@ -4,7 +4,8 @@ "scripts": { "prescript": "echo workspace-2 prescript", "script": "echo workspace-2 script", - "postscript": "echo workspace-2 postscript" + "postscript": "echo workspace-2 postscript", + "check": "echo WORKSPACE-CHILD-2 ARGS:" }, "dependencies": { "workspace-1": "1.0.0" diff --git a/__tests__/fixtures/request-cache/GET/gitlab.com/leanlabsio/kanban/raw/7f21696fb9d08130dd62abd96c9572f513c05301/package.json.bin b/__tests__/fixtures/request-cache/GET/gitlab.com/leanlabsio/kanban/raw/7f21696fb9d08130dd62abd96c9572f513c05301/package.json.bin new file mode 100644 index 0000000000..11580057f6 --- /dev/null +++ b/__tests__/fixtures/request-cache/GET/gitlab.com/leanlabsio/kanban/raw/7f21696fb9d08130dd62abd96c9572f513c05301/package.json.bin @@ -0,0 +1,62 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Sun, 29 Dec 2019 14:24:54 GMT +Content-Type: text/plain; charset=utf-8 +Content-Length: 1181 +Cache-Control: max-age=3600, public +Content-Disposition: inline +Etag: W/"78309fbf8af4479c47eca65b0c5e3f51" +Referrer-Policy: strict-origin-when-cross-origin +Set-Cookie: experimentation_subject_id=IjJjZjk1MWRjLWUzMDgtNDc3ZC05MTlkLTA0MGU5MWFjY2VlOCI%3D--64f51f0ae3455ebf84d41c0a0a6723703e719689; domain=.gitlab.com; path=/; expires=Thu, 29 Dec 2039 14:24:54 -0000; secure; HttpOnly +X-Content-Type-Options: nosniff +X-Download-Options: noopen +X-Frame-Options: DENY +X-Permitted-Cross-Domain-Policies: none +X-Request-Id: xcIbPa5i6G2 +X-Runtime: 0.056763 +X-Ua-Compatible: IE=edge +X-Xss-Protection: 1; mode=block +Strict-Transport-Security: max-age=31536000 +Referrer-Policy: strict-origin-when-cross-origin +GitLab-LB: fe-07-lb-gprd +GitLab-SV: web-28-sv-gprd + +{ + "name": "kanban", + "version": "0.0.1", + "repository": "gitlab.com/leanlabsio/kanban", + "scripts": { + "install": "npm install", + "build": "grunt build", + "watch": "grunt watch" + }, + "devDependencies": { + "grunt": "~0.4.1", + "grunt-cli": "~0.1.13", + "grunt-contrib-copy": "^0.5.0", + "grunt-contrib-concat": "~0.5.0", + "grunt-contrib-watch": "~0.5.3", + "grunt-contrib-uglify": "~0.7.0", + "grunt-sass": "1.0.0", + "grunt-contrib-connect": "~0.8.0", + "grunt-connect-proxy": "~0.1.11" + }, + "dependencies": { + "angular": "=1.5.6", + "angular-lodash": "https://github.com/EMSSConsulting/angular-lodash.git#68a726c", + "foundation-sites": "5.5.2", + "angular-foundation": "https://github.com/pineconellc/angular-foundation.git#8f3f260", + "angular-loading-bar": "=0.5.2", + "angular-storage": "=0.0.6", + "angular-ui-router": "=0.3.0", + "angularjs-datepicker": "=0.2.15", + "font-awesome": "=4.6.3", + "markdown-it": "=5.0.2", + "markdown-it-emoji": "=1.1.0", + "ng-sortable": "=1.3.6", + "sass-flex-mixin": "=1.0.3", + "lodash": "=4.13.1", + "twemoji": "=2.1.0", + "angular-file-upload": "=2.3.4" + } +} diff --git a/__tests__/index.js b/__tests__/index.js index 218d7285d1..425e8acb76 100644 --- a/__tests__/index.js +++ b/__tests__/index.js @@ -355,6 +355,39 @@ test.concurrent('should run help for camelised command', async () => { // but actual flags on the command line are passed. test.concurrent('should not pass yarnrc flags to workspace command', async () => { const stdout = await execCommand('workspace', ['workspace-1', 'run', 'check', '--x'], 'run-workspace', true); - const params = stdout.find(x => x && x.indexOf('--x') >= 0); + const params = stdout.find(x => x && x.indexOf('ARGS:') === 0); expect(params).not.toMatch(/emoji/); }); + +// regression test for #7776 +test.concurrent('should pass args to workspace command without need for "--"', async () => { + const stdout = await execCommand('workspace', ['workspace-1', 'run', 'check', '--x', 'y'], 'run-workspace', true); + const params = stdout.find(x => x && x.indexOf('ARGS:') === 0); + expect(params).toEqual('ARGS: --x y'); +}); + +// regression test for #7776 +test.concurrent('should pass args after "--" to workspace command', async () => { + const stdout = await execCommand( + 'workspace', + ['workspace-1', 'run', 'check', '--', 'x', '-y'], + 'run-workspace', + true, + ); + const params = stdout.find(x => x && x.indexOf('ARGS:') === 0); + expect(params).toEqual('ARGS: x -y'); +}); + +// regression test for #7776 +test.concurrent('should pass args to workspaces command without need for "--"', async () => { + const stdout = await execCommand('workspaces', ['run', 'check', '--x', 'y'], 'run-workspace', true); + const params = stdout.find(x => x && x.indexOf('ARGS:') === 0); + expect(params).toEqual('ARGS: --x y'); +}); + +// regression test for #7776 +test.concurrent('should pass args after "--" to workspaces command', async () => { + const stdout = await execCommand('workspaces', ['run', 'check', '--', 'x', '-y'], 'run-workspace', true); + const params = stdout.find(x => x && x.indexOf('ARGS:') === 0); + expect(params).toEqual('ARGS: x -y'); +}); diff --git a/src/cli/commands/workspace.js b/src/cli/commands/workspace.js index f6708cd8d5..4be65c6ed1 100644 --- a/src/cli/commands/workspace.js +++ b/src/cli/commands/workspace.js @@ -21,11 +21,11 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg throw new MessageError(reporter.lang('workspaceRootNotFound', config.cwd)); } - if (flags.originalArgs < 1) { + if (args.length < 1) { throw new MessageError(reporter.lang('workspaceMissingWorkspace')); } - if (flags.originalArgs < 2) { + if (args.length < 2) { throw new MessageError(reporter.lang('workspaceMissingCommand')); } @@ -33,7 +33,7 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg invariant(manifest && manifest.workspaces, 'We must find a manifest with a "workspaces" property'); const workspaces = await config.resolveWorkspaces(workspaceRootFolder, manifest); - const [workspaceName, ...rest] = flags.originalArgs || []; + const [workspaceName, ...rest] = args || []; if (!Object.prototype.hasOwnProperty.call(workspaces, workspaceName)) { throw new MessageError(reporter.lang('workspaceUnknownWorkspace', workspaceName)); diff --git a/src/cli/commands/workspaces.js b/src/cli/commands/workspaces.js index 5896e98b50..e95e45f180 100644 --- a/src/cli/commands/workspaces.js +++ b/src/cli/commands/workspaces.js @@ -76,12 +76,10 @@ export async function runScript(config: Config, reporter: Reporter, flags: Objec const workspaces = await config.resolveWorkspaces(workspaceRootFolder, manifest); try { - const [_, ...rest] = flags.originalArgs || []; - for (const workspaceName of Object.keys(workspaces)) { const {loc} = workspaces[workspaceName]; reporter.log(`${os.EOL}> ${workspaceName}`); - await child.spawn(NODE_BIN_PATH, [YARN_BIN_PATH, ...rest], { + await child.spawn(NODE_BIN_PATH, [YARN_BIN_PATH, 'run', ...args], { stdio: 'inherit', cwd: loc, }); diff --git a/src/cli/index.js b/src/cli/index.js index 58103360b2..f86454a57a 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -198,15 +198,20 @@ export async function main({ let warnAboutRunDashDash = false; // we are using "yarn