From 1a209989bc21f50b49b9a695b687cbcbd8b74abf Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Thu, 27 Sep 2018 11:30:04 +0200
Subject: [PATCH] feat: yarn integrity switching (#2567)

Detects if `yarn.lock` contains `integrity` fields already and if so then runs `yarn` using v1.10.1 instead of the default v1.9.4.
---
 lib/manager/npm/extract/locked-versions.js  | 4 ++++
 lib/manager/npm/extract/yarn.js             | 4 ++++
 lib/manager/npm/post-update/index.js        | 2 +-
 lib/manager/npm/post-update/yarn.js         | 8 +++++++-
 package.json                                | 3 ++-
 test/workers/branch/lock-files/yarn.spec.js | 8 +++-----
 yarn.lock                                   | 5 +++++
 7 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/lib/manager/npm/extract/locked-versions.js b/lib/manager/npm/extract/locked-versions.js
index 32921c1823..f1325d7c1a 100644
--- a/lib/manager/npm/extract/locked-versions.js
+++ b/lib/manager/npm/extract/locked-versions.js
@@ -21,6 +21,10 @@ async function getLockedVersions(packageFiles) {
         dep.lockedVersion =
           lockFileCache[yarnLock][`${dep.depName}@${dep.currentValue}`];
       }
+      // istanbul ignore if
+      if (lockFileCache[yarnLock]['@renovate_yarn_integrity']) {
+        packageFile.yarnIntegrity = true;
+      }
     } else if (npmLock) {
       logger.debug({ npmLock }, 'npm lockfile');
       if (!lockFileCache[npmLock]) {
diff --git a/lib/manager/npm/extract/yarn.js b/lib/manager/npm/extract/yarn.js
index 8bf56b0162..e9bf2937b7 100644
--- a/lib/manager/npm/extract/yarn.js
+++ b/lib/manager/npm/extract/yarn.js
@@ -20,6 +20,10 @@ async function getYarnLock(filePath) {
     for (const [entry, val] of Object.entries(yarnLockParsed.object)) {
       logger.trace({ entry, version: val.version });
       lockFile[entry] = val.version;
+      // istanbul ignore if
+      if (val.integrity) {
+        lockFile['@renovate_yarn_integrity'] = true;
+      }
     }
     return lockFile;
   } catch (err) {
diff --git a/lib/manager/npm/post-update/index.js b/lib/manager/npm/post-update/index.js
index 347c9a4366..106b91f715 100644
--- a/lib/manager/npm/post-update/index.js
+++ b/lib/manager/npm/post-update/index.js
@@ -419,7 +419,7 @@ async function getAdditionalFiles(config, packageFiles) {
     const res = await yarn.generateLockFile(
       upath.join(config.localDir, lockFileDir),
       env,
-      config.binarysource
+      config
     );
     if (res.error) {
       // istanbul ignore if
diff --git a/lib/manager/npm/post-update/yarn.js b/lib/manager/npm/post-update/yarn.js
index c8f80be8b9..bf87272dae 100644
--- a/lib/manager/npm/post-update/yarn.js
+++ b/lib/manager/npm/post-update/yarn.js
@@ -7,7 +7,8 @@ module.exports = {
   generateLockFile,
 };
 
-async function generateLockFile(cwd, env, binarySource) {
+async function generateLockFile(cwd, env, config = {}) {
+  const { binarySource, yarnIntegrity } = config;
   logger.debug(`Spawning yarn install to create ${cwd}/yarn.lock`);
   let lockFile = null;
   let stdout;
@@ -24,6 +25,11 @@ async function generateLockFile(cwd, env, binarySource) {
         'bin/yarn.js'
       );
       cmd = `node ${installedPath}`;
+      // istanbul ignore if
+      if (yarnIntegrity) {
+        logger.info('Using yarn@1.10 for install');
+        cmd = cmd.replace('node_modules/yarn/', 'node_modules/yarn110/');
+      }
     } catch (localerr) {
       logger.debug('No locally installed yarn found');
       // Look inside globally installed renovate
diff --git a/package.json b/package.json
index 7c5a82c56d..43edc3c58c 100644
--- a/package.json
+++ b/package.json
@@ -120,7 +120,8 @@
     "validator": "10.8.0",
     "vso-node-api": "6.5.0",
     "www-authenticate": "0.6.2",
-    "yarn": "1.9.4"
+    "yarn": "1.9.4",
+    "yarn110": "npm:yarn@1.10.1"
   },
   "devDependencies": {
     "babel-plugin-transform-object-rest-spread": "6.26.0",
diff --git a/test/workers/branch/lock-files/yarn.spec.js b/test/workers/branch/lock-files/yarn.spec.js
index 3e442cb934..6f487f9c43 100644
--- a/test/workers/branch/lock-files/yarn.spec.js
+++ b/test/workers/branch/lock-files/yarn.spec.js
@@ -87,11 +87,9 @@ describe('generateLockFile', () => {
       stderror: '',
     });
     fs.readFile = jest.fn(() => 'package-lock-contents');
-    const res = await yarnHelper.generateLockFile(
-      'some-dir',
-      undefined,
-      'global'
-    );
+    const res = await yarnHelper.generateLockFile('some-dir', undefined, {
+      binarySource: 'global',
+    });
     expect(fs.readFile.mock.calls.length).toEqual(1);
     expect(res.lockFile).toEqual('package-lock-contents');
   });
diff --git a/yarn.lock b/yarn.lock
index f85bd8f526..e6df1dd12e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9206,6 +9206,11 @@ yargs@~3.10.0:
     decamelize "^1.0.0"
     window-size "0.1.0"
 
+"yarn110@npm:yarn@1.10.1":
+  version "1.10.1"
+  resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.10.1.tgz#b792ba28f050ae94cd7e719dbca80639d70da76f"
+  integrity sha512-EH0H1fyfFxkE4UpG4b+VCaVY4I488I2EyQNmGjGGKmvsSIb0G3b+1IcfGYPI2gqa1du43g4ZA3jH8fXlq6oVxg==
+
 yarn@1.9.4:
   version "1.9.4"
   resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.9.4.tgz#3b82d8446b652775723900b470d966861976924b"
-- 
GitLab