From c4463c69f9516e91a85c67678e987f1b529a1734 Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Mon, 19 Apr 2021 16:42:29 +0200
Subject: [PATCH] feat(config): better config migration (#9493)

---
 .../__snapshots__/migration.spec.ts.snap      |  1 +
 lib/config/migration.spec.ts                  |  8 ++++++-
 lib/config/migration.ts                       | 18 +++++----------
 .../presets/__snapshots__/index.spec.ts.snap  | 13 ++++++++---
 lib/config/presets/common.ts                  | 23 +++++++++++++++++++
 lib/config/presets/index.spec.ts              |  8 +++++++
 lib/config/presets/index.ts                   |  9 ++++++++
 lib/config/presets/internal/config.ts         |  4 ----
 lib/config/presets/internal/default.ts        | 22 ------------------
 lib/config/presets/internal/helpers.ts        |  7 ------
 10 files changed, 64 insertions(+), 49 deletions(-)
 create mode 100644 lib/config/presets/common.ts

diff --git a/lib/config/__snapshots__/migration.spec.ts.snap b/lib/config/__snapshots__/migration.spec.ts.snap
index 3f435e0a8d..48456d788e 100644
--- a/lib/config/__snapshots__/migration.spec.ts.snap
+++ b/lib/config/__snapshots__/migration.spec.ts.snap
@@ -95,6 +95,7 @@ Object {
   "dependencyDashboardTitle": "foo",
   "enabled": true,
   "extends": Array [
+    ":automergeBranch",
     "config:js-app",
     "config:js-lib",
     ":dependencyDashboard",
diff --git a/lib/config/migration.spec.ts b/lib/config/migration.spec.ts
index 3b2bdb7bc7..afcfbfef68 100644
--- a/lib/config/migration.spec.ts
+++ b/lib/config/migration.spec.ts
@@ -30,7 +30,13 @@ describe(getName(__filename), () => {
         compatibility: {
           python: '3.7',
         },
-        extends: [':js-app', 'config:library', ':masterIssue'],
+        extends: [
+          ':automergeBranchMergeCommit',
+          'default:js-app',
+          'config:library',
+          ':masterIssue',
+          'helpers:oddIsUnstable',
+        ],
         maintainYarnLock: true,
         onboarding: 'false' as never,
         multipleMajorPrs: true,
diff --git a/lib/config/migration.ts b/lib/config/migration.ts
index 3b9bb54498..8b4f7ad5b1 100644
--- a/lib/config/migration.ts
+++ b/lib/config/migration.ts
@@ -5,6 +5,7 @@ import { logger } from '../logger';
 import type { HostRule } from '../types';
 import { clone } from '../util/clone';
 import { getOptions } from './definitions';
+import { removedPresets } from './presets/common';
 import type { PackageRule, RenovateConfig, RenovateOptions } from './types';
 import { mergeChildConfig } from './utils';
 
@@ -245,22 +246,15 @@ export function migrateConfig(
         }
         const presets = migratedConfig.extends;
         for (let i = 0; i < presets.length; i += 1) {
-          let preset = presets[i];
+          const preset = presets[i];
           if (is.string(preset)) {
-            if (preset === 'config:application' || preset === ':js-app') {
-              preset = 'config:js-app';
-            } else if (preset === ':library' || preset === 'config:library') {
-              preset = 'config:js-lib';
-            } else if (preset.startsWith(':masterIssue')) {
-              preset = preset.replace('masterIssue', 'dependencyDashboard');
-            } else if (
-              [':unpublishSafe', 'default:unpublishSafe'].includes(preset)
-            ) {
-              preset = 'npm:unpublishSafe';
+            const newPreset = removedPresets[preset];
+            if (newPreset !== undefined) {
+              presets[i] = newPreset;
             }
-            presets[i] = preset;
           }
         }
+        migratedConfig.extends = migratedConfig.extends.filter(Boolean);
       } else if (key === 'unpublishSafe') {
         if (val === true) {
           migratedConfig.extends = migratedConfig.extends || [];
diff --git a/lib/config/presets/__snapshots__/index.spec.ts.snap b/lib/config/presets/__snapshots__/index.spec.ts.snap
index 0137555929..fa82ef87f4 100644
--- a/lib/config/presets/__snapshots__/index.spec.ts.snap
+++ b/lib/config/presets/__snapshots__/index.spec.ts.snap
@@ -46,9 +46,7 @@ Object {
   ],
   "packageRules": Array [
     Object {
-      "extends": Array [
-        "",
-      ],
+      "extends": Array [],
       "groupName": "{{arg1}}",
     },
   ],
@@ -67,6 +65,15 @@ exports[`config/presets/index getPreset handles preset not found 2`] = `undefine
 
 exports[`config/presets/index getPreset handles preset not found 3`] = `undefined`;
 
+exports[`config/presets/index getPreset handles removed presets with a migration 1`] = `
+Object {
+  "dependencyDashboard": true,
+  "description": Array [
+    "Enable Renovate Dependency Dashboard creation",
+  ],
+}
+`;
+
 exports[`config/presets/index getPreset handles throw errors 1`] = `undefined`;
 
 exports[`config/presets/index getPreset handles throw errors 2`] = `undefined`;
diff --git a/lib/config/presets/common.ts b/lib/config/presets/common.ts
new file mode 100644
index 0000000000..915c70edae
--- /dev/null
+++ b/lib/config/presets/common.ts
@@ -0,0 +1,23 @@
+export const removedPresets = {
+  ':automergeBranchMergeCommit': ':automergeBranch',
+  ':automergeBranchPush': ':automergeBranch',
+  ':base': 'config:base',
+  ':app': 'config:js-app',
+  ':js-app': 'config:js-app',
+  ':library': 'config:js-lib',
+  ':masterIssue': ':dependencyDashboard',
+  ':masterIssueApproval': ':dependencyDashboardApproval',
+  ':unpublishSafe': 'npm:unpublishSafe',
+  'config:application': 'config:js-app',
+  'config:base-js': 'config:base',
+  'config:library': 'config:js-lib',
+  'default:automergeBranchMergeCommit': ':automergeBranch',
+  'default:automergeBranchPush': ':automergeBranch',
+  'default:base': 'config:base',
+  'default:app': 'config:js-app',
+  'default:js-app': 'config:js-app',
+  'default:library': 'config:js-lib',
+  'default:unpublishSafe': 'npm:unpublishSafe',
+  'helpers:oddIsUnstable': null,
+  'helpers:oddIsUnstablePackages': null,
+};
diff --git a/lib/config/presets/index.spec.ts b/lib/config/presets/index.spec.ts
index 5600d77e79..4ac3017213 100644
--- a/lib/config/presets/index.spec.ts
+++ b/lib/config/presets/index.spec.ts
@@ -392,6 +392,14 @@ describe(getName(__filename), () => {
     });
   });
   describe('getPreset', () => {
+    it('handles removed presets with a migration', async () => {
+      const res = await presets.getPreset(':masterIssue', {});
+      expect(res).toMatchSnapshot();
+    });
+    it('handles removed presets with no migration', async () => {
+      const res = await presets.getPreset('helpers:oddIsUnstable', {});
+      expect(res).toEqual({});
+    });
     it('gets linters', async () => {
       const res = await presets.getPreset('packages:linters', {});
       expect(res).toMatchSnapshot();
diff --git a/lib/config/presets/index.ts b/lib/config/presets/index.ts
index f534e26939..356d47782e 100644
--- a/lib/config/presets/index.ts
+++ b/lib/config/presets/index.ts
@@ -10,6 +10,7 @@ import * as massage from '../massage';
 import * as migration from '../migration';
 import type { GlobalConfig, RenovateConfig } from '../types';
 import { mergeChildConfig } from '../utils';
+import { removedPresets } from './common';
 import * as gitea from './gitea';
 import * as github from './github';
 import * as gitlab from './gitlab';
@@ -165,6 +166,14 @@ export async function getPreset(
   baseConfig?: RenovateConfig
 ): Promise<RenovateConfig> {
   logger.trace(`getPreset(${preset})`);
+  // Check if the preset has been removed or replaced
+  const newPreset = removedPresets[preset];
+  if (newPreset) {
+    return getPreset(newPreset, baseConfig);
+  }
+  if (newPreset === null) {
+    return {};
+  }
   const {
     presetSource,
     packageName,
diff --git a/lib/config/presets/internal/config.ts b/lib/config/presets/internal/config.ts
index a126a5ef63..973954bb62 100644
--- a/lib/config/presets/internal/config.ts
+++ b/lib/config/presets/internal/config.ts
@@ -21,10 +21,6 @@ export const presets: Record<string, Preset> = {
       'workarounds:all',
     ],
   },
-  'base-js': {
-    description: 'Base configuration for Javascript (deprecated)',
-    extends: ['config:base'],
-  },
   'js-app': {
     description: 'Default configuration for webapps',
     extends: ['config:base', ':pinAllExceptPeerDependencies'],
diff --git a/lib/config/presets/internal/default.ts b/lib/config/presets/internal/default.ts
index f07452536b..b7829d5ebb 100644
--- a/lib/config/presets/internal/default.ts
+++ b/lib/config/presets/internal/default.ts
@@ -304,16 +304,6 @@ export const presets: Record<string, Preset> = {
       'If automerging, push the new commit directly to base branch (no PR)',
     automergeType: 'branch',
   },
-  automergeBranchMergeCommit: {
-    description:
-      'If automerging, perform a merge-commit on branch (no PR) - deprecated, use :automergeBranch instead',
-    automergeType: 'branch-merge-commit',
-  },
-  automergeBranchPush: {
-    description:
-      'If automerging, push the new commit directly to base branch (no PR) - deprecated, use :automergeBranch instead',
-    automergeType: 'branch-push',
-  },
   automergePr: {
     description: 'Raise a PR first before any automerging',
     automergeType: 'pr',
@@ -572,18 +562,6 @@ export const presets: Record<string, Preset> = {
       },
     ],
   },
-  base: {
-    description: 'deprecated alias for config:base',
-    extends: ['config:base'],
-  },
-  app: {
-    description: 'deprecated alias for config:js-app',
-    extends: ['config:js-app'],
-  },
-  library: {
-    description: 'deprecated alias for config:js-lib',
-    extends: ['config:js-lib'],
-  },
   disablePrControls: {
     description: 'Remove the checkbox controls from PRs',
     prBodyTemplate:
diff --git a/lib/config/presets/internal/helpers.ts b/lib/config/presets/internal/helpers.ts
index 5a41039270..8eb0831d21 100644
--- a/lib/config/presets/internal/helpers.ts
+++ b/lib/config/presets/internal/helpers.ts
@@ -10,13 +10,6 @@ export const presets: Record<string, Preset> = {
       },
     ],
   },
-  oddIsUnstable: {
-    description: 'DEPRECATED: Odd version numbers are classified as unstable',
-  },
-  oddIsUnstablePackages: {
-    description:
-      'DEPRECATED: Preconfigure dependencies where an odd major version indicates unstable (Docker-only)',
-  },
   followTypescriptNext: {
     description:
       'Keep <typescript> version in sync with the <code>next</code> tag',
-- 
GitLab