From 163ce43a273dc40c8217143c57d1e570f2e95901 Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Mon, 25 Dec 2017 17:10:20 +0100
Subject: [PATCH] feat: update yarn resolutions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Detect if the upgraded dependency was already in “resolutions” and update it too if it was an exact match. Warn if it was not.

Closes #1318
---
 lib/manager/npm/update.js                    | 41 ++++++++++++++++++++
 test/_fixtures/package-json/inputs/01.json   |  3 ++
 test/_fixtures/package-json/outputs/011.json |  3 ++
 test/_fixtures/package-json/outputs/012.json |  3 ++
 test/_fixtures/package-json/outputs/013.json |  3 ++
 test/manager/npm/update.spec.js              | 10 +++++
 6 files changed, 63 insertions(+)

diff --git a/lib/manager/npm/update.js b/lib/manager/npm/update.js
index fba5a64009..61e6212e2e 100644
--- a/lib/manager/npm/update.js
+++ b/lib/manager/npm/update.js
@@ -51,6 +51,47 @@ function setNewValue(currentFileContent, depType, depName, newVersion) {
       );
       return currentFileContent;
     }
+    if (
+      parsedContents &&
+      parsedContents.resolutions &&
+      parsedContents.resolutions[depName]
+    ) {
+      if (parsedContents.resolutions[depName] === oldVersion) {
+        // Update the file = this is what we want
+        parsedContents.resolutions[depName] = newVersion;
+        // Look for the old version number
+        const oldResolution = `"${oldVersion}"`;
+        const newResolution = `"${newVersion}"`;
+        // Skip ahead to depType section
+        searchIndex = newFileContent.indexOf(`"resolutions"`);
+        logger.debug(`Starting search at index ${searchIndex}`);
+        // Iterate through the rest of the file
+        for (; searchIndex < newFileContent.length; searchIndex += 1) {
+          // First check if we have a hit for the old version
+          if (matchAt(newFileContent, searchIndex, oldResolution)) {
+            logger.debug(`Found match at index ${searchIndex}`);
+            // Now test if the result matches
+            const testContent = replaceAt(
+              newFileContent,
+              searchIndex,
+              oldResolution,
+              newResolution
+            );
+            // Compare the parsed JSON structure of old and new
+            if (_.isEqual(parsedContents, JSON.parse(testContent))) {
+              newFileContent = testContent;
+              break;
+            }
+          }
+        }
+      } else {
+        // istanbul ignore next
+        logger.warn(
+          { parsedContents },
+          'Upgraded dependency exists in yarn resolutions but is different version'
+        );
+      }
+    }
     return newFileContent;
   } catch (err) {
     logger.info({ err }, 'setNewValue error');
diff --git a/test/_fixtures/package-json/inputs/01.json b/test/_fixtures/package-json/inputs/01.json
index 7677886187..6d8aab96b7 100644
--- a/test/_fixtures/package-json/inputs/01.json
+++ b/test/_fixtures/package-json/inputs/01.json
@@ -23,6 +23,9 @@
     "angular-sanitize":  "1.5.8",
     "@angular/core": "4.0.0-beta.1"
   },
+  "resolutions": {
+    "config": "1.21.0"
+  },
   "homepage": "https://keylocation.sg",
   "keywords": [
     "Key Location",
diff --git a/test/_fixtures/package-json/outputs/011.json b/test/_fixtures/package-json/outputs/011.json
index fe8a992cd4..e833043686 100644
--- a/test/_fixtures/package-json/outputs/011.json
+++ b/test/_fixtures/package-json/outputs/011.json
@@ -23,6 +23,9 @@
     "angular-sanitize":  "1.5.8",
     "@angular/core": "4.0.0-beta.1"
   },
+  "resolutions": {
+    "config": "1.21.0"
+  },
   "homepage": "https://keylocation.sg",
   "keywords": [
     "Key Location",
diff --git a/test/_fixtures/package-json/outputs/012.json b/test/_fixtures/package-json/outputs/012.json
index 7778ef556c..f4454edfdd 100644
--- a/test/_fixtures/package-json/outputs/012.json
+++ b/test/_fixtures/package-json/outputs/012.json
@@ -23,6 +23,9 @@
     "angular-sanitize":  "1.5.8",
     "@angular/core": "4.0.0-beta.1"
   },
+  "resolutions": {
+    "config": "1.21.0"
+  },
   "homepage": "https://keylocation.sg",
   "keywords": [
     "Key Location",
diff --git a/test/_fixtures/package-json/outputs/013.json b/test/_fixtures/package-json/outputs/013.json
index c1c87b270c..d332c094ab 100644
--- a/test/_fixtures/package-json/outputs/013.json
+++ b/test/_fixtures/package-json/outputs/013.json
@@ -23,6 +23,9 @@
     "angular-sanitize":  "1.6.1",
     "@angular/core": "4.0.0-beta.1"
   },
+  "resolutions": {
+    "config": "1.21.0"
+  },
   "homepage": "https://keylocation.sg",
   "keywords": [
     "Key Location",
diff --git a/test/manager/npm/update.spec.js b/test/manager/npm/update.spec.js
index db17856ef4..775248d0dc 100644
--- a/test/manager/npm/update.spec.js
+++ b/test/manager/npm/update.spec.js
@@ -23,6 +23,16 @@ describe('workers/branch/package-json', () => {
       );
       testContent.should.equal(outputContent);
     });
+    it('updates resolutions too', () => {
+      const testContent = npmUpdater.setNewValue(
+        input01Content,
+        'dependencies',
+        'config',
+        '1.22.0'
+      );
+      expect(JSON.parse(testContent).dependencies.config).toEqual('1.22.0');
+      expect(JSON.parse(testContent).resolutions.config).toEqual('1.22.0');
+    });
     it('replaces only the first instance of a value', () => {
       const outputContent = readFixture('outputs/012.json');
       const testContent = npmUpdater.setNewValue(
-- 
GitLab