From daac3a0d2b86f059eaa4b3f1d3eef57dae30eaed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Wed, 24 Oct 2018 17:48:24 +0100 Subject: [PATCH 01/13] Bumps the changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33e8693268..edb1a86287 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa ## Master +## 1.12.1 + - Ensures the engine check is ran before showing the UI for `upgrade-interactive` [#6536](https://github.com/yarnpkg/yarn/pull/6536) - [**Orta Therox**](https://github.com/orta) From 97834002c7fc1d487b68297ea05247a9ba8bbdf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Thu, 25 Oct 2018 13:24:33 +0100 Subject: [PATCH 02/13] Fixes Node 10 CI on OSX (#6580) * Update config.yml * Update config.yml * Update config.yml --- .circleci/config.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2e08597b40..bd6f6f0dd9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -157,6 +157,8 @@ jobs: brew uninstall --ignore-dependencies node brew update HOMEBREW_NO_AUTO_UPDATE=1 brew install node@10 + brew link --overwrite --force node@10 + [[ $(node --version) =~ ^v10\. ]] - *attach_workspace - *test_build - *test_run @@ -168,6 +170,8 @@ jobs: command: | brew uninstall --ignore-dependencies node HOMEBREW_NO_AUTO_UPDATE=1 brew install node@8 + brew link --overwrite --force node@8 + [[ $(node --version) =~ ^v8\. ]] - *attach_workspace - *test_build - *test_run @@ -179,7 +183,8 @@ jobs: command: | brew uninstall --ignore-dependencies node HOMEBREW_NO_AUTO_UPDATE=1 brew install node@6 - brew link --force node@6 + brew link --overwrite --force node@6 + [[ $(node --version) =~ ^v6\. ]] - *attach_workspace - *test_build - *test_run From 4b8e49e7af42705d217a2c113ce65ffabe163b93 Mon Sep 17 00:00:00 2001 From: Jack Zhao Date: Thu, 1 Nov 2018 09:30:08 -0700 Subject: [PATCH 03/13] fix audit for packages without name (#6611) * fix audit for packages without name * add test * fix bad dependency version * fix bad dependency version * Update audit.js * Update CHANGELOG.md --- CHANGELOG.md | 8 ++ __tests__/commands/audit.js | 39 ++++++++++ .../private-package/audit-api-response.json | 77 +++++++++++++++++++ .../audit/private-package/package.json | 6 ++ .../fixtures/audit/private-package/yarn.lock | 8 ++ src/cli/commands/audit.js | 11 ++- 6 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 __tests__/fixtures/audit/private-package/audit-api-response.json create mode 100644 __tests__/fixtures/audit/private-package/package.json create mode 100644 __tests__/fixtures/audit/private-package/yarn.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index edb1a86287..91f609c174 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa ## Master +- Fixes an issue with `yarn audit` when the root package was missing a name + + [#6611](https://github.com/yarnpkg/yarn/pull/6611) - [**Jack Zhao**](https://github.com/bugzpodder) + +- Fixes an issue with `yarn audit` when a package was depending on an empty range + + [#6611](https://github.com/yarnpkg/yarn/pull/6611) - [**Jack Zhao**](https://github.com/bugzpodder) + ## 1.12.1 - Ensures the engine check is ran before showing the UI for `upgrade-interactive` diff --git a/__tests__/commands/audit.js b/__tests__/commands/audit.js index aaf0fa5046..9ba7c8b4c4 100644 --- a/__tests__/commands/audit.js +++ b/__tests__/commands/audit.js @@ -123,3 +123,42 @@ test('calls reporter auditSummary with correct data', () => { expect(reporter.auditSummary).toBeCalledWith(apiResponse.metadata); }); }); + +test.concurrent('sends correct dependency map to audit api for private package.', () => { + const expectedApiPost = { + install: [], + remove: [], + metadata: {}, + requires: { + 'left-pad': '^1.3.0', + }, + dependencies: { + 'left-pad': { + version: '1.3.0', + integrity: 'sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==', + requires: {}, + dependencies: {}, + }, + }, + }; + + return runAudit([], {}, 'private-package', async config => { + const calledWithPipe = config.requestManager.request.mock.calls[0][0].body; + const calledWith = JSON.parse(await gunzip(calledWithPipe)); + expect(calledWith).toEqual(expectedApiPost); + }); +}); + +test('calls reporter auditAdvisory with correct data for private package', () => { + return runAudit([], {}, 'single-vulnerable-dep-installed', (config, reporter) => { + const apiResponse = getAuditResponse(config); + expect(reporter.auditAdvisory).toBeCalledWith(apiResponse.actions[0].resolves[0], apiResponse.advisories['118']); + }); +}); + +test('calls reporter auditSummary with correct data for private package', () => { + return runAudit([], {}, 'single-vulnerable-dep-installed', (config, reporter) => { + const apiResponse = getAuditResponse(config); + expect(reporter.auditSummary).toBeCalledWith(apiResponse.metadata); + }); +}); diff --git a/__tests__/fixtures/audit/private-package/audit-api-response.json b/__tests__/fixtures/audit/private-package/audit-api-response.json new file mode 100644 index 0000000000..e0d4605b3e --- /dev/null +++ b/__tests__/fixtures/audit/private-package/audit-api-response.json @@ -0,0 +1,77 @@ +{ + "actions": [ + { + "action": "install", + "module": "minimatch", + "target": "3.0.4", + "isMajor": false, + "resolves": [ + { + "id": 118, + "path": "minimatch", + "dev": false, + "optional": false, + "bundled": false + } + ] + } + ], + "advisories": { + "118": { + "findings": [ + { + "version": "3.0.0", + "paths": [ + "minimatch" + ], + "dev": false, + "optional": false, + "bundled": false + } + ], + "id": 118, + "created": "2016-05-25T16:37:20.000Z", + "updated": "2018-03-01T21:58:01.072Z", + "deleted": null, + "title": "Regular Expression Denial of Service", + "found_by": { + "name": "Nick Starke" + }, + "reported_by": { + "name": "Nick Starke" + }, + "module_name": "minimatch", + "cves": [ + "CVE-2016-10540" + ], + "vulnerable_versions": "<=3.0.1", + "patched_versions": ">=3.0.2", + "overview": "Affected versions of `minimatch` are vulnerable to regular expression denial of service attacks when user input is passed into the `pattern` argument of `minimatch(path, pattern)`.\n\n\n## Proof of Concept\n```\nvar minimatch = require(“minimatch”);\n\n// utility function for generating long strings\nvar genstr = function (len, chr) {\n var result = “”;\n for (i=0; i<=len; i++) {\n result = result + chr;\n }\n return result;\n}\n\nvar exploit = “[!” + genstr(1000000, “\\\\”) + “A”;\n\n// minimatch exploit.\nconsole.log(“starting minimatch”);\nminimatch(“foo”, exploit);\nconsole.log(“finishing minimatch”);\n```", + "recommendation": "Update to version 3.0.2 or later.", + "references": "", + "access": "public", + "severity": "high", + "cwe": "CWE-400", + "metadata": { + "module_type": "Multi.Library", + "exploitability": 4, + "affected_components": "Internal::Code::Function::minimatch({type:'args', key:0, vector:{type:'string'}})" + }, + "url": "https://nodesecurity.io/advisories/118" + } + }, + "muted": [], + "metadata": { + "vulnerabilities": { + "info": 0, + "low": 0, + "moderate": 0, + "high": 1, + "critical": 0 + }, + "dependencies": 5, + "devDependencies": 0, + "optionalDependencies": 0, + "totalDependencies": 5 + } +} diff --git a/__tests__/fixtures/audit/private-package/package.json b/__tests__/fixtures/audit/private-package/package.json new file mode 100644 index 0000000000..f16c191691 --- /dev/null +++ b/__tests__/fixtures/audit/private-package/package.json @@ -0,0 +1,6 @@ +{ + "private": true, + "dependencies": { + "left-pad": "^1.3.0" + } +} diff --git a/__tests__/fixtures/audit/private-package/yarn.lock b/__tests__/fixtures/audit/private-package/yarn.lock new file mode 100644 index 0000000000..9660884091 --- /dev/null +++ b/__tests__/fixtures/audit/private-package/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +left-pad@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" + integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== diff --git a/src/cli/commands/audit.js b/src/cli/commands/audit.js index b9faa70381..4505976f28 100644 --- a/src/cli/commands/audit.js +++ b/src/cli/commands/audit.js @@ -160,13 +160,18 @@ export default class Audit { _mapHoistedNodes(auditNode: AuditNode, hoistedNodes: HoistedTrees) { for (const node of hoistedNodes) { const pkg = node.manifest.pkg; + const requires = Object.assign({}, pkg.dependencies || {}, pkg.optionalDependencies || {}); + for (const name of Object.keys(requires)) { + if (!requires[name]) { + requires[name] = '*'; + } + } auditNode.dependencies[node.name] = { version: node.version, integrity: pkg._remote ? pkg._remote.integrity || '' : '', - requires: Object.assign({}, pkg.dependencies || {}, pkg.optionalDependencies || {}), + requires, dependencies: {}, }; - if (node.children) { this._mapHoistedNodes(auditNode.dependencies[node.name], node.children); } @@ -175,7 +180,7 @@ export default class Audit { _mapHoistedTreesToAuditTree(manifest: Object, hoistedTrees: HoistedTrees): AuditTree { const auditTree: AuditTree = { - name: manifest.name, + name: manifest.name || undefined, version: manifest.version || undefined, install: [], remove: [], From b62e9e4701bf8bc6e0fd4893513ba80ecedcf5b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Thu, 1 Nov 2018 20:18:58 -0700 Subject: [PATCH 04/13] Fixes the resolve shim for liftoff (#6623) * Fixes the resolve shim for liftoff * Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ src/util/generate-pnp-map-api.tpl.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91f609c174..83541734b9 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 +- Fixes Gulp when used with Plug'n'Play + + [#6623](https://github.com/yarnpkg/yarn/pull/6623) - [**Maël Nison**](https://twitter.com/arcanis) + - Fixes an issue with `yarn audit` when the root package was missing a name [#6611](https://github.com/yarnpkg/yarn/pull/6611) - [**Jack Zhao**](https://github.com/bugzpodder) diff --git a/src/util/generate-pnp-map-api.tpl.js b/src/util/generate-pnp-map-api.tpl.js index 693b82394a..6b744d13fc 100644 --- a/src/util/generate-pnp-map-api.tpl.js +++ b/src/util/generate-pnp-map-api.tpl.js @@ -748,7 +748,7 @@ exports.setupCompatibilityLayer = () => { // at all unless modulePath is set, which we cannot configure from any other way than through // the Liftoff pipeline (the key isn't whitelisted for env or cli options). - patchedModules.set(/^resolve$/, realResolve => { + patchedModules.set('resolve', realResolve => { const mustBeShimmed = caller => { const callerLocator = exports.findPackageLocator(caller); From 4177b081dcee74cd7385e1ce2922159513f5bee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Sat, 3 Nov 2018 12:42:08 -0700 Subject: [PATCH 05/13] Stop copying `.bin` folders (#6628) * Stops copying the .bin folder from the cache * Adds a test --- __tests__/commands/install/integration.js | 5 +++++ __tests__/fixtures/install/install-no-bin/package.json | 5 +++++ src/package-linker.js | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 __tests__/fixtures/install/install-no-bin/package.json diff --git a/__tests__/commands/install/integration.js b/__tests__/commands/install/integration.js index 60a6f4dcfb..cad6455f0e 100644 --- a/__tests__/commands/install/integration.js +++ b/__tests__/commands/install/integration.js @@ -48,6 +48,11 @@ async function mockConstants(base: Config, mocks: Object, cb: (config: Config) = beforeEach(request.__resetAuthedRequests); afterEach(request.__resetAuthedRequests); +test('install should not copy the .bin folders from the cache', () => + runInstall({}, 'install-no-bin', async config => { + expect(await fs.exists(`${config.cwd}/node_modules/is-pnp/.bin`)).toEqual(false); + })); + test('install should not hoist packages above their peer dependencies', () => runInstall({}, 'install-should-not-hoist-through-peer-deps', async config => { expect(await fs.exists(`${config.cwd}/node_modules/a/node_modules/c`)).toEqual(true); diff --git a/__tests__/fixtures/install/install-no-bin/package.json b/__tests__/fixtures/install/install-no-bin/package.json new file mode 100644 index 0000000000..5736570f54 --- /dev/null +++ b/__tests__/fixtures/install/install-no-bin/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "is-pnp": "^1.0.2" + } +} diff --git a/src/package-linker.js b/src/package-linker.js index c0f69d921a..463a9835ce 100644 --- a/src/package-linker.js +++ b/src/package-linker.js @@ -444,7 +444,7 @@ export default class PackageLinker { possibleExtraneous, artifactFiles, - ignoreBasenames: [constants.METADATA_FILENAME, constants.TARBALL_FILENAME], + ignoreBasenames: [constants.METADATA_FILENAME, constants.TARBALL_FILENAME, '.bin'], onStart: (num: number) => { tick = this.reporter.progress(num); From 4e3b2f6112edd4171768e0a94659acdb60d4af62 Mon Sep 17 00:00:00 2001 From: Yoad Snapir Date: Mon, 5 Nov 2018 14:17:13 +0200 Subject: [PATCH 06/13] fix: Use cmdshim instead of symlink on win32 in base-fetcher (#6621) * fix: Use cmdshim instead of symlink on win32 in base-fetcher * Update CHANGELOG * Bumps the cache key * Use cmdShim.ifExists to handle missing src like symlink (ignores) * Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ .../corrupted-meta-empty/.yarn-metadata.json | 0 .../corrupted-meta-not-existing/.gitkeep | 0 .../corrupted-meta-typo/.yarn-metadata.json | 0 .../good/node_modules/good/.yarn-metadata.json | 0 src/constants.js | 2 +- src/fetchers/base-fetcher.js | 13 ++++++++++++- 7 files changed, 17 insertions(+), 2 deletions(-) rename __tests__/fixtures/cache/corrupted/.yarn-cache/{v3 => v4}/corrupted-meta-empty/node_modules/corrupted-meta-empty/.yarn-metadata.json (100%) rename __tests__/fixtures/cache/corrupted/.yarn-cache/{v3 => v4}/corrupted-meta-not-existing/node_modules/corrupted-meta-not-existing/.gitkeep (100%) rename __tests__/fixtures/cache/corrupted/.yarn-cache/{v3 => v4}/corrupted-meta-typo/node_modules/corrupted-meta-typo/.yarn-metadata.json (100%) rename __tests__/fixtures/cache/corrupted/.yarn-cache/{v3 => v4}/good/node_modules/good/.yarn-metadata.json (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83541734b9..6fba204d69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa [#6611](https://github.com/yarnpkg/yarn/pull/6611) - [**Jack Zhao**](https://github.com/bugzpodder) +- Fixes an issue with how symlinks are setup into the cache on Windows + + [#6621](https://github.com/yarnpkg/yarn/pull/6621) - [**Yoad Snapir**](https://github.com/yoadsn) + ## 1.12.1 - Ensures the engine check is ran before showing the UI for `upgrade-interactive` diff --git a/__tests__/fixtures/cache/corrupted/.yarn-cache/v3/corrupted-meta-empty/node_modules/corrupted-meta-empty/.yarn-metadata.json b/__tests__/fixtures/cache/corrupted/.yarn-cache/v4/corrupted-meta-empty/node_modules/corrupted-meta-empty/.yarn-metadata.json similarity index 100% rename from __tests__/fixtures/cache/corrupted/.yarn-cache/v3/corrupted-meta-empty/node_modules/corrupted-meta-empty/.yarn-metadata.json rename to __tests__/fixtures/cache/corrupted/.yarn-cache/v4/corrupted-meta-empty/node_modules/corrupted-meta-empty/.yarn-metadata.json diff --git a/__tests__/fixtures/cache/corrupted/.yarn-cache/v3/corrupted-meta-not-existing/node_modules/corrupted-meta-not-existing/.gitkeep b/__tests__/fixtures/cache/corrupted/.yarn-cache/v4/corrupted-meta-not-existing/node_modules/corrupted-meta-not-existing/.gitkeep similarity index 100% rename from __tests__/fixtures/cache/corrupted/.yarn-cache/v3/corrupted-meta-not-existing/node_modules/corrupted-meta-not-existing/.gitkeep rename to __tests__/fixtures/cache/corrupted/.yarn-cache/v4/corrupted-meta-not-existing/node_modules/corrupted-meta-not-existing/.gitkeep diff --git a/__tests__/fixtures/cache/corrupted/.yarn-cache/v3/corrupted-meta-typo/node_modules/corrupted-meta-typo/.yarn-metadata.json b/__tests__/fixtures/cache/corrupted/.yarn-cache/v4/corrupted-meta-typo/node_modules/corrupted-meta-typo/.yarn-metadata.json similarity index 100% rename from __tests__/fixtures/cache/corrupted/.yarn-cache/v3/corrupted-meta-typo/node_modules/corrupted-meta-typo/.yarn-metadata.json rename to __tests__/fixtures/cache/corrupted/.yarn-cache/v4/corrupted-meta-typo/node_modules/corrupted-meta-typo/.yarn-metadata.json diff --git a/__tests__/fixtures/cache/corrupted/.yarn-cache/v3/good/node_modules/good/.yarn-metadata.json b/__tests__/fixtures/cache/corrupted/.yarn-cache/v4/good/node_modules/good/.yarn-metadata.json similarity index 100% rename from __tests__/fixtures/cache/corrupted/.yarn-cache/v3/good/node_modules/good/.yarn-metadata.json rename to __tests__/fixtures/cache/corrupted/.yarn-cache/v4/good/node_modules/good/.yarn-metadata.json diff --git a/src/constants.js b/src/constants.js index e93a098c59..cb4f587288 100644 --- a/src/constants.js +++ b/src/constants.js @@ -28,7 +28,7 @@ export const YARN_INSTALLER_MSI = 'https://yarnpkg.com/latest.msi'; export const SELF_UPDATE_VERSION_URL = 'https://yarnpkg.com/latest-version'; // cache version, bump whenever we make backwards incompatible changes -export const CACHE_VERSION = 3; +export const CACHE_VERSION = 4; // lockfile version, bump whenever we make backwards incompatible changes export const LOCKFILE_VERSION = 1; diff --git a/src/fetchers/base-fetcher.js b/src/fetchers/base-fetcher.js index 94b43fbea4..e5e7b38aef 100644 --- a/src/fetchers/base-fetcher.js +++ b/src/fetchers/base-fetcher.js @@ -9,7 +9,9 @@ import normalizeManifest from '../util/normalize-manifest/index.js'; import {makePortableProxyScript} from '../util/portable-script.js'; import * as constants from '../constants.js'; import * as fs from '../util/fs.js'; +import lockMutex from '../util/mutex.js'; +const cmdShim = require('@zkochan/cmd-shim'); const path = require('path'); export default class BaseFetcher { @@ -77,7 +79,16 @@ export default class BaseFetcher { } await fs.mkdirp(binDest); - await fs.symlink(src, `${binDest}/${binName}`); + if (process.platform === 'win32') { + const unlockMutex = await lockMutex(src); + try { + await cmdShim.ifExists(src, `${binDest}/${binName}`); + } finally { + unlockMutex(); + } + } else { + await fs.symlink(src, `${binDest}/${binName}`); + } } } From 7977c422ed2007ab9902b496cf85038860bbdb02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Mon, 5 Nov 2018 16:40:46 +0000 Subject: [PATCH 07/13] Uses NODE_OPTIONS with PnP instead of CLI args (#6629) * Uses NODE_OPTIONS when spawning a process * Adds an additional test * Update CHANGELOG.md --- CHANGELOG.md | 8 +++ .../pkg-tests/pkg-tests-specs/sources/pnp.js | 69 +++++++++++++++++++ packages/pkg-tests/yarn.test.js | 3 +- src/cli/commands/node.js | 4 +- src/util/execute-lifecycle-script.js | 19 +++-- 5 files changed, 90 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fba204d69..3e26bfff41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa ## Master +**Important:** This release contains a cache bump. It will cause the very first install following the upgrade to take slightly more time, especially if you don't use the [Offline Mirror](https://yarnpkg.com/blog/2016/11/24/offline-mirror/) feature. After that everything will be back to normal. + +- Uses `NODE_OPTIONS` to instruct Node to load the PnP hook, instead of raw CLI arguments + + **Caveat:** This change might cause issues for PnP users having a space inside their cwd (cf [nodejs/node#24065](https://github.com/nodejs/node/pull/24065)) + + [#6479](https://github.com/yarnpkg/yarn/pull/6629) - [**Maël Nison**](https://twitter.com/arcanis) + - Fixes Gulp when used with Plug'n'Play [#6623](https://github.com/yarnpkg/yarn/pull/6623) - [**Maël Nison**](https://twitter.com/arcanis) diff --git a/packages/pkg-tests/pkg-tests-specs/sources/pnp.js b/packages/pkg-tests/pkg-tests-specs/sources/pnp.js index ec95577320..487669f959 100644 --- a/packages/pkg-tests/pkg-tests-specs/sources/pnp.js +++ b/packages/pkg-tests/pkg-tests-specs/sources/pnp.js @@ -1340,5 +1340,74 @@ module.exports = makeTemporaryEnv => { }, ), ); + + test( + `it should not break spawning new Node processes ('node' command)`, + makeTemporaryEnv( + { + dependencies: {[`no-deps`]: `1.0.0`}, + }, + {plugNPlay: true}, + async ({path, run, source}) => { + await run(`install`); + + await writeFile(`${path}/script.js`, `console.log(JSON.stringify(require('no-deps')))`); + + await expect( + source( + `JSON.parse(require('child_process').execFileSync(process.execPath, [${JSON.stringify( + `${path}/script.js`, + )}]).toString())`, + ), + ).resolves.toMatchObject({ + name: `no-deps`, + version: `1.0.0`, + }); + }, + ), + ); + + test( + `it should not break spawning new Node processes ('run' command)`, + makeTemporaryEnv( + { + dependencies: {[`no-deps`]: `1.0.0`}, + scripts: {[`script`]: `node main.js`}, + }, + {plugNPlay: true}, + async ({path, run, source}) => { + await run(`install`); + + await writeFile(`${path}/sub.js`, `console.log(JSON.stringify(require('no-deps')))`); + await writeFile( + `${path}/main.js`, + `console.log(require('child_process').execFileSync(process.execPath, [${JSON.stringify( + `${path}/sub.js`, + )}]).toString())`, + ); + + expect(JSON.parse((await run(`run`, `script`)).stdout)).toMatchObject({ + name: `no-deps`, + version: `1.0.0`, + }); + }, + ), + ); + + test( + `it should properly forward the NODE_OPTIONS environment variable`, + makeTemporaryEnv({}, {plugNPlay: true}, async ({path, run, source}) => { + await run(`install`); + + await writeFile(`${path}/foo.js`, `console.log(42);`); + + await expect( + run(`node`, `-e`, `console.log(21);`, {env: {NODE_OPTIONS: `--require ${path}/foo`}}), + ).resolves.toMatchObject({ + // Note that '42' is present twice: the first one because Node executes Yarn, and the second one because Yarn spawns Node + stdout: `42\n42\n21\n`, + }); + }), + ); }); }; diff --git a/packages/pkg-tests/yarn.test.js b/packages/pkg-tests/yarn.test.js index 25b5d968f0..284b57ee61 100644 --- a/packages/pkg-tests/yarn.test.js +++ b/packages/pkg-tests/yarn.test.js @@ -21,7 +21,7 @@ const pkgDriver = generatePkgDriver({ async runDriver( path, [command, ...args], - {cwd, projectFolder, registryUrl, plugNPlay, plugnplayShebang, plugnplayBlacklist}, + {cwd, projectFolder, registryUrl, plugNPlay, plugnplayShebang, plugnplayBlacklist, env}, ) { let beforeArgs = []; let middleArgs = []; @@ -49,6 +49,7 @@ const pkgDriver = generatePkgDriver({ [`PATH`]: `${path}/bin${delimiter}${process.env.PATH}`, }, plugNPlay ? {[`YARN_PLUGNPLAY_OVERRIDE`]: plugNPlay ? `1` : `0`} : {}, + env, ), cwd: cwd || path, }, diff --git a/src/cli/commands/node.js b/src/cli/commands/node.js index a8c752c1a1..1fb70fd1ee 100644 --- a/src/cli/commands/node.js +++ b/src/cli/commands/node.js @@ -21,14 +21,16 @@ export function hasWrapper(commander: Object, args: Array): boolean { export async function run(config: Config, reporter: Reporter, flags: Object, args: Array): Promise { const pnpPath = `${config.lockfileFolder}/${PNP_FILENAME}`; + let nodeOptions = process.env.NODE_OPTIONS || ''; if (await fs.exists(pnpPath)) { - args = ['-r', pnpPath, ...args]; + nodeOptions += ` --require ${pnpPath}`; } try { await child.spawn(NODE_BIN_PATH, args, { stdio: 'inherit', cwd: flags.into || config.cwd, + env: {...process.env, NODE_OPTIONS: nodeOptions}, }); } catch (err) { throw err; diff --git a/src/util/execute-lifecycle-script.js b/src/util/execute-lifecycle-script.js index 82c01acae3..7401cc10e8 100644 --- a/src/util/execute-lifecycle-script.js +++ b/src/util/execute-lifecycle-script.js @@ -26,14 +26,6 @@ export const IGNORE_MANIFEST_KEYS: Set = new Set(['readme', 'notice', 'l // See https://github.com/yarnpkg/yarn/issues/2286. const IGNORE_CONFIG_KEYS = ['lastUpdateCheck']; -async function getPnpParameters(config: Config): Promise> { - if (await fs.exists(`${config.lockfileFolder}/${constants.PNP_FILENAME}`)) { - return ['-r', `${config.lockfileFolder}/${constants.PNP_FILENAME}`]; - } else { - return []; - } -} - let wrappersFolder = null; export async function getWrappersFolder(config: Config): Promise { @@ -45,7 +37,6 @@ export async function getWrappersFolder(config: Config): Promise { await makePortableProxyScript(process.execPath, wrappersFolder, { proxyBasename: 'node', - prependArguments: [...(await getPnpParameters(config))], }); await makePortableProxyScript(process.execPath, wrappersFolder, { @@ -212,8 +203,9 @@ export async function makeEnv( } } - if (await fs.exists(`${config.lockfileFolder}/${constants.PNP_FILENAME}`)) { - const pnpApi = dynamicRequire(`${config.lockfileFolder}/${constants.PNP_FILENAME}`); + const pnpFile = `${config.lockfileFolder}/${constants.PNP_FILENAME}`; + if (await fs.exists(pnpFile)) { + const pnpApi = dynamicRequire(pnpFile); const packageLocator = pnpApi.findPackageLocator(`${config.cwd}/`); const packageInformation = pnpApi.getPackageInformation(packageLocator); @@ -227,6 +219,11 @@ export async function makeEnv( pathParts.unshift(`${dependencyInformation.packageLocation}/.bin`); } + + // Note that NODE_OPTIONS doesn't support any style of quoting its arguments at the moment + // For this reason, it won't work if the user has a space inside its $PATH + env.NODE_OPTIONS = env.NODE_OPTIONS || ''; + env.NODE_OPTIONS += ` --require ${pnpFile}`; } pathParts.unshift(await getWrappersFolder(config)); From 5539fa23d1495b9aaa2409376dae2275aa0e725e Mon Sep 17 00:00:00 2001 From: Philipp Feigl Date: Mon, 5 Nov 2018 17:44:47 +0100 Subject: [PATCH 08/13] Fixes potential freeze on win+node10 interactive upgrades (#5949) (#6635) * Fixes potential freeze on win+node10 interactive upgrades (#5949) There is a potential freeze when running interactive upgrades after selecting the options. This boiles down to a problem in the `inquirer` library which is used internally to provide the possible options. Updating `inquirer`to the latest version fixes the problem. * Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ package.json | 2 +- yarn.lock | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e26bfff41..0b29cca30b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,10 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa - Fixes an issue with how symlinks are setup into the cache on Windows [#6621](https://github.com/yarnpkg/yarn/pull/6621) - [**Yoad Snapir**](https://github.com/yoadsn) + +- Upgrades `enquirer`, fixing `upgrade-interactive` for users using both Node 10 and Windows + + [#6635](https://github.com/yarnpkg/yarn/pull/6635) - [**Philipp Feigl**](https://github.com/pfeigl) ## 1.12.1 diff --git a/package.json b/package.json index a3265afef6..dfafabcdbc 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "hash-for-dep": "^1.2.3", "imports-loader": "^0.8.0", "ini": "^1.3.4", - "inquirer": "^3.0.1", + "inquirer": "^6.2.0", "invariant": "^2.2.0", "is-builtin-module": "^2.0.0", "is-ci": "^1.0.10", diff --git a/yarn.lock b/yarn.lock index da31a9ae85..db8ff70842 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1699,6 +1699,11 @@ chardet@^0.4.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + chokidar@^2.0.0, chokidar@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" @@ -2879,6 +2884,15 @@ external-editor@^2.0.1, external-editor@^2.0.4: iconv-lite "^0.4.17" tmp "^0.0.33" +external-editor@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" + integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" @@ -3744,6 +3758,13 @@ iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + ieee754@^1.1.4: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" @@ -3849,7 +3870,7 @@ inquirer@3.0.6: strip-ansi "^3.0.0" through "^2.3.6" -inquirer@^3.0.1, inquirer@^3.0.6: +inquirer@^3.0.6: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== @@ -3869,6 +3890,25 @@ inquirer@^3.0.1, inquirer@^3.0.6: strip-ansi "^4.0.0" through "^2.3.6" +inquirer@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" + integrity sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg== + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.0" + figures "^2.0.0" + lodash "^4.17.10" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.1.0" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + interpret@^1.0.0, interpret@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" @@ -6529,6 +6569,13 @@ rx@^4.1.0: resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= +rxjs@^6.1.0: + version "6.3.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" + integrity sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw== + dependencies: + tslib "^1.9.0" + safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -7263,6 +7310,11 @@ trim-right@^1.0.1: resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= +tslib@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== + tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" From a40f3fc981355878f855de6b4110647ecf6d0c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Mon, 5 Nov 2018 17:02:07 +0000 Subject: [PATCH 09/13] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b29cca30b..5d3561550d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,7 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa [#6621](https://github.com/yarnpkg/yarn/pull/6621) - [**Yoad Snapir**](https://github.com/yoadsn) -- Upgrades `enquirer`, fixing `upgrade-interactive` for users using both Node 10 and Windows +- Upgrades `inquirer`, fixing `upgrade-interactive` for users using both Node 10 and Windows [#6635](https://github.com/yarnpkg/yarn/pull/6635) - [**Philipp Feigl**](https://github.com/pfeigl) From 85660f79bfad96af843dcd3d87ed75e81c527c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Tue, 6 Nov 2018 15:16:50 +0000 Subject: [PATCH 10/13] Precompiles inquirer for Node 4 compat (#6640) --- scripts/build-webpack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-webpack.js b/scripts/build-webpack.js index dc7b68ffae..e310c777f7 100755 --- a/scripts/build-webpack.js +++ b/scripts/build-webpack.js @@ -121,7 +121,7 @@ const compilerLegacy = webpack({ rules: [ { test: /\.js$/, - exclude: /node_modules/, + exclude: /node_modules\/(?!inquirer)/, use: [ { loader:'babel-loader', From 1ceabe85b1d740004941e4bdac838d4ad2b2ff01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Tue, 6 Nov 2018 15:59:52 +0000 Subject: [PATCH 11/13] Tries a fix for Windows --- scripts/build-webpack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-webpack.js b/scripts/build-webpack.js index e310c777f7..deaa903b70 100755 --- a/scripts/build-webpack.js +++ b/scripts/build-webpack.js @@ -121,7 +121,7 @@ const compilerLegacy = webpack({ rules: [ { test: /\.js$/, - exclude: /node_modules\/(?!inquirer)/, + exclude: /node_modules[\\\/](?!inquirer)/, use: [ { loader:'babel-loader', From 124a2ef64381d2551aa8b1fa8d871862c12fa822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Wed, 7 Nov 2018 12:32:36 +0000 Subject: [PATCH 12/13] Exposes pnpapi through resolveToUnqualified (#6643) * Exposes pnpapi through resolveToUnqualified * Update CHANGELOG.md --- CHANGELOG.md | 6 +++++- .../pkg-tests-specs/sources/pnpapi-v1.js | 20 +++++++++++++++---- src/util/generate-pnp-map-api.tpl.js | 7 +++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d3561550d..456a356572 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,11 +27,15 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa - Fixes an issue with how symlinks are setup into the cache on Windows [#6621](https://github.com/yarnpkg/yarn/pull/6621) - [**Yoad Snapir**](https://github.com/yoadsn) - + - Upgrades `inquirer`, fixing `upgrade-interactive` for users using both Node 10 and Windows [#6635](https://github.com/yarnpkg/yarn/pull/6635) - [**Philipp Feigl**](https://github.com/pfeigl) +- Exposes the path to the PnP file using `require.resolve('pnpapi')` + + [#6643](https://github.com/yarnpkg/yarn/pull/6643) - [**Maël Nison**](https://twitter.com/arcanis) + ## 1.12.1 - Ensures the engine check is ran before showing the UI for `upgrade-interactive` diff --git a/packages/pkg-tests/pkg-tests-specs/sources/pnpapi-v1.js b/packages/pkg-tests/pkg-tests-specs/sources/pnpapi-v1.js index e56fb700e8..56a6aba36a 100644 --- a/packages/pkg-tests/pkg-tests-specs/sources/pnpapi-v1.js +++ b/packages/pkg-tests/pkg-tests-specs/sources/pnpapi-v1.js @@ -1,9 +1,10 @@ +const {normalize} = require('path'); const {fs: {writeFile, writeJson}} = require('pkg-tests-core'); module.exports = makeTemporaryEnv => { describe(`Plug'n'Play API (v1)`, () => { test( - `it should expost VERSIONS`, + `it should expose VERSIONS`, makeTemporaryEnv({}, {plugNPlay: true}, async ({path, run, source}) => { await run(`install`); @@ -12,7 +13,7 @@ module.exports = makeTemporaryEnv => { ); test( - `it should expost resolveToUnqualified`, + `it should expose resolveToUnqualified`, makeTemporaryEnv({}, {plugNPlay: true}, async ({path, run, source}) => { await run(`install`); @@ -21,7 +22,7 @@ module.exports = makeTemporaryEnv => { ); test( - `it should expost resolveToUnqualified`, + `it should expose resolveToUnqualified`, makeTemporaryEnv({}, {plugNPlay: true}, async ({path, run, source}) => { await run(`install`); @@ -30,7 +31,7 @@ module.exports = makeTemporaryEnv => { ); test( - `it should expost resolveToUnqualified`, + `it should expose resolveToUnqualified`, makeTemporaryEnv({}, {plugNPlay: true}, async ({path, run, source}) => { await run(`install`); @@ -39,6 +40,17 @@ module.exports = makeTemporaryEnv => { ); describe(`resolveRequest`, () => { + test( + `it should return the path to the PnP file for when 'pnpapi' is requested`, + makeTemporaryEnv({}, {plugNPlay: true}, async ({path, run, source}) => { + await run(`install`); + + await expect(source(`require('pnpapi').resolveRequest('pnpapi', '${path}/')`)).resolves.toEqual( + normalize(`${path}/.pnp.js`), + ); + }), + ); + test( `it should return null for builtins`, makeTemporaryEnv({}, {plugNPlay: true}, async ({path, run, source}) => { diff --git a/src/util/generate-pnp-map-api.tpl.js b/src/util/generate-pnp-map-api.tpl.js index 6b744d13fc..306db98d79 100644 --- a/src/util/generate-pnp-map-api.tpl.js +++ b/src/util/generate-pnp-map-api.tpl.js @@ -13,6 +13,7 @@ const StringDecoder = require('string_decoder'); const ignorePattern = $$BLACKLIST ? new RegExp($$BLACKLIST) : null; +const pnpFile = path.resolve(__dirname, __filename); const builtinModules = new Set(Module.builtinModules || Object.keys(process.binding('natives'))); const topLevelLocator = {name: null, reference: null}; @@ -313,6 +314,12 @@ exports.getPackageInformation = function getPackageInformation({name, reference} */ exports.resolveToUnqualified = function resolveToUnqualified(request, issuer, {considerBuiltins = true} = {}) { + // The 'pnpapi' request is reserved and will always return the path to the PnP file, from everywhere + + if (request === `pnpapi`) { + return pnpFile; + } + // Bailout if the request is a native module if (considerBuiltins && builtinModules.has(request)) { From f8e42c563f7c10adb5f53afc59104f541e145176 Mon Sep 17 00:00:00 2001 From: Jeff Valore Date: Wed, 7 Nov 2018 07:34:49 -0500 Subject: [PATCH 13/13] fix(audit) Report vulnerabilities in workspace package dependencies (#6639) * added failing test for #6625 * fix(audit): Add workspaceAggregator dependencies to root manifest to be audited. This change takes the packages that are included as part of the workspace and adds them to what is sent to the npm audit api. fixes #6625 * update changelog for PR 6639 --- CHANGELOG.md | 4 ++ __tests__/commands/audit.js | 60 ++++++++++++++++++- .../audit/workspace/audit-api-response.json | 18 ++++++ .../fixtures/audit/workspace/package.json | 8 +++ .../workspace/packages/prj1/package.json | 8 +++ __tests__/fixtures/audit/workspace/yarn.lock | 28 +++++++++ src/cli/commands/audit.js | 15 +++++ 7 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 __tests__/fixtures/audit/workspace/audit-api-response.json create mode 100644 __tests__/fixtures/audit/workspace/package.json create mode 100644 __tests__/fixtures/audit/workspace/packages/prj1/package.json create mode 100644 __tests__/fixtures/audit/workspace/yarn.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index 456a356572..dc78f9d4d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa **Important:** This release contains a cache bump. It will cause the very first install following the upgrade to take slightly more time, especially if you don't use the [Offline Mirror](https://yarnpkg.com/blog/2016/11/24/offline-mirror/) feature. After that everything will be back to normal. +- Fixes an issue with `yarn audit` when using workspaces + + [#6625](https://github.com/yarnpkg/yarn/pull/6639) - [**Jeff Valore**](https://twitter.com/codingwithspike) + - Uses `NODE_OPTIONS` to instruct Node to load the PnP hook, instead of raw CLI arguments **Caveat:** This change might cause issues for PnP users having a space inside their cwd (cf [nodejs/node#24065](https://github.com/nodejs/node/pull/24065)) diff --git a/__tests__/commands/audit.js b/__tests__/commands/audit.js index 9ba7c8b4c4..c796527a2e 100644 --- a/__tests__/commands/audit.js +++ b/__tests__/commands/audit.js @@ -105,7 +105,7 @@ test('calls reporter auditAdvisory with correct data', () => { }); }); -// *** Test temporarily removed due to inability to correctly puggest actions to the user. +// *** Test temporarily removed due to inability to correctly suggest actions to the user. // test('calls reporter auditAction with correct data', () => { // return runAudit([], {}, 'single-vulnerable-dep-installed', (config, reporter) => { // const apiResponse = getAuditResponse(config); @@ -162,3 +162,61 @@ test('calls reporter auditSummary with correct data for private package', () => expect(reporter.auditSummary).toBeCalledWith(apiResponse.metadata); }); }); + +test.concurrent('sends correct dependency map to audit api for workspaces.', () => { + const expectedApiPost = { + dependencies: { + 'balanced-match': { + dependencies: {}, + integrity: 'sha1-ibTRmasr7kneFk6gK4nORi1xt2c=', + requires: {}, + version: '1.0.0', + }, + 'brace-expansion': { + dependencies: {}, + integrity: 'sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==', + requires: { + 'balanced-match': '^1.0.0', + 'concat-map': '0.0.1', + }, + version: '1.1.11', + }, + 'concat-map': { + dependencies: {}, + integrity: 'sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=', + requires: {}, + version: '0.0.1', + }, + minimatch: { + dependencies: {}, + integrity: 'sha1-UjYVelHk8ATBd/s8Un/33Xjw74M=', + requires: { + 'brace-expansion': '^1.0.0', + }, + version: '3.0.0', + }, + prj1: { + dependencies: {}, + integrity: '', + requires: { + minimatch: '3.0.0', + }, + version: '0.0.0', + }, + }, + install: [], + metadata: {}, + name: 'yarn-test', + remove: [], + requires: { + prj1: '0.0.0', + }, + version: '1.0.0', + }; + + return runAudit([], {}, 'workspace', async config => { + const calledWithPipe = config.requestManager.request.mock.calls[0][0].body; + const calledWith = JSON.parse(await gunzip(calledWithPipe)); + expect(calledWith).toEqual(expectedApiPost); + }); +}); diff --git a/__tests__/fixtures/audit/workspace/audit-api-response.json b/__tests__/fixtures/audit/workspace/audit-api-response.json new file mode 100644 index 0000000000..c9171e2624 --- /dev/null +++ b/__tests__/fixtures/audit/workspace/audit-api-response.json @@ -0,0 +1,18 @@ +{ + "actions": [], + "advisories": {}, + "muted": [], + "metadata": { + "vulnerabilities": { + "info": 0, + "low": 0, + "moderate": 0, + "high": 0, + "critical": 0 + }, + "dependencies": 0, + "devDependencies": 0, + "optionalDependencies": 0, + "totalDependencies": 0 + } +} diff --git a/__tests__/fixtures/audit/workspace/package.json b/__tests__/fixtures/audit/workspace/package.json new file mode 100644 index 0000000000..828404e8b1 --- /dev/null +++ b/__tests__/fixtures/audit/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "yarn-test", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "private": true, + "workspaces": ["packages/*"] +} diff --git a/__tests__/fixtures/audit/workspace/packages/prj1/package.json b/__tests__/fixtures/audit/workspace/packages/prj1/package.json new file mode 100644 index 0000000000..32af682e2f --- /dev/null +++ b/__tests__/fixtures/audit/workspace/packages/prj1/package.json @@ -0,0 +1,8 @@ +{ + "name": "prj1", + "private": true, + "version": "0.0.0", + "dependencies": { + "minimatch": "3.0.0" + } +} diff --git a/__tests__/fixtures/audit/workspace/yarn.lock b/__tests__/fixtures/audit/workspace/yarn.lock new file mode 100644 index 0000000000..5e2aa34974 --- /dev/null +++ b/__tests__/fixtures/audit/workspace/yarn.lock @@ -0,0 +1,28 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.0.0: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +minimatch@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.0.tgz#5236157a51e4f004c177fb3c527ff7dd78f0ef83" + integrity sha1-UjYVelHk8ATBd/s8Un/33Xjw74M= + dependencies: + brace-expansion "^1.0.0" diff --git a/src/cli/commands/audit.js b/src/cli/commands/audit.js index 4505976f28..14c20d4a1f 100644 --- a/src/cli/commands/audit.js +++ b/src/cli/commands/audit.js @@ -229,12 +229,27 @@ export default class Audit { return responseJson; } + _insertWorkspacePackagesIntoManifest(manifest: Object, resolver: PackageResolver) { + if (resolver.workspaceLayout) { + const workspaceAggregatorName = resolver.workspaceLayout.virtualManifestName; + const workspaceManifest = resolver.workspaceLayout.workspaces[workspaceAggregatorName].manifest; + + manifest.dependencies = Object.assign(manifest.dependencies || {}, workspaceManifest.dependencies); + manifest.devDependencies = Object.assign(manifest.devDependencies || {}, workspaceManifest.devDependencies); + manifest.optionalDependencies = Object.assign( + manifest.optionalDependencies || {}, + workspaceManifest.optionalDependencies, + ); + } + } + async performAudit( manifest: Object, resolver: PackageResolver, linker: PackageLinker, patterns: Array, ): Promise { + this._insertWorkspacePackagesIntoManifest(manifest, resolver); const hoistedTrees = await hoistedTreeBuilder(resolver, linker, patterns); const auditTree = this._mapHoistedTreesToAuditTree(manifest, hoistedTrees); this.auditData = await this._fetchAudit(auditTree);