From ca23927735350ff283f7d6c791b2a2f41dcbc29a Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Fri, 13 Jul 2018 06:48:52 +0200
Subject: [PATCH] feat: pin PRs should only block necessary PRs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Previously if there were any “pin” updates then that would block all non-pin updates until the pin one was merged. However, this doesn’t make sense if the other PR is for an unrelated dependency.

Closes https://github.com/renovatebot/config-help/issues/64
---
 lib/manager/docker/package.js                    |  7 +++++++
 lib/workers/repository/process/lookup/index.js   |  7 +++++++
 lib/workers/repository/process/write.js          | 11 ++++++++---
 lib/workers/repository/updates/generate.js       |  1 +
 .../docker/__snapshots__/package.spec.js.snap    |  1 +
 .../lookup/__snapshots__/index.spec.js.snap      | 16 ++++++++++++++++
 test/workers/repository/process/write.spec.js    |  6 +++---
 7 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/lib/manager/docker/package.js b/lib/manager/docker/package.js
index b452d14be2..4479fede9e 100644
--- a/lib/manager/docker/package.js
+++ b/lib/manager/docker/package.js
@@ -159,6 +159,13 @@ async function getPackageUpdates(config) {
       );
     }
   }
+  if (upgrades.some(upgrade => upgrade.updateType === 'pin')) {
+    for (const upgrade of upgrades) {
+      if (upgrade.updateType !== 'pin') {
+        upgrade.blockedByPin = true;
+      }
+    }
+  }
   return upgrades.filter(u => u.newDigest !== null);
 }
 
diff --git a/lib/workers/repository/process/lookup/index.js b/lib/workers/repository/process/lookup/index.js
index a8c51a098d..f9146864ff 100644
--- a/lib/workers/repository/process/lookup/index.js
+++ b/lib/workers/repository/process/lookup/index.js
@@ -148,6 +148,13 @@ async function lookupUpdates(config) {
       filteredVersions.includes(release.version) ||
       release.version === fromVersion
   );
+  if (res.updates.some(update => update.updateType === 'pin')) {
+    for (const update of res.updates) {
+      if (update.updateType !== 'pin' && update.updateType !== 'rollback') {
+        update.blockedByPin = true;
+      }
+    }
+  }
   return res;
 }
 
diff --git a/lib/workers/repository/process/write.js b/lib/workers/repository/process/write.js
index af171e9b31..267db0dcdd 100644
--- a/lib/workers/repository/process/write.js
+++ b/lib/workers/repository/process/write.js
@@ -10,9 +10,14 @@ module.exports = {
 async function writeUpdates(config, packageFiles, allBranches) {
   let branches = allBranches;
   logger.info(`Processing ${branches.length} branch(es)`);
-  if (!config.mirrorMode && branches.some(upg => upg.updateType === 'pin')) {
-    branches = branches.filter(upg => upg.updateType === 'pin');
-    logger.info(`Processing ${branches.length} "pin" PRs first`);
+  if (!config.mirrorMode) {
+    branches = branches.filter(branchConfig => {
+      if (branchConfig.blockedByPin) {
+        logger.info(`Branch ${branchConfig.branchName} is blocked by a Pin PR`);
+        return false;
+      }
+      return true;
+    });
   }
   const tmpDir = await tmp.dir({ unsafeCleanup: true });
   let prsRemaining = await getPrsRemaining(config, branches);
diff --git a/lib/workers/repository/updates/generate.js b/lib/workers/repository/updates/generate.js
index 7f6bccfb8b..bf5242eea5 100644
--- a/lib/workers/repository/updates/generate.js
+++ b/lib/workers/repository/updates/generate.js
@@ -144,6 +144,7 @@ function generateBranchConfig(branchUpgrades) {
     upgrade => upgrade.updateType !== 'lockFileMaintenance'
   );
   config.automerge = config.upgrades.every(upgrade => upgrade.automerge);
+  config.blockedByPin = config.upgrades.every(upgrade => upgrade.blockedByPin);
   return config;
 }
 
diff --git a/test/manager/docker/__snapshots__/package.spec.js.snap b/test/manager/docker/__snapshots__/package.spec.js.snap
index 18a83e9608..0a7e53eb0d 100644
--- a/test/manager/docker/__snapshots__/package.spec.js.snap
+++ b/test/manager/docker/__snapshots__/package.spec.js.snap
@@ -11,6 +11,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "newDepTag": "some-dep:1.1.0-something",
     "newDigest": "sha256:two",
     "newFrom": "some-dep:1.1.0-something@sha256:two",
diff --git a/test/workers/repository/process/lookup/__snapshots__/index.spec.js.snap b/test/workers/repository/process/lookup/__snapshots__/index.spec.js.snap
index 9da251760a..f5b8bcf6fc 100644
--- a/test/workers/repository/process/lookup/__snapshots__/index.spec.js.snap
+++ b/test/workers/repository/process/lookup/__snapshots__/index.spec.js.snap
@@ -9,6 +9,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "0.4.4",
     "isSingleVersion": true,
@@ -47,6 +48,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "0.9.4",
     "isRange": true,
@@ -59,6 +61,7 @@ Array [
     "updateType": "minor",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "0.9.4",
     "isRange": true,
@@ -173,6 +176,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "0.9.7",
     "isSingleVersion": true,
@@ -264,6 +268,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "0.4.4",
     "isSingleVersion": true,
@@ -275,6 +280,7 @@ Array [
     "updateType": "minor",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "0.4.4",
     "isSingleVersion": true,
@@ -406,6 +412,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "0.4.4",
     "isSingleVersion": true,
@@ -428,6 +435,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "0.4.4",
     "isSingleVersion": true,
@@ -787,6 +795,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "0.4.4",
     "isSingleVersion": true,
@@ -798,6 +807,7 @@ Array [
     "updateType": "minor",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "0.4.4",
     "isSingleVersion": true,
@@ -820,6 +830,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "0.4.4",
     "isSingleVersion": true,
@@ -831,6 +842,7 @@ Array [
     "updateType": "minor",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "0.4.4",
     "isSingleVersion": true,
@@ -887,6 +899,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "1.3.0",
     "isSingleVersion": true,
@@ -1144,6 +1157,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "1.0.1",
     "isSingleVersion": true,
@@ -1258,6 +1272,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "1.3.0",
     "isSingleVersion": true,
@@ -1297,6 +1312,7 @@ Array [
     "updateType": "pin",
   },
   Object {
+    "blockedByPin": true,
     "canBeUnpublished": false,
     "fromVersion": "1.0.0",
     "isSingleVersion": true,
diff --git a/test/workers/repository/process/write.spec.js b/test/workers/repository/process/write.spec.js
index 5a9ac99620..8863fe82c6 100644
--- a/test/workers/repository/process/write.spec.js
+++ b/test/workers/repository/process/write.spec.js
@@ -16,11 +16,11 @@ beforeEach(() => {
 describe('workers/repository/write', () => {
   describe('writeUpdates()', () => {
     const packageFiles = {};
-    it('runs pins first', async () => {
-      const branches = [{ updateType: 'pin' }, {}, {}];
+    it('skips branches blocked by pin', async () => {
+      const branches = [{ updateType: 'pin' }, { blockedByPin: true }, {}];
       const res = await writeUpdates(config, packageFiles, branches);
       expect(res).toEqual('done');
-      expect(branchWorker.processBranch.mock.calls).toHaveLength(1);
+      expect(branchWorker.processBranch.mock.calls).toHaveLength(2);
     });
     it('stops after automerge', async () => {
       const branches = [{}, {}, {}, {}];
-- 
GitLab