From 6c4892b59336ecb7bcb09ad1678f068f4ac11045 Mon Sep 17 00:00:00 2001
From: Michael Kriese <michael.kriese@visualon.de>
Date: Mon, 2 Mar 2020 12:06:16 +0100
Subject: [PATCH] chore(types): fix more typescript types (#5615)

---
 .eslintrc.js                                  |  7 ++
 lib/config/common.ts                          | 94 +++++++++++++++---
 lib/config/decrypt.ts                         |  8 +-
 lib/config/definitions.ts                     |  2 +-
 lib/config/massage.ts                         | 10 +-
 lib/config/migration.ts                       | 52 ++++++----
 lib/config/presets/index.ts                   | 12 ++-
 lib/config/utils.ts                           | 14 +--
 lib/config/validation.ts                      |  8 +-
 lib/datasource/docker/index.ts                |  5 +-
 lib/manager/bazel/update.spec.ts              |  3 +-
 lib/manager/common.ts                         |  9 +-
 lib/manager/gomod/update.spec.ts              | 19 ++--
 lib/types/host-rules.ts                       | 15 +++
 lib/types/index.ts                            |  1 +
 lib/util/host-rules.ts                        | 14 +--
 lib/workers/branch/check-existing.ts          |  4 +-
 lib/workers/branch/commit.ts                  | 15 +--
 lib/workers/branch/get-updated.ts             |  6 +-
 lib/workers/branch/index.ts                   | 16 +--
 lib/workers/common.ts                         | 97 +++++++++++++++----
 lib/workers/pr/body/banner.ts                 |  4 +-
 lib/workers/pr/body/changelogs.ts             |  4 +-
 lib/workers/pr/body/common.ts                 | 29 ------
 lib/workers/pr/body/config-description.ts     |  4 +-
 lib/workers/pr/body/footer.ts                 |  4 +-
 lib/workers/pr/body/index.ts                  |  6 +-
 lib/workers/pr/body/notes.ts                  |  6 +-
 lib/workers/pr/body/updates-table.ts          |  6 +-
 lib/workers/pr/changelog/common.ts            | 15 ---
 lib/workers/pr/changelog/index.ts             |  5 +-
 lib/workers/pr/changelog/releases.ts          | 12 +--
 lib/workers/pr/changelog/source-github.ts     | 10 +-
 lib/workers/pr/index.ts                       |  4 +-
 lib/workers/repository/onboarding/pr/index.ts |  5 +-
 .../repository/onboarding/pr/pr-list.ts       |  7 +-
 lib/workers/repository/process/limits.ts      |  7 +-
 .../repository/process/lookup/common.ts       |  4 +-
 .../repository/process/lookup/index.ts        |  4 +-
 lib/workers/repository/process/sort.ts        |  8 +-
 lib/workers/repository/updates/branchify.ts   | 18 +++-
 lib/workers/repository/updates/generate.ts    | 25 +++--
 test/config/migration.spec.ts                 | 29 ++++--
 test/workers/branch/check-existing.spec.ts    | 10 +-
 test/workers/branch/commit.spec.ts            | 15 ++-
 test/workers/pr/changelog/index.spec.ts       |  8 +-
 test/workers/pr/changelog/releases.spec.ts    | 23 ++---
 test/workers/repository/configured.spec.ts    |  2 +-
 test/workers/repository/error-config.spec.ts  |  2 +-
 test/workers/repository/error.spec.ts         |  2 +-
 .../repository/extract/manager-files.spec.ts  |  2 +-
 test/workers/repository/index.spec.ts         |  2 +-
 test/workers/repository/master-issue.spec.ts  | 18 ++--
 .../repository/process/extract-update.spec.ts |  5 +-
 .../workers/repository/process/limits.spec.ts |  6 +-
 test/workers/repository/process/sort.spec.ts  | 17 ++--
 test/workers/repository/result.spec.ts        |  2 +-
 .../repository/updates/branchify.spec.ts      |  3 +-
 .../repository/updates/generate.spec.ts       | 46 ++++-----
 59 files changed, 447 insertions(+), 343 deletions(-)
 create mode 100644 lib/types/host-rules.ts
 delete mode 100644 lib/workers/pr/body/common.ts

diff --git a/.eslintrc.js b/.eslintrc.js
index e24396d3c7..4b05aff10b 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -5,6 +5,9 @@ module.exports = {
   },
   extends: [
     'airbnb-typescript/base',
+    'plugin:import/errors',
+    'plugin:import/warnings',
+    'plugin:import/typescript',
     // https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin/src/configs
     'plugin:@typescript-eslint/eslint-recommended',
     'plugin:@typescript-eslint/recommended',
@@ -56,6 +59,10 @@ module.exports = {
       },
     ], // disable until proper interfaced api
   },
