From e76ef17db5eb997e990e9f191251713fe7440a76 Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Mon, 18 Feb 2019 22:22:33 +0100
Subject: [PATCH] feat: ignorePresets

Closes #841
---
 lib/config/definitions.js             |  9 +++++++++
 lib/config/presets.js                 | 22 +++++++++++++++++++---
 website/docs/configuration-options.md | 13 +++++++++++++
 3 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/lib/config/definitions.js b/lib/config/definitions.js
index e21b310b5d..d62cd96d5c 100644
--- a/lib/config/definitions.js
+++ b/lib/config/definitions.js
@@ -14,6 +14,15 @@ const options = [
     allowString: true,
     cli: false,
   },
+  {
+    name: 'ignorePresets',
+    description:
+      'A list of presets to ignore, including nested ones inside `extends`',
+    stage: 'package',
+    type: 'list',
+    allowString: true,
+    cli: false,
+  },
   {
     name: 'description',
     description: 'Plain text description for a config or preset',
diff --git a/lib/config/presets.js b/lib/config/presets.js
index 1e6a98b7f2..098d751c3d 100644
--- a/lib/config/presets.js
+++ b/lib/config/presets.js
@@ -19,7 +19,14 @@ module.exports = {
   getPreset,
 };
 
-async function resolveConfigPresets(inputConfig, existingPresets = []) {
+async function resolveConfigPresets(
+  inputConfig,
+  ignorePresets,
+  existingPresets = []
+) {
+  if (!ignorePresets) {
+    ignorePresets = inputConfig.ignorePresets || []; // eslint-disable-line
+  }
   logger.trace(
     { config: inputConfig, existingPresets },
     'resolveConfigPresets'
@@ -31,6 +38,9 @@ async function resolveConfigPresets(inputConfig, existingPresets = []) {
       // istanbul ignore if
       if (existingPresets.includes(preset)) {
         logger.info(`Already seen preset ${preset} in ${existingPresets}`);
+      } else if (ignorePresets.includes(preset)) {
+        // istanbul ignore next
+        logger.info(`Ignoring preset ${preset} in ${existingPresets}`);
       } else {
         logger.trace(`Resolving preset "${preset}"`);
         let fetchedPreset;
@@ -61,6 +71,7 @@ async function resolveConfigPresets(inputConfig, existingPresets = []) {
         }
         const presetConfig = await resolveConfigPresets(
           fetchedPreset,
+          ignorePresets,
           existingPresets.concat([preset])
         );
         // istanbul ignore if
@@ -79,6 +90,7 @@ async function resolveConfigPresets(inputConfig, existingPresets = []) {
   // Now assign "regular" config on top
   config = configParser.mergeChildConfig(config, inputConfig);
   delete config.extends;
+  delete config.ignorePresets;
   logger.trace({ config }, `Post-merge resolve config`);
   for (const [key, val] of Object.entries(config)) {
     const ignoredKeys = ['content', 'onboardingConfig'];
@@ -88,7 +100,7 @@ async function resolveConfigPresets(inputConfig, existingPresets = []) {
       for (const element of val) {
         if (is.object(element)) {
           config[key].push(
-            await resolveConfigPresets(element, existingPresets)
+            await resolveConfigPresets(element, ignorePresets, existingPresets)
           );
         } else {
           config[key].push(element);
@@ -97,7 +109,11 @@ async function resolveConfigPresets(inputConfig, existingPresets = []) {
     } else if (is.object(val) && !ignoredKeys.includes(key)) {
       // Resolve nested objects
       logger.trace(`Resolving object "${key}"`);
-      config[key] = await resolveConfigPresets(val, existingPresets);
+      config[key] = await resolveConfigPresets(
+        val,
+        ignorePresets,
+        existingPresets
+      );
     }
   }
   logger.trace({ config: inputConfig }, 'Input config');
diff --git a/website/docs/configuration-options.md b/website/docs/configuration-options.md
index fc6a7bbbd4..e723076aeb 100644
--- a/website/docs/configuration-options.md
+++ b/website/docs/configuration-options.md
@@ -312,6 +312,19 @@ There may be times where an `.npmrc` file in your repository causes problems, su
 
 Using this setting, you can selectively ignore package files that you don't want Renovate autodiscovering. For instance if your repository has an "examples" directory of many package.json files that you don't want to be kept up to date.
 
+## ignorePresets
+
+Use this if you are extending a complex preset but won't want to use every "sub preset" that it uses. For example, take this config:
+
+```json
+{
+  "extends": ["config:base"],
+  "ignorePresets": [":prHourlyLimit2"]
+}
+```
+
+It would take the entire "config:base" preset - which contains a lot of sub-presets - but ignore the ":prHourlyLimit2" rule.
+
 ## ignoreUnstable
 
 By default, Renovate won't update any package versions to unstable versions (e.g. `4.0.0-rc3`) unless the current version has the same major.minor.patch and was _already_ unstable (e.g. it was already on `4.0.0-rc2`). Renovate will not "jump" unstable versions automatically, e.g. if you are on `4.0.0-rc2` and newer versions `4.0.0` and `4.1.0-alpha.1` exist then Renovate will update you to `4.0.0` only. If you need to force permanent unstable updates for a package, you can add a package rule setting `ignoreUnstable` to `false`.
-- 
GitLab