From cfa495da618dad5a9cfedb74bc36a98deb4a9f2a Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@keylocation.sg>
Date: Sun, 6 Aug 2017 06:41:45 +0200
Subject: [PATCH] feat: support package rule merging (#632)

packageRules are now mergeable between parent and child. Child rules will be placed before parent rules.

Closes #591
---
 lib/config/definitions.js |  1 +
 lib/config/index.js       | 15 +++++++++++----
 test/config/index.spec.js | 17 +++++++++++++++++
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/lib/config/definitions.js b/lib/config/definitions.js
index d43372a112..e686c36144 100644
--- a/lib/config/definitions.js
+++ b/lib/config/definitions.js
@@ -192,6 +192,7 @@ const options = [
     description: 'Rules for matching package names',
     type: 'list',
     stage: 'depType',
+    mergeable: true,
     cli: false,
     env: false,
   },
diff --git a/lib/config/index.js b/lib/config/index.js
index a165b3b440..864e574d3a 100644
--- a/lib/config/index.js
+++ b/lib/config/index.js
@@ -118,10 +118,17 @@ function mergeChildConfig(parentConfig, childConfig) {
   for (const option of definitions.getOptions()) {
     if (option.mergeable && childConfig[option.name]) {
       logger.debug(`mergeable option: ${option.name}`);
-      config[option.name] = {
-        ...parentConfig[option.name],
-        ...childConfig[option.name],
-      };
+      if (option.type === 'list') {
+        // Place parent values *after* child
+        config[option.name] = config[option.name].concat(
+          parentConfig[option.name]
+        );
+      } else {
+        config[option.name] = {
+          ...parentConfig[option.name],
+          ...childConfig[option.name],
+        };
+      }
       logger.debug({ option: config[option.name] }, `config.${option.name}`);
     }
   }
diff --git a/test/config/index.spec.js b/test/config/index.spec.js
index 315b08575b..f597604369 100644
--- a/test/config/index.spec.js
+++ b/test/config/index.spec.js
@@ -173,5 +173,22 @@ describe('config/index', () => {
       const config = configParser.mergeChildConfig(parentConfig, childConfig);
       expect(config.depTypes).toMatchSnapshot();
     });
+    it('merges packageRules', () => {
+      const parentConfig = { ...defaultConfig };
+      Object.assign(parentConfig, {
+        packageRules: [{ a: 1 }, { a: 2 }],
+      });
+      const childConfig = {
+        packageRules: [{ a: 3 }, { a: 4 }],
+      };
+      const configParser = require('../../lib/config/index.js');
+      const config = configParser.mergeChildConfig(parentConfig, childConfig);
+      expect(config.packageRules.map(rule => rule.a)).toMatchObject([
+        3,
+        4,
+        1,
+        2,
+      ]);
+    });
   });
 });
-- 
GitLab