+  settings: {
+    // https://github.com/benmosher/eslint-plugin-import/issues/1618
+    'import/internal-regex': '^type\\-fest$',
+  },
   overrides: [
     {
       files: ['**/*.spec.ts'],
diff --git a/lib/config/common.ts b/lib/config/common.ts
index 21a0ce348c..993c140d8d 100644
--- a/lib/config/common.ts
+++ b/lib/config/common.ts
@@ -1,4 +1,6 @@
 import { Range } from 'semver';
+import { LogLevel } from 'bunyan';
+import { HostRule } from '../types';
 
 export type RenovateConfigStage =
   | 'global'
@@ -7,30 +9,82 @@ export type RenovateConfigStage =
   | 'branch'
   | 'pr';
 
+export interface GroupConfig extends Record<string, unknown> {
+  branchName?: string;
+  branchTopic?: string;
+}
+
 // TODO: Proper typings
 export interface RenovateSharedConfig {
   automerge?: boolean;
+  branchPrefix?: string;
   branchName?: string;
+
+  commitMessage?: string;
   enabled?: boolean;
+  enabledManagers?: string[];
+  group?: GroupConfig;
+  groupName?: string;
+  groupSlug?: string;
   ignoreDeps?: string[];
+  ignorePaths?: string[];
   labels?: string[];
   managers?: string | string[];
+  masterIssueApproval?: boolean;
+  npmrc?: string;
   platform?: string;
+  postUpgradeTasks?: PostUpgradeTasks;
+  prBodyColumns?: string[];
+  prCreation?: 'immediate' | 'not-pending' | 'status-success' | 'approval';
   productLinks?: Record<string, string>;
   prPriority?: number;
+  rebaseLabel?: string;
   rebaseWhen?: string;
   recreateClosed?: boolean;
   requiredStatusChecks?: string[];
   schedule?: string[];
-
   semanticCommits?: boolean;
   semanticCommitScope?: string;
   semanticCommitType?: string;
   statusCheckVerify?: boolean;
   suppressNotifications?: string[];
   timezone?: string;
+  unicodeEmoji?: boolean;
+}
+
+export interface GlobalConfig {
+  prBanner?: string;
+  prFooter?: string;
+}
+
+export interface RenovateAdminConfig {
   allowedPostUpgradeCommands?: string[];
-  postUpgradeTasks?: PostUpgradeTasks;
+  autodiscover?: boolean;
+  autodiscoverFilter?: string;
+
+  baseDir?: string;
+  cacheDir?: string;
+  configWarningReuseIssue?: boolean;
+  dryRun?: boolean;
+
+  global?: GlobalConfig;
+
+  localDir?: string;
+  logFile?: string;
+  logFileLevel?: LogLevel;
+  logLevel?: LogLevel;
+  logContext?: string;
+
+  onboarding?: boolean;
+  onboardingBranch?: string;
+  onboardingPrTitle?: string;
+  onboardingConfig?: RenovateSharedConfig;
+
+  postUpdateOptions?: string[];
+  privateKey?: string | Buffer;
+  repositories?: RenovateRepository[];
+  requireConfig?: boolean;
+  trustLevel?: 'low' | 'high';
 }
 
 export type PostUpgradeTasks = {
@@ -50,33 +104,42 @@ export type RenovateRepository =
 
 // TODO: Proper typings
 export interface RenovateConfig
-  extends RenovateSharedConfig,
+  extends RenovateAdminConfig,
+    RenovateSharedConfig,
     UpdateConfig<PackageRule>,
-    Record<string, any> {
-  autodiscover?: boolean;
-  autodiscoverFilter?: string;
-  baseBranch?: string;
+    Record<string, unknown> {
   baseBranches?: string[];
+  baseBranch?: string;
   branchList?: string[];
   description?: string[];
-  dryRun?: boolean;
+
+  endpoint?: string;
   errors?: ValidationMessage[];
+  extends?: string[];
 
-  /** TODO: Type? */
-  global?: Record<string, any>;
+  gitAuthor?: string;
 
+  hostRules?: HostRule[];
+
+  ignorePresets?: string[];
   includeForks?: boolean;
   isFork?: boolean;
-  onboarding?: boolean;
-  onboardingConfig?: RenovateSharedConfig;
+
+  masterIssue?: boolean;
+  masterIssueAutoclose?: boolean;
+  masterIssueChecks?: Record<string, string>;
+  masterIssueRebaseAllOpen?: boolean;
+  masterIssueTitle?: string;
+
   packageRules?: PackageRule[];
   prConcurrentLimit?: number;
   prHourlyLimit?: number;
-  privateKey?: string | Buffer;
   repoIsOnboarded?: boolean;
-  repositories?: RenovateRepository[];
-  requireConfig?: boolean;
+
+  updateType?: UpdateType;
+
   warnings?: ValidationMessage[];
+  vulnerabilityAlerts?: RenovateSharedConfig;
 }
 
 export type UpdateType =
@@ -86,6 +149,7 @@ export type UpdateType =
   | 'pin'
   | 'digest'
   | 'lockFileMaintenance'
+  | 'lockfileUpdate'
   | 'rollback'
   | 'bump';
 
diff --git a/lib/config/decrypt.ts b/lib/config/decrypt.ts
index 1525926b28..fcd8060433 100644
--- a/lib/config/decrypt.ts
+++ b/lib/config/decrypt.ts
@@ -86,13 +86,15 @@ export function decryptConfig(
       decryptedConfig[key] = [];
       val.forEach(item => {
         if (is.object(item) && !is.array(item)) {
-          decryptedConfig[key].push(decryptConfig(item, privateKey));
+          (decryptedConfig[key] as RenovateConfig[]).push(
+            decryptConfig(item as RenovateConfig, privateKey)
+          );
         } else {
-          decryptedConfig[key].push(item);
+          (decryptedConfig[key] as RenovateConfig[]).push(item);
         }
       });
     } else if (is.object(val) && key !== 'content') {
-      decryptedConfig[key] = decryptConfig(val, privateKey);
+      decryptedConfig[key] = decryptConfig(val as RenovateConfig, privateKey);
     }
   }
   delete decryptedConfig.encrypted;
diff --git a/lib/config/definitions.ts b/lib/config/definitions.ts
index 2eccced333..52630e0bb7 100644
--- a/lib/config/definitions.ts
+++ b/lib/config/definitions.ts
@@ -1677,7 +1677,7 @@ const options: RenovateOptions[] = [
   },
 ];
 
-export function getOptions(): any {
+export function getOptions(): RenovateOptions[] {
   return options;
 }
 
diff --git a/lib/config/massage.ts b/lib/config/massage.ts
index 4d54a813d7..375027781f 100644
--- a/lib/config/massage.ts
+++ b/lib/config/massage.ts
@@ -21,20 +21,22 @@ export function massageConfig(config: RenovateConfig): RenovateConfig {
   for (const [key, val] of Object.entries(config)) {
     if (allowedStrings.includes(key) && is.string(val)) {
       massagedConfig[key] = [val];
-    } else if (key === 'npmToken' && val && val.length < 50) {
+    } else if (key === 'npmToken' && is.string(val) && val.length < 50) {
       massagedConfig.npmrc = `//registry.npmjs.org/:_authToken=${val}\n`;
       delete massagedConfig.npmToken;
     } else if (is.array(val)) {
       massagedConfig[key] = [];
       val.forEach(item => {
         if (is.object(item)) {
-          massagedConfig[key].push(massageConfig(item));
+          (massagedConfig[key] as RenovateConfig[]).push(
+            massageConfig(item as RenovateConfig)
+          );
         } else {
-          massagedConfig[key].push(item);
+          (massagedConfig[key] as RenovateConfig[]).push(item);
         }
       });
     } else if (is.object(val) && key !== 'encrypted') {
-      massagedConfig[key] = massageConfig(val);
+      massagedConfig[key] = massageConfig(val as RenovateConfig);
     }
   }
   if (is.nonEmptyArray(massagedConfig.packageRules)) {
diff --git a/lib/config/migration.ts b/lib/config/migration.ts
index 7ea887b262..5a078439d2 100644
--- a/lib/config/migration.ts
+++ b/lib/config/migration.ts
@@ -3,7 +3,8 @@ import later from 'later';
 import { logger } from '../logger';
 import { clone } from '../util/clone';
 import { getOptions, RenovateOptions } from './definitions';
-import { RenovateConfig } from './common';
+import { RenovateConfig, PackageRule } from './common';
+import { HostRule } from '../types';
 
 const options = getOptions();
 
@@ -28,6 +29,15 @@ export interface MigratedConfig {
   migratedConfig: RenovateConfig;
 }
 
+interface MigratedRenovateConfig extends RenovateConfig {
+  endpoints?: HostRule[];
+  pathRules: PackageRule[];
+  packages: PackageRule[];
+
+  node?: RenovateConfig;
+  travis?: RenovateConfig;
+}
+
 // Returns a migrated config
 export function migrateConfig(
   config: RenovateConfig,
@@ -42,7 +52,7 @@ export function migrateConfig(
       });
     }
     let isMigrated = false;
-    const migratedConfig = clone(config);
+    const migratedConfig = clone(config) as MigratedRenovateConfig;
     const depTypes = [
       'dependencies',
       'devDependencies',
@@ -94,7 +104,8 @@ export function migrateConfig(
             fileList.push((packageFile as any).packageFile);
             if (Object.keys(packageFile).length > 1) {
               migratedConfig.packageRules = migratedConfig.packageRules || [];
-              const payload = migrateConfig(packageFile, key).migratedConfig;
+              const payload = migrateConfig(packageFile as RenovateConfig, key)
+                .migratedConfig;
               for (const subrule of payload.packageRules || []) {
                 subrule.paths = [(packageFile as any).packageFile];
                 migratedConfig.packageRules.push(subrule);
@@ -117,7 +128,8 @@ export function migrateConfig(
       } else if (depTypes.includes(key)) {
         isMigrated = true;
         migratedConfig.packageRules = migratedConfig.packageRules || [];
-        const depTypePackageRule = migrateConfig(val, key).migratedConfig;
+        const depTypePackageRule = migrateConfig(val as RenovateConfig, key)
+          .migratedConfig;
         depTypePackageRule.depTypeList = [key];
         delete depTypePackageRule.packageRules;
         migratedConfig.packageRules.push(depTypePackageRule);
@@ -165,10 +177,10 @@ export function migrateConfig(
         if (val === 'widen') {
           migratedConfig.rangeStrategy = 'widen';
         }
-      } else if (key === 'semanticPrefix') {
+      } else if (key === 'semanticPrefix' && is.string(val)) {
         isMigrated = true;
         delete migratedConfig.semanticPrefix;
-        let [text] = val.split(':');
+        let [text] = val.split(':') as any; // TODO: fixme
         text = text.split('(');
         [migratedConfig.semanticCommitType] = text;
         if (text.length > 1) {
@@ -211,7 +223,7 @@ export function migrateConfig(
         isMigrated = true;
         delete migratedConfig.multipleMajorPrs;
         migratedConfig.separateMultipleMajor = val;
-      } else if (key === 'renovateFork') {
+      } else if (key === 'renovateFork' && is.boolean(val)) {
         isMigrated = true;
         delete migratedConfig.renovateFork;
         migratedConfig.includeForks = val;
@@ -281,7 +293,7 @@ export function migrateConfig(
         delete migratedConfig.baseBranch;
       } else if (key === 'schedule' && val) {
         // massage to array first
-        const schedules = is.string(val) ? [val] : [...val];
+        const schedules = is.string(val) ? [val] : [...(val as string[])];
         // split 'and'
         const schedulesLength = schedules.length;
         for (let i = 0; i < schedulesLength; i += 1) {
@@ -340,9 +352,7 @@ export function migrateConfig(
             schedules[i] = schedules[i].replace(' every day', '');
           }
           if (
-            schedules[i].match(
-              /every (mon|tues|wednes|thurs|fri|satur|sun)day$/
-            )
+            /every (mon|tues|wednes|thurs|fri|satur|sun)day$/.test(schedules[i])
           ) {
             isMigrated = true;
             schedules[i] = schedules[i].replace(/every ([a-z]*day)$/, 'on $1');
@@ -354,7 +364,7 @@ export function migrateConfig(
         }
         if (isMigrated) {
           if (is.string(val) && schedules.length === 1) {
-            [migratedConfig.schedule] = schedules;
+            [migratedConfig.schedule] = schedules as any; // TODO: fixme
           } else {
             migratedConfig.schedule = schedules;
           }
@@ -371,7 +381,10 @@ export function migrateConfig(
             const depTypeName = (depType as any).depType;
             if (depTypeName) {
               migratedConfig.packageRules = migratedConfig.packageRules || [];
-              const newPackageRule = migrateConfig(depType, key).migratedConfig;
+              const newPackageRule = migrateConfig(
+                depType as RenovateConfig,
+                key
+              ).migratedConfig;
               delete newPackageRule.depType;
               newPackageRule.depTypeList = [depTypeName];
               migratedConfig.packageRules.push(newPackageRule);
@@ -395,7 +408,7 @@ export function migrateConfig(
         val.length === 1
       ) {
         migratedConfig[key] = `${val[0]}`;
-      } else if (key === 'node' && val.enabled === true) {
+      } else if (key === 'node' && (val as RenovateConfig).enabled === true) {
         isMigrated = true;
         delete migratedConfig.node.enabled;
         migratedConfig.travis = migratedConfig.travis || {};
@@ -408,9 +421,9 @@ export function migrateConfig(
         }
       } else if (is.array(val)) {
         const newArray = [];
-        for (const item of migratedConfig[key]) {
+        for (const item of migratedConfig[key] as unknown[]) {
           if (is.object(item) && !is.array(item)) {
-            const arrMigrate = migrateConfig(item, key);
+            const arrMigrate = migrateConfig(item as RenovateConfig, key);
             newArray.push(arrMigrate.migratedConfig);
             if (arrMigrate.isMigrated) {
               isMigrated = true;
@@ -421,14 +434,17 @@ export function migrateConfig(
         }
         migratedConfig[key] = newArray;
       } else if (is.object(val)) {
-        const subMigrate = migrateConfig(migratedConfig[key], key);
+        const subMigrate = migrateConfig(
+          migratedConfig[key] as RenovateConfig,
+          key
+        );
         if (subMigrate.isMigrated) {
           isMigrated = true;
           migratedConfig[key] = subMigrate.migratedConfig;
         }
       } else if (
         key.startsWith('commitMessage') &&
-        val &&
+        is.string(val) &&
         (val.includes('currentVersion') || val.includes('newVersion'))
       ) {
         isMigrated = true;
diff --git a/lib/config/presets/index.ts b/lib/config/presets/index.ts
index e694730dc8..6bf870f410 100644
--- a/lib/config/presets/index.ts
+++ b/lib/config/presets/index.ts
@@ -223,18 +223,22 @@ export async function resolveConfigPresets(
       config[key] = [];
       for (const element of val) {
         if (is.object(element)) {
-          config[key].push(
-            await resolveConfigPresets(element, ignorePresets, existingPresets)
+          (config[key] as RenovateConfig[]).push(
+            await resolveConfigPresets(
+              element as RenovateConfig,
+              ignorePresets,
+              existingPresets
+            )
           );
         } else {
-          config[key].push(element);
+          (config[key] as RenovateConfig[]).push(element);
         }
       }
     } else if (is.object(val) && !ignoredKeys.includes(key)) {
       // Resolve nested objects
       logger.trace(`Resolving object "${key}"`);
       config[key] = await resolveConfigPresets(
-        val,
+        val as RenovateConfig,
         ignorePresets,
         existingPresets
       );
diff --git a/lib/config/utils.ts b/lib/config/utils.ts
index a514874f1f..5a85746162 100644
--- a/lib/config/utils.ts
+++ b/lib/config/utils.ts
@@ -3,10 +3,10 @@ import { logger } from '../logger';
 import { clone } from '../util/clone';
 import * as definitions from './definitions';
 
-export function mergeChildConfig<
-  T extends RenovateConfig = RenovateConfig,
-  TChild extends RenovateConfig = RenovateConfig
->(parent: T, child: TChild): T & TChild {
+export function mergeChildConfig<T, TChild>(
+  parent: T,
+  child: TChild
+): T & TChild {
   logger.trace({ parent, child }, `mergeChildConfig`);
   if (!child) {
     return parent as never;
@@ -22,13 +22,13 @@ export function mergeChildConfig<
     ) {
       logger.trace(`mergeable option: ${option.name}`);
       if (option.type === 'array') {
-        config[option.name] = parentConfig[option.name].concat(
+        config[option.name] = (parentConfig[option.name] as unknown[]).concat(
           config[option.name]
         );
       } else {
         config[option.name] = mergeChildConfig(
-          parentConfig[option.name],
-          childConfig[option.name]
+          parentConfig[option.name] as RenovateConfig,
+          childConfig[option.name] as RenovateConfig
         );
       }
       logger.trace(
diff --git a/lib/config/validation.ts b/lib/config/validation.ts
index 70e99520d1..694ec8f9e5 100644
--- a/lib/config/validation.ts
+++ b/lib/config/validation.ts
@@ -93,7 +93,7 @@ export async function validateConfig(
           message: `Invalid configuration option: ${currentPath}`,
         });
       } else if (key === 'schedule') {
-        const [validSchedule, errorMessage] = hasValidSchedule(val);
+        const [validSchedule, errorMessage] = hasValidSchedule(val as string[]);
         if (!validSchedule) {
           errors.push({
             depName: 'Configuration Error',
@@ -101,7 +101,7 @@ export async function validateConfig(
           });
         }
       } else if (key === 'timezone' && val !== null) {
-        const [validTimezone, errorMessage] = hasValidTimezone(val);
+        const [validTimezone, errorMessage] = hasValidTimezone(val as string);
         if (!validTimezone) {
           errors.push({
             depName: 'Configuration Error',
@@ -173,7 +173,9 @@ export async function validateConfig(
               for (const packageRule of val) {
                 let hasSelector = false;
                 if (is.object(packageRule)) {
-                  const resolvedRule = await resolveConfigPresets(packageRule);
+                  const resolvedRule = await resolveConfigPresets(
+                    packageRule as RenovateConfig
+                  );
                   errors.push(
                     ...managerValidator.check({ resolvedRule, currentPath })
                   );
diff --git a/lib/datasource/docker/index.ts b/lib/datasource/docker/index.ts
index 1000420522..b0f80b414e 100644
--- a/lib/datasource/docker/index.ts
+++ b/lib/datasource/docker/index.ts
@@ -10,6 +10,7 @@ import got from '../../util/got';
 import * as hostRules from '../../util/host-rules';
 import { DatasourceError, GetReleasesConfig, ReleaseResult } from '../common';
 import { GotResponse } from '../../platform';
+import { HostRule } from '../../types';
 
 // TODO: add got typings when available
 // TODO: replace www-authenticate with https://www.npmjs.com/package/auth-header ?
@@ -58,7 +59,7 @@ export function getRegistryRepository(
 
 function getECRAuthToken(
   region: string,
-  opts: hostRules.HostRule
+  opts: HostRule
 ): Promise<string | null> {
   const config = { region, accessKeyId: undefined, secretAccessKey: undefined };
   if (opts.username && opts.password) {
@@ -105,7 +106,7 @@ async function getAuthHeaders(
       apiCheckResponse.headers['www-authenticate']
     );
 
-    const opts: hostRules.HostRule & {
+    const opts: HostRule & {
       headers?: Record<string, string>;
     } = hostRules.find({ hostType: id, url: apiCheckUrl });
     opts.json = true;
diff --git a/lib/manager/bazel/update.spec.ts b/lib/manager/bazel/update.spec.ts
index 5265692a25..f0ad57a428 100644
--- a/lib/manager/bazel/update.spec.ts
+++ b/lib/manager/bazel/update.spec.ts
@@ -2,6 +2,7 @@ import { readFileSync } from 'fs';
 import { fromStream as _fromStream } from 'hasha';
 import { resolve } from 'path';
 import { updateDependency } from './update';
+import { UpdateType } from '../../config';
 
 jest.mock('hasha');
 jest.mock('../../util/got');
@@ -99,7 +100,7 @@ describe('manager/bazel/update', () => {
         currentDigest: 'dec09d789f3dba190787f8b4454c7d3c936fed9e',
         newDigest: 'aaa09d789f3dba190787f8b4454c7d3c936fe123',
         newValue: 'v1.0.3',
-        updateType: 'major',
+        updateType: 'major' as UpdateType,
       };
       const res = await updateDependency({
         fileContent: content,
diff --git a/lib/manager/common.ts b/lib/manager/common.ts
index c0ddd4ce6f..1ffb55469b 100644
--- a/lib/manager/common.ts
+++ b/lib/manager/common.ts
@@ -1,6 +1,6 @@
 import { ReleaseType } from 'semver';
 import { RangeStrategy } from '../types';
-import { ValidationMessage } from '../config/common';
+import { ValidationMessage, GlobalConfig, UpdateType } from '../config/common';
 
 export type Result<T> = T | Promise<T>;
 
@@ -17,7 +17,7 @@ export interface ManagerData<T> {
 
 export interface ExtractConfig extends ManagerConfig {
   endpoint?: string;
-  global?: any;
+  global?: GlobalConfig;
   gradle?: { timeout?: number };
   aliases?: Record<string, string>;
   ignoreNpmrcFile?: boolean;
@@ -132,6 +132,8 @@ export interface PackageDependency<T = Record<string, any>> extends Package<T> {
   datasource?: string;
   deprecationMessage?: string;
   digestOneAndOnly?: boolean;
+  displayFrom?: string;
+  displayTo?: string;
   fromVersion?: string;
   lockedVersion?: string;
   moduleName?: string;
@@ -141,6 +143,7 @@ export interface PackageDependency<T = Record<string, any>> extends Package<T> {
   skipReason?: string;
   source?: string;
   sourceLine?: number;
+  toVersion?: string;
   updates?: PackageUpdateResult[];
   versionLine?: number;
   autoReplaceData?: AutoReplaceData;
@@ -166,7 +169,7 @@ export interface Upgrade<T = Record<string, any>>
   packageFile?: string;
   rangeStrategy?: RangeStrategy;
   toVersion?: string;
-  updateType?: string;
+  updateType?: UpdateType;
   version?: string;
 }
 
diff --git a/lib/manager/gomod/update.spec.ts b/lib/manager/gomod/update.spec.ts
index 16a2a124ba..615c9fb6f0 100644
--- a/lib/manager/gomod/update.spec.ts
+++ b/lib/manager/gomod/update.spec.ts
@@ -1,5 +1,6 @@
 import { readFileSync } from 'fs';
 import { updateDependency } from './update';
+import { UpdateType } from '../../config';
 
 const gomod1 = readFileSync('lib/manager/gomod/__fixtures__/1/go.mod', 'utf8');
 const gomod2 = readFileSync('lib/manager/gomod/__fixtures__/2/go.mod', 'utf8');
@@ -57,7 +58,7 @@ describe('manager/gomod/update', () => {
         depName: 'github.com/pkg/errors',
         managerData: { lineNumber: 2 },
         newMajor: 2,
-        updateType: 'major',
+        updateType: 'major' as UpdateType,
         currentValue: 'v0.7.0',
         newValue: 'v2.0.0',
         depType: 'require',
@@ -72,7 +73,7 @@ describe('manager/gomod/update', () => {
         depName: 'gopkg.in/russross/blackfriday.v1',
         managerData: { lineNumber: 7 },
         newMajor: 2,
-        updateType: 'major',
+        updateType: 'major' as UpdateType,
         currentValue: 'v1.0.0',
         newValue: 'v2.0.0',
         depType: 'require',
@@ -127,7 +128,7 @@ describe('manager/gomod/update', () => {
         currentValue: 'v1.9.0',
         newValue: 'v2.0.0',
         newMajor: 2,
-        updateType: 'major',
+        updateType: 'major' as UpdateType,
         depType: 'require',
       };
       const res = updateDependency({ fileContent: gomod2, upgrade });
@@ -142,7 +143,7 @@ describe('manager/gomod/update', () => {
         currentValue: 'v2.3.0',
         newValue: 'v3.0.0',
         newMajor: 3,
-        updateType: 'major',
+        updateType: 'major' as UpdateType,
         depType: 'require',
       };
       const res = updateDependency({ fileContent: gomod2, upgrade });
@@ -155,7 +156,7 @@ describe('manager/gomod/update', () => {
         depName: 'github.com/spf13/jwalterweatherman',
         managerData: { lineNumber: 43, multiLine: true },
         currentVersion: 'v0.0.0',
-        updateType: 'digest',
+        updateType: 'digest' as UpdateType,
         currentDigest: '14d3d4c51834',
         newDigest: '123456123456abcdef',
         depType: 'require',
@@ -170,7 +171,7 @@ describe('manager/gomod/update', () => {
         depName: 'github.com/spf13/jwalterweatherman',
         managerData: { lineNumber: 43, multiLine: true },
         currentVersion: 'v0.0.0',
-        updateType: 'digest',
+        updateType: 'digest' as UpdateType,
         currentDigest: 'abcdefabcdef',
         newDigest: '14d3d4c51834000000',
         depType: 'require',
@@ -219,7 +220,7 @@ describe('manager/gomod/update', () => {
         depType: 'replace',
         currentValue: 'v0.7.0',
         newMajor: 2,
-        updateType: 'major',
+        updateType: 'major' as UpdateType,
       };
       const res = updateDependency({ fileContent: gomod1, upgrade });
       expect(res).not.toEqual(gomod1);
@@ -233,7 +234,7 @@ describe('manager/gomod/update', () => {
         depType: 'replace',
         currentValue: 'v0.7.0',
         newMajor: 2,
-        updateType: 'digest',
+        updateType: 'digest' as UpdateType,
         currentDigest: '14d3d4c51834',
         newDigest: '123456123456abcdef',
       };
@@ -249,7 +250,7 @@ describe('manager/gomod/update', () => {
         depType: 'require',
         currentValue: 'v3.5.0+incompatible',
         newMajor: 6,
-        updateType: 'major',
+        updateType: 'major' as UpdateType,
       };
       const res = updateDependency({ fileContent: gomod1, upgrade });
       expect(res).not.toEqual(gomod1);
diff --git a/lib/types/host-rules.ts b/lib/types/host-rules.ts
new file mode 100644
index 0000000000..23081f0deb
--- /dev/null
+++ b/lib/types/host-rules.ts
@@ -0,0 +1,15 @@
+export interface HostRule {
+  endpoint?: string;
+  host?: string;
+  hostType?: string;
+  domainName?: string;
+  hostName?: string;
+  json?: true;
+  baseUrl?: string;
+  token?: string;
+  username?: string;
+  password?: string;
+  insecureRegistry?: boolean;
+  platform?: string;
+  timeout?: number;
+}
diff --git a/lib/types/index.ts b/lib/types/index.ts
index 668de19dbd..fc18cdda86 100644
--- a/lib/types/index.ts
+++ b/lib/types/index.ts
@@ -1 +1,2 @@
+export * from './host-rules';
 export * from './versioning';
diff --git a/lib/util/host-rules.ts b/lib/util/host-rules.ts
index 83080e3afc..fb5490dd6b 100644
--- a/lib/util/host-rules.ts
+++ b/lib/util/host-rules.ts
@@ -2,19 +2,7 @@ import URL from 'url';
 import merge from 'deepmerge';
 import { logger } from '../logger';
 import * as sanitize from './sanitize';
-
-export interface HostRule {
-  hostType?: string;
-  domainName?: string;
-  hostName?: string;
-  json?: true;
-  baseUrl?: string;
-  token?: string;
-  username?: string;
-  password?: string;
-  insecureRegistry?: boolean;
-  timeout?: number;
-}
+import { HostRule } from '../types';
 
 let hostRules: HostRule[] = [];
 
diff --git a/lib/workers/branch/check-existing.ts b/lib/workers/branch/check-existing.ts
index 9f6236090d..011c23ed7c 100644
--- a/lib/workers/branch/check-existing.ts
+++ b/lib/workers/branch/check-existing.ts
@@ -1,11 +1,11 @@
 import { logger } from '../../logger';
-import { RenovateConfig } from '../../config';
 import { platform } from '../../platform';
 import { REPOSITORY_CHANGED } from '../../constants/error-messages';
+import { BranchConfig } from '../common';
 
 /** TODO: Proper return type */
 export async function prAlreadyExisted(
-  config: RenovateConfig
+  config: BranchConfig
 ): Promise<any | null> {
   logger.trace({ config }, 'prAlreadyExisted');
   if (config.recreateClosed) {
diff --git a/lib/workers/branch/commit.ts b/lib/workers/branch/commit.ts
index df1a42e223..23c08fbcfb 100644
--- a/lib/workers/branch/commit.ts
+++ b/lib/workers/branch/commit.ts
@@ -1,20 +1,11 @@
 import is from '@sindresorhus/is';
 import minimatch from 'minimatch';
-import { FileData, platform } from '../../platform';
+import { platform } from '../../platform';
 import { logger } from '../../logger';
-import { RenovateConfig } from '../../config';
-
-export type CommitConfig = RenovateConfig & {
-  baseBranch?: string;
-  branchName: string;
-  commitMessage: string;
-  excludeCommitPaths?: string[];
-  updatedPackageFiles: FileData[];
-  updatedArtifacts: FileData[];
-};
+import { BranchConfig } from '../common';
 
 export async function commitFilesToBranch(
-  config: CommitConfig
+  config: BranchConfig
 ): Promise<string | null> {
   let updatedFiles = config.updatedPackageFiles.concat(config.updatedArtifacts);
   // istanbul ignore if
diff --git a/lib/workers/branch/get-updated.ts b/lib/workers/branch/get-updated.ts
index 3d51141ff9..26274f7d9e 100644
--- a/lib/workers/branch/get-updated.ts
+++ b/lib/workers/branch/get-updated.ts
@@ -2,11 +2,11 @@ import is from '@sindresorhus/is';
 import { FileData, platform } from '../../platform';
 import { logger } from '../../logger';
 import { get } from '../../manager';
-import { RenovateConfig } from '../../config';
-import { UpdateArtifactsConfig, ArtifactError } from '../../manager/common';
+import { ArtifactError } from '../../manager/common';
 import { WORKER_FILE_UPDATE_FAILED } from '../../constants/error-messages';
 import * as datasourceGitSubmodules from '../../datasource/git-submodules';
 import { doAutoReplace } from './auto-replace';
+import { BranchConfig } from '../common';
 
 export interface PackageFilesResult {
   artifactErrors: ArtifactError[];
@@ -16,7 +16,7 @@ export interface PackageFilesResult {
 }
 
 export async function getUpdatedPackageFiles(
-  config: RenovateConfig & UpdateArtifactsConfig
+  config: BranchConfig
 ): Promise<PackageFilesResult> {
   logger.debug('manager.getUpdatedPackageFiles()');
   logger.trace({ config });
diff --git a/lib/workers/branch/index.ts b/lib/workers/branch/index.ts
index d298ff2370..07a8707c48 100644
--- a/lib/workers/branch/index.ts
+++ b/lib/workers/branch/index.ts
@@ -19,7 +19,7 @@ import { ensurePr, checkAutoMerge } from '../pr';
 import { RenovateConfig } from '../../config';
 import { platform } from '../../platform';
 import { emojify } from '../../util/emoji';
-import { BranchConfig } from '../common';
+import { BranchConfig, ProcessBranchResult } from '../common';
 import {
   PLATFORM_AUTHENTICATION_ERROR,
   PLATFORM_BAD_CREDENTIALS,
@@ -36,20 +36,6 @@ import { BRANCH_STATUS_FAILURE } from '../../constants/branch-constants';
 import { exec } from '../../util/exec';
 import { regEx } from '../../util/regex';
 
-export type ProcessBranchResult =
-  | 'already-existed'
-  | 'automerged'
-  | 'done'
-  | 'error'
-  | 'needs-approval'
-  | 'needs-pr-approval'
-  | 'not-scheduled'
-  | 'no-work'
-  | 'pending'
-  | 'pr-created'
-  | 'pr-edited'
-  | 'pr-hourly-limit-reached';
-
 // TODO: proper typings
 function rebaseCheck(config: RenovateConfig, branchPr: any): boolean {
   const titleRebase = branchPr.title && branchPr.title.startsWith('rebase!');
diff --git a/lib/workers/common.ts b/lib/workers/common.ts
index 052d359ec7..6d070b2d8c 100644
--- a/lib/workers/common.ts
+++ b/lib/workers/common.ts
@@ -1,21 +1,76 @@
-import { PrBodyUpgrade, PrBodyConfig } from './pr/body/common';
-import { PackageDependency } from '../manager/common';
-import { ChangeLogConfig } from './pr/changelog';
-import { RenovateSharedConfig } from '../config';
-import { StabilityConfig, UnpublishableConfig } from './branch/status-checks';
-import { CommitConfig } from './branch/commit';
-
-export type PrUpgrade = PrBodyUpgrade &
-  PackageDependency &
-  ChangeLogConfig &
-  PrBodyConfig & {
-    manager?: string;
-    hasUrls?: boolean;
-    githubName?: string | undefined;
-  };
-
-export type BranchConfig = RenovateSharedConfig &
-  StabilityConfig &
-  UnpublishableConfig &
-  CommitConfig &
-  PrBodyConfig<PrUpgrade>;
+import { Merge } from 'type-fest';
+import { PackageDependency, ArtifactError } from '../manager/common';
+import {
+  RenovateSharedConfig,
+  RenovateConfig,
+  GroupConfig,
+  RenovateAdminConfig,
+  ValidationMessage,
+} from '../config';
+import { LookupUpdate } from './repository/process/lookup/common';
+import { FileData, PlatformPrOptions } from '../platform';
+import { Release } from '../datasource';
+
+export interface BranchUpgradeConfig
+  extends Merge<RenovateConfig, PackageDependency>,
+    Partial<LookupUpdate>,
+    RenovateSharedConfig {
+  artifactErrors?: ArtifactError[];
+  branchName: string;
+  commitMessage?: string;
+  currentDigest?: string;
+  currentDigestShort?: string;
+  currentValue?: string;
+  currentVersion?: string;
+
+  endpoint?: string;
+  excludeCommitPaths?: string[];
+  group?: GroupConfig;
+
+  groupName?: string;
+  groupSlug?: string;
+  language?: string;
+  manager?: string;
+  packageFile?: string;
+
+  parentBranch?: string;
+  prBodyNotes?: string[];
+  prPriority?: number;
+  prTitle?: string;
+  releases?: Release[];
+  releaseTimestamp?: string;
+
+  sourceDirectory?: string;
+  updatedPackageFiles?: FileData[];
+  updatedArtifacts?: FileData[];
+}
+
+export type ProcessBranchResult =
+  | 'already-existed'
+  | 'automerged'
+  | 'done'
+  | 'error'
+  | 'needs-approval'
+  | 'needs-pr-approval'
+  | 'not-scheduled'
+  | 'no-work'
+  | 'pending'
+  | 'pr-created'
+  | 'pr-edited'
+  | 'pr-hourly-limit-reached'
+  | 'rebase';
+
+export interface BranchConfig
+  extends BranchUpgradeConfig,
+    RenovateAdminConfig,
+    PlatformPrOptions {
+  automergeType?: string;
+  baseBranch?: string;
+  canBeUnpublished?: boolean;
+  errors?: ValidationMessage[];
+  hasTypes?: boolean;
+  releaseTimestamp?: string;
+
+  res?: ProcessBranchResult;
+  upgrades: BranchUpgradeConfig[];
+}
diff --git a/lib/workers/pr/body/banner.ts b/lib/workers/pr/body/banner.ts
index e25fdd6f3c..57dca7f20c 100644
--- a/lib/workers/pr/body/banner.ts
+++ b/lib/workers/pr/body/banner.ts
@@ -1,8 +1,8 @@
 import handlebars from 'handlebars';
-import { PrBodyConfig } from './common';
+import { BranchConfig } from '../../common';
 
 // istanbul ignore next
-export function getPrBanner(config: PrBodyConfig): string {
+export function getPrBanner(config: BranchConfig): string {
   if (config.global && config.global.prBanner) {
     return handlebars.compile(config.global.prBanner)(config) + '\n\n';
   }
diff --git a/lib/workers/pr/body/changelogs.ts b/lib/workers/pr/body/changelogs.ts
index 36a13313db..62361663f0 100644
--- a/lib/workers/pr/body/changelogs.ts
+++ b/lib/workers/pr/body/changelogs.ts
@@ -1,8 +1,8 @@
 import handlebars from 'handlebars';
 import releaseNotesHbs from '../changelog/hbs-template';
-import { PrBodyConfig } from './common';
+import { BranchConfig } from '../../common';
 
-export function getChangelogs(config: PrBodyConfig): string {
+export function getChangelogs(config: BranchConfig): string {
   let releaseNotes = '';
   // istanbul ignore if
   if (!config.hasReleaseNotes) {
diff --git a/lib/workers/pr/body/common.ts b/lib/workers/pr/body/common.ts
deleted file mode 100644
index 1e70914c6f..0000000000
--- a/lib/workers/pr/body/common.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { LookupUpdate } from '../../repository/process/lookup/common';
-import { RenovateSharedConfig } from '../../../config';
-import { Release, ReleaseResult } from '../../../datasource';
-
-export type PrBodyUpgrade = LookupUpdate &
-  Release &
-  ReleaseResult & {
-    prBodyNotes?: string[];
-    depName?: string;
-    depNameLinked?: string;
-    references?: string;
-    versioning: string;
-    stabilityDays?: number;
-  };
-
-// TODO: Unify and optimize types and interfaces
-export type PrBodyConfig<T extends PrBodyUpgrade = PrBodyUpgrade> = {
-  upgrades: T[];
-  prBanner?: string;
-  prBodyTemplate: string;
-  prBodyColumns: string[];
-  prBodyDefinitions: Record<string, string>;
-  prTitle?: string;
-  updateType: string;
-  isGroup?: boolean;
-  isPin?: boolean;
-  hasReleaseNotes?: boolean;
-  global?: { prBanner?: string; prFooter?: string };
-} & Partial<RenovateSharedConfig>;
diff --git a/lib/workers/pr/body/config-description.ts b/lib/workers/pr/body/config-description.ts
index 1f087bcd3a..fc187c82c6 100644
--- a/lib/workers/pr/body/config-description.ts
+++ b/lib/workers/pr/body/config-description.ts
@@ -1,10 +1,10 @@
 import { platform } from '../../../platform';
 import { emojify } from '../../../util/emoji';
-import { PrBodyConfig } from './common';
+import { BranchConfig } from '../../common';
 import { BRANCH_STATUS_FAILED } from '../../../constants/branch-constants';
 
 export async function getPrConfigDescription(
-  config: PrBodyConfig
+  config: BranchConfig
 ): Promise<string> {
   let prBody = `\n\n---\n\n### Renovate configuration\n\n`;
   prBody += emojify(`:date: **Schedule**: `);
diff --git a/lib/workers/pr/body/footer.ts b/lib/workers/pr/body/footer.ts
index 6bd7f2bf46..ee49fb0343 100644
--- a/lib/workers/pr/body/footer.ts
+++ b/lib/workers/pr/body/footer.ts
@@ -1,8 +1,8 @@
 import handlebars from 'handlebars';
-import { PrBodyConfig } from './common';
+import { BranchConfig } from '../../common';
 
 // istanbul ignore next
-export function getPrFooter(config: PrBodyConfig): string {
+export function getPrFooter(config: BranchConfig): string {
   if (config.global && config.global.prFooter) {
     return '\n---\n\n' + handlebars.compile(config.global.prFooter)(config);
   }
diff --git a/lib/workers/pr/body/index.ts b/lib/workers/pr/body/index.ts
index 7d7d390323..6d36b4bd49 100644
--- a/lib/workers/pr/body/index.ts
+++ b/lib/workers/pr/body/index.ts
@@ -8,11 +8,11 @@ import { getPrUpdatesTable } from './updates-table';
 import { getPrNotes, getPrExtraNotes } from './notes';
 import { getChangelogs } from './changelogs';
 import { getControls } from './controls';
-import { PrBodyConfig } from './common';
+import { BranchConfig } from '../../common';
 
 handlebars.registerHelper('encodeURIComponent', encodeURIComponent);
 
-function massageUpdateMetadata(config: PrBodyConfig): void {
+function massageUpdateMetadata(config: BranchConfig): void {
   config.upgrades.forEach(upgrade => {
     /* eslint-disable no-param-reassign */
     const { homepage, sourceUrl, sourceDirectory, changelogUrl } = upgrade;
@@ -66,7 +66,7 @@ function massageUpdateMetadata(config: PrBodyConfig): void {
   });
 }
 
-export async function getPrBody(config: PrBodyConfig): Promise<string> {
+export async function getPrBody(config: BranchConfig): Promise<string> {
   massageUpdateMetadata(config);
   const content = {
     banner: getPrBanner(config),
diff --git a/lib/workers/pr/body/notes.ts b/lib/workers/pr/body/notes.ts
index ba0b619ae7..60d8348be9 100644
--- a/lib/workers/pr/body/notes.ts
+++ b/lib/workers/pr/body/notes.ts
@@ -2,9 +2,9 @@ import is from '@sindresorhus/is';
 import handlebars from 'handlebars';
 import { logger } from '../../../logger';
 import { emojify } from '../../../util/emoji';
-import { PrBodyConfig } from './common';
+import { BranchConfig } from '../../common';
 
-export function getPrNotes(config: PrBodyConfig): string {
+export function getPrNotes(config: BranchConfig): string {
   const notes = [];
   for (const upgrade of config.upgrades) {
     if (is.nonEmptyArray(upgrade.prBodyNotes)) {
@@ -26,7 +26,7 @@ export function getPrNotes(config: PrBodyConfig): string {
   return uniqueNotes.join('\n\n') + '\n\n';
 }
 
-export function getPrExtraNotes(config: PrBodyConfig): string {
+export function getPrExtraNotes(config: BranchConfig): string {
   let res = '';
   if (config.upgrades.some(upgrade => upgrade.gitRef)) {
     res += emojify(
diff --git a/lib/workers/pr/body/updates-table.ts b/lib/workers/pr/body/updates-table.ts
index e9df72f8de..c35dc3e85c 100644
--- a/lib/workers/pr/body/updates-table.ts
+++ b/lib/workers/pr/body/updates-table.ts
@@ -1,13 +1,13 @@
 import handlebars from 'handlebars';
 import { logger } from '../../../logger';
-import { PrBodyConfig } from './common';
+import { BranchConfig } from '../../common';
 
 type TableDefinition = {
   header: string;
   value: string;
 };
 
-function getTableDefinition(config: PrBodyConfig): TableDefinition[] {
+function getTableDefinition(config: BranchConfig): TableDefinition[] {
   const res = [];
   for (const header of config.prBodyColumns) {
     const value = config.prBodyDefinitions[header];
@@ -34,7 +34,7 @@ function getNonEmptyColumns(
   return res;
 }
 
-export function getPrUpdatesTable(config: PrBodyConfig): string {
+export function getPrUpdatesTable(config: BranchConfig): string {
   const tableDefinitions = getTableDefinition(config);
   const tableValues = config.upgrades.map(upgrade => {
     const res: Record<string, string> = {};
diff --git a/lib/workers/pr/changelog/common.ts b/lib/workers/pr/changelog/common.ts
index 0d5b54fbf6..adb98a3209 100644
--- a/lib/workers/pr/changelog/common.ts
+++ b/lib/workers/pr/changelog/common.ts
@@ -1,5 +1,3 @@
-import { Release } from '../../../datasource';
-
 export interface ChangeLogNotes {
   body?: string;
   id?: number;
@@ -40,16 +38,3 @@ export interface ChangeLogResult {
   versions?: ChangeLogRelease[];
   error?: ChangeLogError;
 }
-
-export interface ChangeLogConfig {
-  depName: string;
-  depType?: string;
-  endpoint: string;
-  fromVersion: string;
-  manager?: string;
-  releases: Release[];
-  sourceUrl?: string;
-  toVersion: string;
-  versioning: string;
-  changeLogError?: ChangeLogError;
-}
diff --git a/lib/workers/pr/changelog/index.ts b/lib/workers/pr/changelog/index.ts
index bb66f1d32a..76b3f4083f 100644
--- a/lib/workers/pr/changelog/index.ts
+++ b/lib/workers/pr/changelog/index.ts
@@ -2,12 +2,13 @@ import { logger } from '../../../logger';
 import * as allVersioning from '../../../versioning';
 import * as sourceGithub from './source-github';
 import { getInRangeReleases } from './releases';
-import { ChangeLogConfig, ChangeLogResult } from './common';
+import { ChangeLogResult } from './common';
+import { BranchUpgradeConfig } from '../../common';
 
 export * from './common';
 
 export async function getChangeLogJSON(
-  args: ChangeLogConfig
+  args: BranchUpgradeConfig
 ): Promise<ChangeLogResult | null> {
   const { sourceUrl, versioning, fromVersion, toVersion } = args;
   if (!sourceUrl) {
diff --git a/lib/workers/pr/changelog/releases.ts b/lib/workers/pr/changelog/releases.ts
index 8092906ba0..ba9bbe9edd 100644
--- a/lib/workers/pr/changelog/releases.ts
+++ b/lib/workers/pr/changelog/releases.ts
@@ -1,6 +1,7 @@
-import { getPkgReleases, Release, PkgReleaseConfig } from '../../../datasource';
+import { getPkgReleases, Release } from '../../../datasource';
 import { logger } from '../../../logger';
 import { get, VersioningApi } from '../../../versioning';
+import { BranchUpgradeConfig } from '../../common';
 
 function matchesMMP(version: VersioningApi, v1: string, v2: string): boolean {
   return (
@@ -18,15 +19,8 @@ function matchesUnstable(
   return !version.isStable(v1) && matchesMMP(version, v1, v2);
 }
 
-export type ReleaseConfig = PkgReleaseConfig & {
-  fromVersion: string;
-  releases?: Release[];
-  sourceUrl?: string;
-  toVersion: string;
-};
-
 export async function getInRangeReleases(
-  config: ReleaseConfig
+  config: BranchUpgradeConfig
 ): Promise<Release[] | null> {
   const { versioning, fromVersion, toVersion, depName, datasource } = config;
   try {
diff --git a/lib/workers/pr/changelog/source-github.ts b/lib/workers/pr/changelog/source-github.ts
index eec4e9bdf8..acf1143da8 100644
--- a/lib/workers/pr/changelog/source-github.ts
+++ b/lib/workers/pr/changelog/source-github.ts
@@ -4,14 +4,10 @@ import { logger } from '../../../logger';
 import * as hostRules from '../../../util/host-rules';
 import * as allVersioning from '../../../versioning';
 import { addReleaseNotes } from './release-notes';
-import {
-  ChangeLogConfig,
-  ChangeLogError,
-  ChangeLogRelease,
-  ChangeLogResult,
-} from './common';
+import { ChangeLogError, ChangeLogRelease, ChangeLogResult } from './common';
 import { Release } from '../../../datasource';
 import { PLATFORM_TYPE_GITHUB } from '../../../constants/platforms';
+import { BranchUpgradeConfig } from '../../common';
 
 const { get: ghGot } = api;
 
@@ -57,7 +53,7 @@ export async function getChangeLogJSON({
   releases,
   depName,
   manager,
-}: ChangeLogConfig): Promise<ChangeLogResult | null> {
+}: BranchUpgradeConfig): Promise<ChangeLogResult | null> {
   if (sourceUrl === 'https://github.com/DefinitelyTyped/DefinitelyTyped') {
     logger.debug('No release notes for @types');
     return null;
diff --git a/lib/workers/pr/index.ts b/lib/workers/pr/index.ts
index 8abad5b271..9ccac90650 100644
--- a/lib/workers/pr/index.ts
+++ b/lib/workers/pr/index.ts
@@ -3,7 +3,7 @@ import uniq from 'lodash/uniq';
 import { logger } from '../../logger';
 import { ChangeLogError, getChangeLogJSON } from './changelog';
 import { getPrBody } from './body';
-import { BranchStatus, platform, Pr } from '../../platform';
+import { BranchStatus, platform, Pr, PlatformPrOptions } from '../../platform';
 import { BranchConfig } from '../common';
 import {
   PLATFORM_FAILURE,
@@ -343,7 +343,7 @@ export async function ensurePr(
         logger.info('DRY-RUN: Would create PR: ' + prTitle);
         pr = { number: 0, displayNumber: 'Dry run PR' } as never;
       } else {
-        const platformOptions = {
+        const platformOptions: PlatformPrOptions = {
           azureAutoComplete: config.azureAutoComplete,
           statusCheckVerify: config.statusCheckVerify,
           gitLabAutomerge:
diff --git a/lib/workers/repository/onboarding/pr/index.ts b/lib/workers/repository/onboarding/pr/index.ts
index f9d59580e2..86004ab715 100644
--- a/lib/workers/repository/onboarding/pr/index.ts
+++ b/lib/workers/repository/onboarding/pr/index.ts
@@ -4,15 +4,16 @@ import { logger } from '../../../../logger';
 import { getConfigDesc } from './config-description';
 import { getErrors, getWarnings, getDepWarnings } from './errors-warnings';
 import { getBaseBranchDesc } from './base-branch';
-import { getPrList, PrBranchConfig } from './pr-list';
+import { getPrList } from './pr-list';
 import { emojify } from '../../../../util/emoji';
 import { RenovateConfig } from '../../../../config';
 import { PackageFile } from '../../../../manager/common';
+import { BranchConfig } from '../../../common';
 
 export async function ensureOnboardingPr(
   config: RenovateConfig,
   packageFiles: Record<string, PackageFile[]> | null,
-  branches: PrBranchConfig[]
+  branches: BranchConfig[]
 ): Promise<void> {
   if (config.repoIsOnboarded) {
     return;
diff --git a/lib/workers/repository/onboarding/pr/pr-list.ts b/lib/workers/repository/onboarding/pr/pr-list.ts
index 5f8908e4d1..81bf98744c 100644
--- a/lib/workers/repository/onboarding/pr/pr-list.ts
+++ b/lib/workers/repository/onboarding/pr/pr-list.ts
@@ -3,14 +3,9 @@ import { logger } from '../../../../logger';
 import { RenovateConfig } from '../../../../config';
 import { BranchConfig } from '../../../common';
 
-export type PrBranchConfig = Pick<
-  BranchConfig,
-  'upgrades' | 'baseBranch' | 'branchName' | 'schedule' | 'prTitle'
->;
-
 export function getPrList(
   config: RenovateConfig,
-  branches: PrBranchConfig[]
+  branches: BranchConfig[]
 ): string {
   logger.debug('getPrList()');
   logger.trace({ config });
diff --git a/lib/workers/repository/process/limits.ts b/lib/workers/repository/process/limits.ts
index 1b4e395d92..77ad824ee2 100644
--- a/lib/workers/repository/process/limits.ts
+++ b/lib/workers/repository/process/limits.ts
@@ -4,9 +4,6 @@ import { platform } from '../../../platform';
 import { RenovateConfig } from '../../../config';
 import { BranchConfig } from '../../common';
 
-export type LimitBranchConfig = Pick<BranchConfig, 'branchName'> &
-  Partial<BranchConfig>;
-
 export async function getPrHourlyRemaining(
   config: RenovateConfig
 ): Promise<number> {
@@ -44,7 +41,7 @@ export async function getPrHourlyRemaining(
 
 export async function getConcurrentPrsRemaining(
   config: RenovateConfig,
-  branches: LimitBranchConfig[]
+  branches: BranchConfig[]
 ): Promise<number> {
   if (config.prConcurrentLimit) {
     logger.debug(`Enforcing prConcurrentLimit (${config.prConcurrentLimit})`);
@@ -64,7 +61,7 @@ export async function getConcurrentPrsRemaining(
 
 export async function getPrsRemaining(
   config: RenovateConfig,
-  branches: LimitBranchConfig[]
+  branches: BranchConfig[]
 ): Promise<number> {
   const hourlyRemaining = await getPrHourlyRemaining(config);
   const concurrentRemaining = await getConcurrentPrsRemaining(config, branches);
diff --git a/lib/workers/repository/process/lookup/common.ts b/lib/workers/repository/process/lookup/common.ts
index d018bb90d5..cafb0d2a18 100644
--- a/lib/workers/repository/process/lookup/common.ts
+++ b/lib/workers/repository/process/lookup/common.ts
@@ -1,3 +1,5 @@
+import { UpdateType } from '../../../../config';
+
 export interface LookupUpdate {
   blockedByPin?: boolean;
   branchName?: string;
@@ -18,5 +20,5 @@ export interface LookupUpdate {
   newVersion?: string;
   semanticCommitType?: string;
   toVersion?: string;
-  updateType: string;
+  updateType: UpdateType;
 }
diff --git a/lib/workers/repository/process/lookup/index.ts b/lib/workers/repository/process/lookup/index.ts
index 95d7ad3be6..f33389e55a 100644
--- a/lib/workers/repository/process/lookup/index.ts
+++ b/lib/workers/repository/process/lookup/index.ts
@@ -11,7 +11,7 @@ import {
 } from '../../../../datasource';
 import { LookupUpdate } from './common';
 import { RangeConfig } from '../../../../manager/common';
-import { RenovateConfig } from '../../../../config';
+import { RenovateConfig, UpdateType } from '../../../../config';
 import { clone } from '../../../../util/clone';
 import * as datasourceGitSubmodules from '../../../../datasource/git-submodules';
 
@@ -55,7 +55,7 @@ function getType(
   config: LookupUpdateConfig,
   fromVersion: string,
   toVersion: string
-): string {
+): UpdateType {
   const { versioning, rangeStrategy, currentValue } = config;
   const version = allVersioning.get(versioning);
   if (rangeStrategy === 'bump' && version.matches(toVersion, currentValue)) {
diff --git a/lib/workers/repository/process/sort.ts b/lib/workers/repository/process/sort.ts
index b715e32546..3bab1e95c5 100644
--- a/lib/workers/repository/process/sort.ts
+++ b/lib/workers/repository/process/sort.ts
@@ -1,13 +1,7 @@
 import { logger } from '../../../logger';
 import { BranchConfig } from '../../common';
 
-export type SortBranchConfig = Pick<
-  BranchConfig,
-  'prPriority' | 'updateType' | 'prTitle'
-> &
-  Partial<BranchConfig>;
-
-export function sortBranches(branches: SortBranchConfig[]): void {
+export function sortBranches(branches: Partial<BranchConfig>[]): void {
   // Sort branches
   const sortOrder = [
     'pin',
diff --git a/lib/workers/repository/updates/branchify.ts b/lib/workers/repository/updates/branchify.ts
index 7c48a49fb0..1e05ab2306 100644
--- a/lib/workers/repository/updates/branchify.ts
+++ b/lib/workers/repository/updates/branchify.ts
@@ -1,11 +1,13 @@
 import slugify from 'slugify';
 import handlebars from 'handlebars';
 import { clean as cleanGitRef } from 'clean-git-ref';
+import { Merge } from 'type-fest';
 import { logger, addMeta, removeMeta } from '../../../logger';
 
 import { generateBranchConfig } from './generate';
 import { flattenUpdates } from './flatten';
 import { RenovateConfig, ValidationMessage } from '../../../config';
+import { BranchUpgradeConfig, BranchConfig } from '../../common';
 
 /**
  * Clean git branch name
@@ -22,11 +24,17 @@ function cleanBranchName(branchName: string): string {
     .replace(/\s/g, ''); // whitespace
 }
 
-// TODO: fix return type
+export type BranchifiedConfig = Merge<
+  RenovateConfig,
+  {
+    branches: BranchConfig[];
+    branchList: string[];
+  }
+>;
 export function branchifyUpgrades(
   config: RenovateConfig,
   packageFiles: Record<string, any[]>
-): RenovateConfig {
+): BranchifiedConfig {
   logger.debug('branchifyUpgrades');
   const updates = flattenUpdates(config, packageFiles);
   logger.debug(
@@ -36,10 +44,10 @@ export function branchifyUpgrades(
   );
   const errors: ValidationMessage[] = [];
   const warnings: ValidationMessage[] = [];
-  const branchUpgrades = {};
-  const branches = [];
+  const branchUpgrades: Record<string, BranchUpgradeConfig[]> = {};
+  const branches: BranchConfig[] = [];
   for (const u of updates) {
-    const update = { ...u };
+    const update: BranchUpgradeConfig = { ...u } as any;
     // Massage legacy vars just in case
     update.currentVersion = update.currentValue;
     update.newVersion = update.newVersion || update.newValue;
diff --git a/lib/workers/repository/updates/generate.ts b/lib/workers/repository/updates/generate.ts
index 0f1e7bfaaf..147d26f3c3 100644
--- a/lib/workers/repository/updates/generate.ts
+++ b/lib/workers/repository/updates/generate.ts
@@ -3,12 +3,8 @@ import { DateTime } from 'luxon';
 import semver from 'semver';
 import mdTable from 'markdown-table';
 import { logger } from '../../../logger';
-import {
-  mergeChildConfig,
-  ManagerConfig,
-  RenovateConfig,
-} from '../../../config';
-import { PackageDependency } from '../../../manager/common';
+import { mergeChildConfig } from '../../../config';
+import { BranchConfig, BranchUpgradeConfig } from '../../common';
 
 function ifTypesGroup(
   depNames: string[],
@@ -28,7 +24,7 @@ function ifTypesGroup(
 }
 
 function getTableValues(
-  upgrade: PackageDependency & ManagerConfig
+  upgrade: BranchUpgradeConfig
 ): [string, string, string, string] | null {
   if (!upgrade.commitBodyTable) {
     return null;
@@ -63,12 +59,14 @@ function getTableValues(
   return null;
 }
 
-export function generateBranchConfig(branchUpgrades): RenovateConfig {
+export function generateBranchConfig(
+  branchUpgrades: BranchUpgradeConfig[]
+): BranchConfig {
   logger.debug(`generateBranchConfig(${branchUpgrades.length})`);
   logger.trace({ config: branchUpgrades });
-  let config: any = {
+  let config: BranchConfig = {
     upgrades: [],
-  };
+  } as any;
   const hasGroupName = branchUpgrades[0].groupName !== null;
   logger.debug(`hasGroupName: ${hasGroupName}`);
   // Use group settings only if multiple upgrades or lazy grouping is disabled
@@ -101,9 +99,9 @@ export function generateBranchConfig(branchUpgrades): RenovateConfig {
   logger.debug(`groupEligible: ${groupEligible}`);
   const useGroupSettings = hasGroupName && groupEligible;
   logger.debug(`useGroupSettings: ${useGroupSettings}`);
-  let releaseTimestamp;
+  let releaseTimestamp: string;
   for (const branchUpgrade of branchUpgrades) {
-    let upgrade = { ...branchUpgrade };
+    let upgrade: BranchUpgradeConfig = { ...branchUpgrade };
     if (upgrade.currentDigest) {
       upgrade.currentDigestShort =
         upgrade.currentDigestShort ||
@@ -205,6 +203,7 @@ export function generateBranchConfig(branchUpgrades): RenovateConfig {
       upgrade.commitMessagePrefix = semanticPrefix;
       upgrade.commitMessagePrefix += semanticPrefix.endsWith(':') ? ' ' : ': ';
       upgrade.toLowerCase =
+        // eslint-disable-next-line @typescript-eslint/prefer-regexp-exec
         upgrade.semanticCommitType.match(/[A-Z]/) === null &&
         !upgrade.semanticCommitType.startsWith(':');
     }
@@ -304,7 +303,7 @@ export function generateBranchConfig(branchUpgrades): RenovateConfig {
     });
   }
   // Now assign first upgrade's config as branch config
-  config = { ...config, ...config.upgrades[0], releaseTimestamp };
+  config = { ...config, ...config.upgrades[0], releaseTimestamp }; // TODO: fixme
   config.canBeUnpublished = config.upgrades.some(
     upgrade => upgrade.canBeUnpublished
   );
diff --git a/test/config/migration.spec.ts b/test/config/migration.spec.ts
index 2eb9ca263b..4c1518100b 100644
--- a/test/config/migration.spec.ts
+++ b/test/config/migration.spec.ts
@@ -1,15 +1,22 @@
 import * as configMigration from '../../lib/config/migration';
 import { getConfig } from '../../lib/config/defaults';
-import { RenovateConfig } from '../../lib/config';
+import {
+  RenovateConfig as _RenovateConfig,
+  RenovateSharedConfig,
+} from '../../lib/config';
 import { PLATFORM_TYPE_GITHUB } from '../../lib/constants/platforms';
 
 const defaultConfig = getConfig();
 
+interface RenovateConfig extends _RenovateConfig {
+  node?: RenovateSharedConfig & { supportPolicy?: unknown };
+}
+
 describe('config/migration', () => {
   describe('migrateConfig(config, parentConfig)', () => {
     it('it migrates config', () => {
       const config: RenovateConfig = {
-        endpoints: [{}],
+        endpoints: [{}] as never,
         enabled: true,
         platform: PLATFORM_TYPE_GITHUB,
         hostRules: [
@@ -73,12 +80,12 @@ describe('config/migration', () => {
         packageRules: [
           {
             packagePatterns: '^(@angular|typescript)' as never,
-            groupName: ['angular packages'],
+            groupName: ['angular packages'] as never,
             excludedPackageNames: 'foo',
           },
           {
             packagePatterns: ['^foo'],
-            groupName: ['foo'],
+            groupName: ['foo'] as never,
           },
           {
             packageName: 'angular',
@@ -297,7 +304,7 @@ describe('config/migration', () => {
         node: {
           enabled: true,
           supportPolicy: ['lts'],
-          automerge: 'none',
+          automerge: 'none' as never,
         },
       };
       const { isMigrated, migratedConfig } = configMigration.migrateConfig(
@@ -306,9 +313,15 @@ describe('config/migration', () => {
       );
       expect(migratedConfig).toMatchSnapshot();
       expect(isMigrated).toBe(true);
-      expect(migratedConfig.node.enabled).toBeUndefined();
-      expect(migratedConfig.travis.enabled).toBe(true);
-      expect(migratedConfig.node.supportPolicy).toBeDefined();
+      expect(
+        (migratedConfig.node as RenovateSharedConfig).enabled
+      ).toBeUndefined();
+      expect((migratedConfig.travis as RenovateSharedConfig).enabled).toBe(
+        true
+      );
+      expect(
+        (migratedConfig.node as RenovateConfig).supportPolicy
+      ).toBeDefined();
     });
     it('it migrates packageFiles', () => {
       const config: RenovateConfig = {
diff --git a/test/workers/branch/check-existing.spec.ts b/test/workers/branch/check-existing.spec.ts
index f857d75232..61ac20beea 100644
--- a/test/workers/branch/check-existing.spec.ts
+++ b/test/workers/branch/check-existing.spec.ts
@@ -1,16 +1,16 @@
 import { prAlreadyExisted } from '../../../lib/workers/branch/check-existing';
-import { defaultConfig, platform } from '../../util';
-import { RenovateConfig } from '../../../lib/config';
+import { defaultConfig, platform, partial } from '../../util';
+import { BranchConfig } from '../../../lib/workers/common';
 
 describe('workers/branch/check-existing', () => {
   describe('prAlreadyExisted', () => {
-    let config: RenovateConfig;
+    let config: BranchConfig;
     beforeEach(() => {
-      config = {
+      config = partial<BranchConfig>({
         ...defaultConfig,
         branchName: 'some-branch',
         prTitle: 'some-title',
-      };
+      });
       jest.resetAllMocks();
     });
     it('returns false if recreating closed PRs', async () => {
diff --git a/test/workers/branch/commit.spec.ts b/test/workers/branch/commit.spec.ts
index f39c47a7a0..7b0e23d574 100644
--- a/test/workers/branch/commit.spec.ts
+++ b/test/workers/branch/commit.spec.ts
@@ -1,15 +1,12 @@
-import {
-  commitFilesToBranch,
-  CommitConfig,
-} from '../../../lib/workers/branch/commit';
-import { defaultConfig, platform } from '../../util';
-import { RenovateConfig } from '../../../lib/config';
+import { commitFilesToBranch } from '../../../lib/workers/branch/commit';
+import { defaultConfig, platform, partial } from '../../util';
+import { BranchConfig } from '../../../lib/workers/common';
 
 describe('workers/branch/automerge', () => {
   describe('commitFilesToBranch', () => {
-    let config: RenovateConfig & CommitConfig;
+    let config: BranchConfig;
     beforeEach(() => {
-      config = {
+      config = partial<BranchConfig>({
         ...defaultConfig,
         branchName: 'renovate/some-branch',
         commitMessage: 'some commit message',
@@ -18,7 +15,7 @@ describe('workers/branch/automerge', () => {
         semanticCommitScope: 'b',
         updatedPackageFiles: [],
         updatedArtifacts: [],
-      };
+      });
       jest.resetAllMocks();
       platform.commitFilesToBranch.mockResolvedValueOnce('abc123');
     });
diff --git a/test/workers/pr/changelog/index.spec.ts b/test/workers/pr/changelog/index.spec.ts
index 6a3e13057c..76e8d41b3c 100644
--- a/test/workers/pr/changelog/index.spec.ts
+++ b/test/workers/pr/changelog/index.spec.ts
@@ -2,19 +2,19 @@ import { api } from '../../../../lib/platform/github/gh-got-wrapper';
 import * as hostRules from '../../../../lib/util/host-rules';
 import {
   getChangeLogJSON,
-  ChangeLogConfig,
   ChangeLogError,
 } from '../../../../lib/workers/pr/changelog';
-import { mocked } from '../../../util';
+import { mocked, partial } from '../../../util';
 import { PLATFORM_TYPE_GITHUB } from '../../../../lib/constants/platforms';
 import * as semverVersioning from '../../../../lib/versioning/semver';
+import { BranchConfig } from '../../../../lib/workers/common';
 
 jest.mock('../../../../lib/platform/github/gh-got-wrapper');
 jest.mock('../../../../lib/datasource/npm');
 
 const ghGot = mocked(api).get;
 
-const upgrade: ChangeLogConfig = {
+const upgrade: BranchConfig = partial<BranchConfig>({
   endpoint: 'https://api.github.com/',
   depName: 'renovate',
   versioning: semverVersioning.id,
@@ -33,7 +33,7 @@ const upgrade: ChangeLogConfig = {
     { version: '2.4.2', releaseTimestamp: '2017-12-24T03:20:46.238Z' },
     { version: '2.5.2' },
   ],
-};
+});
 
 describe('workers/pr/changelog', () => {
   describe('getChangeLogJSON', () => {
diff --git a/test/workers/pr/changelog/releases.spec.ts b/test/workers/pr/changelog/releases.spec.ts
index 89252131f6..a60755e040 100644
--- a/test/workers/pr/changelog/releases.spec.ts
+++ b/test/workers/pr/changelog/releases.spec.ts
@@ -1,8 +1,9 @@
 import * as releases from '../../../../lib/workers/pr/changelog/releases';
 import * as datasource from '../../../../lib/datasource';
-import { mocked } from '../../../util';
+import { mocked, partial } from '../../../util';
 import * as dockerVersioning from '../../../../lib/versioning/docker';
 import * as npmVersioning from '../../../../lib/versioning/npm';
+import { BranchUpgradeConfig } from '../../../../lib/workers/common';
 
 jest.mock('../../../../lib/datasource');
 
@@ -41,51 +42,51 @@ describe('workers/pr/changelog/releases', () => {
       });
     });
     it('should contain only stable', async () => {
-      const config = {
+      const config = partial<BranchUpgradeConfig>({
         versioning: npmVersioning.id,
         fromVersion: '1.0.0',
         toVersion: '1.1.0',
-      };
+      });
       const res = await releases.getInRangeReleases(config);
       expect(res).toMatchSnapshot();
       expect(res).toHaveLength(3);
     });
     it('should contain fromVersion unstable', async () => {
-      const config = {
+      const config = partial<BranchUpgradeConfig>({
         versioning: npmVersioning.id,
         fromVersion: '1.0.1-rc0',
         toVersion: '1.1.0',
-      };
+      });
       const res = await releases.getInRangeReleases(config);
       expect(res).toMatchSnapshot();
       expect(res).toHaveLength(4);
     });
     it('should contain toVersion unstable', async () => {
-      const config = {
+      const config = partial<BranchUpgradeConfig>({
         versioning: npmVersioning.id,
         fromVersion: '1.0.1',
         toVersion: '1.2.0-rc1',
-      };
+      });
       const res = await releases.getInRangeReleases(config);
       expect(res).toMatchSnapshot();
       expect(res).toHaveLength(4);
     });
     it('should contain both fromVersion toVersion unstable', async () => {
-      const config = {
+      const config = partial<BranchUpgradeConfig>({
         versioning: npmVersioning.id,
         fromVersion: '1.0.1-rc0',
         toVersion: '1.2.0-rc1',
-      };
+      });
       const res = await releases.getInRangeReleases(config);
       expect(res).toMatchSnapshot();
       expect(res).toHaveLength(6);
     });
     it('should valueToVersion', async () => {
-      const config = {
+      const config = partial<BranchUpgradeConfig>({
         versioning: dockerVersioning.id,
         fromVersion: '1.0.1-rc0',
         toVersion: '1.2.0-rc0',
-      };
+      });
       const res = await releases.getInRangeReleases(config);
       expect(res).toMatchSnapshot();
       expect(res).toHaveLength(3);
diff --git a/test/workers/repository/configured.spec.ts b/test/workers/repository/configured.spec.ts
index 1977926e2d..fcb3237b64 100644
--- a/test/workers/repository/configured.spec.ts
+++ b/test/workers/repository/configured.spec.ts
@@ -4,7 +4,7 @@ import { getConfig, RenovateConfig } from '../../util';
 let config: RenovateConfig;
 beforeEach(() => {
   jest.resetAllMocks();
-  config = getConfig;
+  config = getConfig();
 });
 
 describe('workers/repository/configured', () => {
diff --git a/test/workers/repository/error-config.spec.ts b/test/workers/repository/error-config.spec.ts
index b9b6d831dd..caae622188 100644
--- a/test/workers/repository/error-config.spec.ts
+++ b/test/workers/repository/error-config.spec.ts
@@ -9,7 +9,7 @@ jest.mock('../../../lib/platform');
 let config: RenovateConfig;
 beforeEach(() => {
   jest.resetAllMocks();
-  config = getConfig;
+  config = getConfig();
 });
 
 describe('workers/repository/error-config', () => {
diff --git a/test/workers/repository/error.spec.ts b/test/workers/repository/error.spec.ts
index 28129426d8..67a747c419 100644
--- a/test/workers/repository/error.spec.ts
+++ b/test/workers/repository/error.spec.ts
@@ -34,7 +34,7 @@ jest.mock('../../../lib/workers/repository/error-config');
 let config: RenovateConfig;
 beforeEach(() => {
   jest.resetAllMocks();
-  config = getConfig;
+  config = getConfig();
 });
 
 describe('workers/repository/error', () => {
diff --git a/test/workers/repository/extract/manager-files.spec.ts b/test/workers/repository/extract/manager-files.spec.ts
index 678cad3dd1..ee556d3bbd 100644
--- a/test/workers/repository/extract/manager-files.spec.ts
+++ b/test/workers/repository/extract/manager-files.spec.ts
@@ -15,7 +15,7 @@ describe('workers/repository/extract/manager-files', () => {
     let config: RenovateConfig;
     beforeEach(() => {
       jest.resetAllMocks();
-      config = getConfig;
+      config = getConfig();
     });
     it('returns empty of manager is disabled', async () => {
       const managerConfig = { manager: 'travis', enabled: false };
diff --git a/test/workers/repository/index.spec.ts b/test/workers/repository/index.spec.ts
index 9cce00c58a..7c805ba780 100644
--- a/test/workers/repository/index.spec.ts
+++ b/test/workers/repository/index.spec.ts
@@ -16,7 +16,7 @@ describe('workers/repository', () => {
   describe('renovateRepository()', () => {
     let config: RenovateConfig;
     beforeEach(() => {
-      config = getConfig;
+      config = getConfig();
     });
     it('runs', async () => {
       process.processRepo.mockResolvedValue(mock<ExtractAndUpdateResult>());
diff --git a/test/workers/repository/master-issue.spec.ts b/test/workers/repository/master-issue.spec.ts
index 1027b01858..3cabeadfc1 100644
--- a/test/workers/repository/master-issue.spec.ts
+++ b/test/workers/repository/master-issue.spec.ts
@@ -3,10 +3,12 @@ import { mock } from 'jest-mock-extended';
 
 import * as masterIssue from '../../../lib/workers/repository/master-issue';
 import { RenovateConfig, getConfig, platform } from '../../util';
-import { BranchConfig, PrUpgrade } from '../../../lib/workers/common';
+import { BranchConfig, BranchUpgradeConfig } from '../../../lib/workers/common';
 import { Pr } from '../../../lib/platform';
 import { PLATFORM_TYPE_GITHUB } from '../../../lib/constants/platforms';
 
+type PrUpgrade = BranchUpgradeConfig;
+
 let config: RenovateConfig;
 beforeEach(() => {
   jest.resetAllMocks();
@@ -90,7 +92,7 @@ describe('workers/repository/master-issue', () => {
     });
 
     it('closes master issue when all branches are automerged and masterIssueAutoclose is true', async () => {
-      const branches = [
+      const branches: BranchConfig[] = [
         { ...mock<BranchConfig>(), prTitle: 'pr1', res: 'automerged' },
         {
           ...mock<BranchConfig>(),
@@ -134,11 +136,11 @@ describe('workers/repository/master-issue', () => {
     });
 
     it('checks an issue with 2 Pending Approvals, 2 not scheduled, 2 pr-hourly-limit-reached and 2 in error', async () => {
-      const branches = [
+      const branches: BranchConfig[] = [
         {
           ...mock<BranchConfig>(),
           prTitle: 'pr1',
-          upgrades: [{ ...mock<PrUpgrade>(), depName: 'dep1' }],
+          upgrades: [{ ...mock<BranchUpgradeConfig>(), depName: 'dep1' }],
           res: 'needs-approval',
           branchName: 'branchName1',
         },
@@ -213,7 +215,7 @@ describe('workers/repository/master-issue', () => {
     });
 
     it('checks an issue with 2 PR pr-edited', async () => {
-      const branches = [
+      const branches: BranchConfig[] = [
         {
           ...mock<BranchConfig>(),
           prTitle: 'pr1',
@@ -258,7 +260,7 @@ describe('workers/repository/master-issue', () => {
     });
 
     it('checks an issue with 3 PR in progress and rebase all option', async () => {
-      const branches = [
+      const branches: BranchConfig[] = [
         {
           ...mock<BranchConfig>(),
           prTitle: 'pr1',
@@ -312,7 +314,7 @@ describe('workers/repository/master-issue', () => {
     });
 
     it('checks an issue with 2 PR closed / ignored', async () => {
-      const branches = [
+      const branches: BranchConfig[] = [
         {
           ...mock<BranchConfig>(),
           prTitle: 'pr1',
@@ -362,7 +364,7 @@ describe('workers/repository/master-issue', () => {
     });
 
     it('checks an issue with 3 PR in approval', async () => {
-      const branches = [
+      const branches: BranchConfig[] = [
         {
           ...mock<BranchConfig>(),
           prTitle: 'pr1',
diff --git a/test/workers/repository/process/extract-update.spec.ts b/test/workers/repository/process/extract-update.spec.ts
index 2b143145c3..1c1eec6988 100644
--- a/test/workers/repository/process/extract-update.spec.ts
+++ b/test/workers/repository/process/extract-update.spec.ts
@@ -10,7 +10,10 @@ jest.mock('../../../../lib/workers/repository/extract');
 
 const branchify = mocked(_branchify);
 
-branchify.branchifyUpgrades.mockReturnValueOnce({});
+branchify.branchifyUpgrades.mockReturnValueOnce({
+  branches: [],
+  branchList: [],
+});
 
 describe('workers/repository/process/extract-update', () => {
   describe('extractAndUpdate()', () => {
diff --git a/test/workers/repository/process/limits.spec.ts b/test/workers/repository/process/limits.spec.ts
index 6db1619c84..5b27ad3a9b 100644
--- a/test/workers/repository/process/limits.spec.ts
+++ b/test/workers/repository/process/limits.spec.ts
@@ -1,6 +1,7 @@
 import moment from 'moment';
 import * as limits from '../../../../lib/workers/repository/process/limits';
 import { platform, getConfig, RenovateConfig } from '../../../util';
+import { BranchConfig } from '../../../../lib/workers/common';
 
 let config: RenovateConfig;
 beforeEach(() => {
@@ -34,7 +35,10 @@ describe('workers/repository/process/limits', () => {
     it('calculates concurrent limit remaining', async () => {
       config.prConcurrentLimit = 20;
       platform.branchExists.mockResolvedValueOnce(true);
-      const branches = [{ branchName: 'test' }, { branchName: undefined }];
+      const branches: BranchConfig[] = [
+        { branchName: 'test', upgrades: [] },
+        { branchName: undefined, upgrades: [] },
+      ];
       const res = await limits.getConcurrentPrsRemaining(config, branches);
       expect(res).toEqual(19);
     });
diff --git a/test/workers/repository/process/sort.spec.ts b/test/workers/repository/process/sort.spec.ts
index 1800330eff..836584f5a7 100644
--- a/test/workers/repository/process/sort.spec.ts
+++ b/test/workers/repository/process/sort.spec.ts
@@ -1,23 +1,24 @@
 import { sortBranches } from '../../../../lib/workers/repository/process/sort';
+import { UpdateType } from '../../../../lib/config';
 
 describe('workers/repository/process/sort', () => {
   describe('sortBranches()', () => {
     it('sorts based on updateType and prTitle', () => {
       const branches = [
         {
-          updateType: 'major',
+          updateType: 'major' as UpdateType,
           prTitle: 'some major update',
         },
         {
-          updateType: 'pin',
+          updateType: 'pin' as UpdateType,
           prTitle: 'some pin',
         },
         {
-          updateType: 'pin',
+          updateType: 'pin' as UpdateType,
           prTitle: 'some other pin',
         },
         {
-          updateType: 'minor',
+          updateType: 'minor' as UpdateType,
           prTitle: 'a minor update',
         },
       ];
@@ -27,22 +28,22 @@ describe('workers/repository/process/sort', () => {
     it('sorts based on prPriority', () => {
       const branches = [
         {
-          updateType: 'major',
+          updateType: 'major' as UpdateType,
           prTitle: 'some major update',
           prPriority: 1,
         },
         {
-          updateType: 'pin',
+          updateType: 'pin' as UpdateType,
           prTitle: 'some pin',
           prPriority: -1,
         },
         {
-          updateType: 'pin',
+          updateType: 'pin' as UpdateType,
           prTitle: 'some other pin',
           prPriority: 0,
         },
         {
-          updateType: 'minor',
+          updateType: 'minor' as UpdateType,
           prTitle: 'a minor update',
           prPriority: -1,
         },
diff --git a/test/workers/repository/result.spec.ts b/test/workers/repository/result.spec.ts
index dd35e8db87..e54b942a69 100644
--- a/test/workers/repository/result.spec.ts
+++ b/test/workers/repository/result.spec.ts
@@ -4,7 +4,7 @@ import { RenovateConfig, getConfig } from '../../util';
 let config: RenovateConfig;
 beforeEach(() => {
   jest.resetAllMocks();
-  config = getConfig;
+  config = getConfig();
 });
 
 describe('workers/repository/result', () => {
diff --git a/test/workers/repository/updates/branchify.spec.ts b/test/workers/repository/updates/branchify.spec.ts
index d99b621888..bb36432f1d 100644
--- a/test/workers/repository/updates/branchify.spec.ts
+++ b/test/workers/repository/updates/branchify.spec.ts
@@ -1,7 +1,6 @@
 import { RenovateConfig, mocked } from '../../../util';
 import { branchifyUpgrades } from '../../../../lib/workers/repository/updates/branchify';
 import * as _flatten from '../../../../lib/workers/repository/updates/flatten';
-import { BranchConfig } from '../../../../lib/workers/common';
 import { getConfig } from '../../../../lib/config/defaults';
 
 const flattenUpdates = mocked(_flatten).flattenUpdates;
@@ -238,7 +237,7 @@ describe('workers/repository/updates/branchify', () => {
       );
 
       branchifyUpgrades(config, {}).branches.forEach(
-        ({ branchName }: BranchConfig, index: number) => {
+        ({ branchName }, index: number) => {
           expect(branchName).toBe(fixtures[index].expectedBranchName);
         }
       );
diff --git a/test/workers/repository/updates/generate.spec.ts b/test/workers/repository/updates/generate.spec.ts
index 8a6272f80b..54dedbf5a6 100644
--- a/test/workers/repository/updates/generate.spec.ts
+++ b/test/workers/repository/updates/generate.spec.ts
@@ -1,6 +1,8 @@
-import { defaultConfig } from '../../../util';
+import { defaultConfig, partial } from '../../../util';
 import { generateBranchConfig } from '../../../../lib/workers/repository/updates/generate';
 import * as datasourceNpm from '../../../../lib/datasource/npm';
+import { UpdateType } from '../../../../lib/config';
+import { BranchUpgradeConfig } from '../../../../lib/workers/common';
 
 beforeEach(() => {
   jest.resetAllMocks();
@@ -243,7 +245,7 @@ describe('workers/repository/updates/generate', () => {
     });
     it('uses semantic commits', () => {
       const branch = [
-        {
+        partial<BranchUpgradeConfig>({
           ...defaultConfig,
           depName: 'some-dep',
           semanticCommits: true,
@@ -257,7 +259,7 @@ describe('workers/repository/updates/generate', () => {
           group: {
             foo: 2,
           },
-        },
+        }),
       ];
       const res = generateBranchConfig(branch);
       expect(res.prTitle).toEqual(
@@ -266,7 +268,7 @@ describe('workers/repository/updates/generate', () => {
     });
     it('scopes monorepo commits', () => {
       const branch = [
-        {
+        partial<BranchUpgradeConfig>({
           ...defaultConfig,
           depName: 'some-dep',
           packageFile: 'foo/package.json',
@@ -281,7 +283,7 @@ describe('workers/repository/updates/generate', () => {
           group: {
             foo: 2,
           },
-        },
+        }),
       ];
       const res = generateBranchConfig(branch);
       expect(res.prTitle).toEqual(
@@ -290,7 +292,7 @@ describe('workers/repository/updates/generate', () => {
     });
     it('scopes monorepo commits', () => {
       const branch = [
-        {
+        partial<BranchUpgradeConfig>({
           ...defaultConfig,
           depName: 'some-dep',
           packageFile: 'foo/package.json',
@@ -305,7 +307,7 @@ describe('workers/repository/updates/generate', () => {
           group: {
             foo: 2,
           },
-        },
+        }),
       ];
       const res = generateBranchConfig(branch);
       expect(res.prTitle).toEqual(
@@ -314,7 +316,7 @@ describe('workers/repository/updates/generate', () => {
     });
     it('scopes monorepo commits', () => {
       const branch = [
-        {
+        partial<BranchUpgradeConfig>({
           ...defaultConfig,
           depName: 'some-dep',
           packageFile: 'package.json',
@@ -329,7 +331,7 @@ describe('workers/repository/updates/generate', () => {
           group: {
             foo: 2,
           },
-        },
+        }),
       ];
       const res = generateBranchConfig(branch);
       expect(res.prTitle).toEqual(
@@ -338,7 +340,7 @@ describe('workers/repository/updates/generate', () => {
     });
     it('scopes monorepo commits', () => {
       const branch = [
-        {
+        partial<BranchUpgradeConfig>({
           ...defaultConfig,
           depName: 'some-dep',
           packageFile: 'package.json',
@@ -353,7 +355,7 @@ describe('workers/repository/updates/generate', () => {
           group: {
             foo: 2,
           },
-        },
+        }),
       ];
       const res = generateBranchConfig(branch);
       expect(res.prTitle).toEqual(
@@ -362,7 +364,7 @@ describe('workers/repository/updates/generate', () => {
     });
     it('scopes monorepo commits with nested package files', () => {
       const branch = [
-        {
+        partial<BranchUpgradeConfig>({
           ...defaultConfig,
           commitBodyTable: false,
           depName: 'some-dep',
@@ -378,7 +380,7 @@ describe('workers/repository/updates/generate', () => {
           group: {
             foo: 2,
           },
-        },
+        }),
       ];
       const res = generateBranchConfig(branch);
       expect(res.prTitle).toEqual(
@@ -387,7 +389,7 @@ describe('workers/repository/updates/generate', () => {
     });
     it('scopes monorepo commits with nested package files', () => {
       const branch = [
-        {
+        partial<BranchUpgradeConfig>({
           ...defaultConfig,
           depName: 'some-dep',
           packageFile: 'foo/bar/package.json',
@@ -402,7 +404,7 @@ describe('workers/repository/updates/generate', () => {
           group: {
             foo: 2,
           },
-        },
+        }),
       ];
       const res = generateBranchConfig(branch);
       expect(res.prTitle).toEqual(
@@ -411,14 +413,14 @@ describe('workers/repository/updates/generate', () => {
     });
     it('adds commit message body', () => {
       const branch = [
-        {
+        partial<BranchUpgradeConfig>({
           ...defaultConfig,
           depName: 'some-dep',
           commitBody: '[skip-ci]',
           newValue: '1.2.0',
           isSingleVersion: true,
           toVersion: '1.2.0',
-        },
+        }),
       ];
       const res = generateBranchConfig(branch);
       expect(res.commitMessage).toMatchSnapshot();
@@ -426,12 +428,12 @@ describe('workers/repository/updates/generate', () => {
     });
     it('supports manual prTitle', () => {
       const branch = [
-        {
+        partial<BranchUpgradeConfig>({
           ...defaultConfig,
           depName: 'some-dep',
           prTitle: 'Upgrade {{depName}}',
           toLowerCase: true,
-        },
+        }),
       ];
       const res = generateBranchConfig(branch);
       expect(res.prTitle).toMatchSnapshot();
@@ -508,7 +510,7 @@ describe('workers/repository/updates/generate', () => {
           newValue: '0.6.0',
           isGroup: true,
           separateMinorPatch: true,
-          updateType: 'minor',
+          updateType: 'minor' as UpdateType,
           fileReplacePosition: 1,
         },
         {
@@ -519,7 +521,7 @@ describe('workers/repository/updates/generate', () => {
           newValue: '0.6.0',
           isGroup: true,
           separateMajorMinor: true,
-          updateType: 'major',
+          updateType: 'major' as UpdateType,
           fileReplacePosition: 2,
         },
         {
@@ -530,7 +532,7 @@ describe('workers/repository/updates/generate', () => {
           newValue: '0.6.0',
           isGroup: true,
           separateMajorMinor: true,
-          updateType: 'patch',
+          updateType: 'patch' as UpdateType,
           fileReplacePosition: 0,
         },
       ];
-- 
GitLab