From 498ec2061835b7351bcd828a3dee12c7a71fdf46 Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Fri, 1 May 2020 07:47:31 +0200
Subject: [PATCH] fea(internal): remove repoCache global (#6098)

---
 lib/config/presets/gitlab.spec.ts             |  1 -
 lib/config/presets/local.spec.ts              |  1 -
 lib/config/presets/npm.spec.ts                |  1 -
 lib/datasource/crate/index.spec.ts            |  3 ---
 lib/datasource/dart/index.spec.ts             |  3 ---
 lib/datasource/docker/index.spec.ts           |  5 ++--
 lib/datasource/galaxy/index.spec.ts           |  3 ---
 lib/datasource/github-tags/index.spec.ts      |  1 -
 lib/datasource/gitlab-tags/index.spec.ts      |  1 -
 lib/datasource/go/index.spec.ts               |  3 ---
 lib/datasource/gradle-version/index.spec.ts   |  1 -
 lib/datasource/helm/index.spec.ts             |  1 -
 lib/datasource/hex/index.spec.ts              |  3 ---
 lib/datasource/index.ts                       |  8 +++----
 lib/datasource/maven/index.spec.ts            |  1 -
 lib/datasource/npm/index.spec.ts              |  3 ++-
 lib/datasource/nuget/index.spec.ts            |  1 -
 lib/datasource/orb/index.spec.ts              |  1 -
 lib/datasource/packagist/index.spec.ts        |  3 ++-
 lib/datasource/packagist/index.ts             | 24 ++++++++-----------
 lib/datasource/pod/index.spec.ts              |  3 ++-
 lib/datasource/pypi/index.spec.ts             |  2 --
 lib/datasource/ruby-version/index.spec.ts     |  1 -
 lib/datasource/rubygems/index.spec.ts         |  3 ++-
 lib/datasource/terraform-module/index.spec.ts |  1 -
 .../terraform-provider/index.spec.ts          |  1 -
 lib/globals.d.ts                              |  2 --
 lib/manager/bundler/artifacts.spec.ts         |  2 +-
 lib/manager/bundler/artifacts.ts              |  9 +++----
 lib/util/cache.spec.ts                        | 10 +++++---
 lib/util/cache.ts                             | 15 ++++++++----
 lib/util/got/cache-get.ts                     | 21 ++++++++--------
 lib/util/got/index.spec.ts                    |  8 +++----
 lib/util/http/index.spec.ts                   |  1 -
 lib/workers/repository/init/index.ts          |  3 ++-
 .../repository/process/lookup/index.spec.ts   |  3 ++-
 test/globals.ts                               |  2 --
 37 files changed, 65 insertions(+), 90 deletions(-)

diff --git a/lib/config/presets/gitlab.spec.ts b/lib/config/presets/gitlab.spec.ts
index ff3a357901..64b6db804b 100644
--- a/lib/config/presets/gitlab.spec.ts
+++ b/lib/config/presets/gitlab.spec.ts
@@ -11,7 +11,6 @@ const glGot: jest.Mock<Promise<PartialDeep<GotResponse>>> = api.get as never;
 describe('config/presets/gitlab', () => {
   beforeEach(() => {
     glGot.mockReset();
-    global.repoCache = {};
     return global.renovateCache.rmAll();
   });
   describe('getPreset()', () => {
diff --git a/lib/config/presets/local.spec.ts b/lib/config/presets/local.spec.ts
index 5780818d57..2820554006 100644
--- a/lib/config/presets/local.spec.ts
+++ b/lib/config/presets/local.spec.ts
@@ -18,7 +18,6 @@ describe('config/presets/local', () => {
     gitlabGetPreset.mockResolvedValueOnce({ resolved: 'preset' });
     githubGetPreset.mockReset();
     githubGetPreset.mockResolvedValueOnce({ resolved: 'preset' });
-    global.repoCache = {};
     return global.renovateCache.rmAll();
   });
   describe('getPreset()', () => {
diff --git a/lib/config/presets/npm.spec.ts b/lib/config/presets/npm.spec.ts
index 868478c0ea..7ba07ce6b8 100644
--- a/lib/config/presets/npm.spec.ts
+++ b/lib/config/presets/npm.spec.ts
@@ -8,7 +8,6 @@ describe('config/presets/npm', () => {
   delete process.env.NPM_TOKEN;
   beforeEach(() => {
     jest.resetAllMocks();
-    global.repoCache = {};
     global.trustLevel = 'low';
     nock.cleanAll();
     return global.renovateCache.rmAll();
diff --git a/lib/datasource/crate/index.spec.ts b/lib/datasource/crate/index.spec.ts
index 176ab304c9..ecf31c4e76 100644
--- a/lib/datasource/crate/index.spec.ts
+++ b/lib/datasource/crate/index.spec.ts
@@ -19,9 +19,6 @@ jest.mock('../../util/got');
 
 describe('datasource/crate', () => {
   describe('getReleases', () => {
-    beforeEach(() => {
-      global.repoCache = {};
-    });
     it('returns null for empty result', async () => {
       got.mockReturnValueOnce(null);
       expect(
diff --git a/lib/datasource/dart/index.spec.ts b/lib/datasource/dart/index.spec.ts
index e4a63bb018..95124ba2e2 100644
--- a/lib/datasource/dart/index.spec.ts
+++ b/lib/datasource/dart/index.spec.ts
@@ -15,9 +15,6 @@ jest.mock('../../util/got');
 
 describe('datasource/dart', () => {
   describe('getReleases', () => {
-    beforeEach(() => {
-      global.repoCache = {};
-    });
     it('returns null for empty result', async () => {
       got.mockReturnValueOnce(null);
       expect(await getReleases({ lookupName: 'non_sense' })).toBeNull();
diff --git a/lib/datasource/docker/index.spec.ts b/lib/datasource/docker/index.spec.ts
index 24909e0b85..f6620f750e 100644
--- a/lib/datasource/docker/index.spec.ts
+++ b/lib/datasource/docker/index.spec.ts
@@ -5,6 +5,7 @@ import * as docker from '.';
 import { getPkgReleases } from '..';
 import * as _hostRules from '../../util/host-rules';
 import { DATASOURCE_FAILURE } from '../../constants/error-messages';
+import { clearRepoCache } from '../../util/cache';
 
 const got: any = _got;
 const hostRules: any = _hostRules;
@@ -29,7 +30,7 @@ describe('api/docker', () => {
   describe('getDigest', () => {
     beforeEach(() => {
       jest.resetAllMocks();
-      global.repoCache = {};
+      clearRepoCache();
       hostRules.find.mockReturnValue({
         username: 'some-username',
         password: 'some-password',
@@ -279,7 +280,7 @@ describe('api/docker', () => {
   describe('getReleases', () => {
     beforeEach(() => {
       jest.clearAllMocks();
-      global.repoCache = {};
+      clearRepoCache();
       return global.renovateCache.rmAll();
     });
     it('returns null if no token', async () => {
diff --git a/lib/datasource/galaxy/index.spec.ts b/lib/datasource/galaxy/index.spec.ts
index a902d97f70..535f956a9d 100644
--- a/lib/datasource/galaxy/index.spec.ts
+++ b/lib/datasource/galaxy/index.spec.ts
@@ -18,9 +18,6 @@ jest.mock('../../util/got');
 
 describe('datasource/galaxy', () => {
   describe('getReleases', () => {
-    beforeEach(() => {
-      global.repoCache = {};
-    });
     it('returns null for empty result', async () => {
       got.mockReturnValueOnce(null);
       expect(
diff --git a/lib/datasource/github-tags/index.spec.ts b/lib/datasource/github-tags/index.spec.ts
index 1655cd3bf6..8119c027c0 100644
--- a/lib/datasource/github-tags/index.spec.ts
+++ b/lib/datasource/github-tags/index.spec.ts
@@ -16,7 +16,6 @@ describe('datasource/github-tags', () => {
     beforeEach(() => {
       jest.resetAllMocks();
       hostRules.hosts = jest.fn(() => []);
-      global.repoCache = {};
       return global.renovateCache.rmAll();
     });
     it('returns null if no token', async () => {
diff --git a/lib/datasource/gitlab-tags/index.spec.ts b/lib/datasource/gitlab-tags/index.spec.ts
index baa74f48de..5d345590c2 100644
--- a/lib/datasource/gitlab-tags/index.spec.ts
+++ b/lib/datasource/gitlab-tags/index.spec.ts
@@ -8,7 +8,6 @@ const glGot: any = api.get;
 
 describe('datasource/gitlab-tags', () => {
   beforeEach(() => {
-    global.repoCache = {};
     return global.renovateCache.rmAll();
   });
   describe('getReleases', () => {
diff --git a/lib/datasource/go/index.spec.ts b/lib/datasource/go/index.spec.ts
index 5b3c72a5cd..38d5de888d 100644
--- a/lib/datasource/go/index.spec.ts
+++ b/lib/datasource/go/index.spec.ts
@@ -24,9 +24,6 @@ Nothing to see here; <a href="https://godoc.org/golang.org/x/text">move along</a
 </html>`;
 
 describe('datasource/go', () => {
-  beforeEach(() => {
-    global.repoCache = {};
-  });
   describe('getDigest', () => {
     it('returns null for wrong name', async () => {
       got.mockReturnValueOnce({
diff --git a/lib/datasource/gradle-version/index.spec.ts b/lib/datasource/gradle-version/index.spec.ts
index 23f7351972..2df73da159 100644
--- a/lib/datasource/gradle-version/index.spec.ts
+++ b/lib/datasource/gradle-version/index.spec.ts
@@ -19,7 +19,6 @@ describe('datasource/gradle-version', () => {
         lookupName: 'abc',
       };
       jest.clearAllMocks();
-      global.repoCache = {};
       return global.renovateCache.rmAll();
     });
 
diff --git a/lib/datasource/helm/index.spec.ts b/lib/datasource/helm/index.spec.ts
index 5c7e2eeea6..956c1ccca6 100644
--- a/lib/datasource/helm/index.spec.ts
+++ b/lib/datasource/helm/index.spec.ts
@@ -16,7 +16,6 @@ describe('datasource/helm', () => {
   describe('getReleases', () => {
     beforeEach(() => {
       jest.resetAllMocks();
-      global.repoCache = {};
       return global.renovateCache.rmAll();
     });
     it('returns null if lookupName was not provided', async () => {
diff --git a/lib/datasource/hex/index.spec.ts b/lib/datasource/hex/index.spec.ts
index 0a165808e6..9d53a52839 100644
--- a/lib/datasource/hex/index.spec.ts
+++ b/lib/datasource/hex/index.spec.ts
@@ -18,9 +18,6 @@ jest.mock('../../util/host-rules');
 
 describe('datasource/hex', () => {
   describe('getReleases', () => {
-    beforeEach(() => {
-      global.repoCache = {};
-    });
     it('returns null for empty result', async () => {
       got.mockReturnValueOnce(null);
       expect(
diff --git a/lib/datasource/index.ts b/lib/datasource/index.ts
index 7122b79fd4..39028e02ec 100644
--- a/lib/datasource/index.ts
+++ b/lib/datasource/index.ts
@@ -14,6 +14,7 @@ import {
 } from './common';
 import datasources from './api.generated';
 import { clone } from '../util/clone';
+import { getRepoCached, setRepoCached } from '../util/cache';
 
 export * from './common';
 
@@ -65,12 +66,11 @@ function getRawReleases(
     config.datasource +
     config.lookupName +
     config.registryUrls;
-  // The repoCache is initialized for each repo
   // By returning a Promise and reusing it, we should only fetch each package at most once
-  if (!global.repoCache[cacheKey]) {
-    global.repoCache[cacheKey] = fetchReleases(config);
+  if (!getRepoCached(cacheKey)) {
+    setRepoCached(cacheKey, fetchReleases(config));
   }
-  return global.repoCache[cacheKey];
+  return getRepoCached<Promise<ReleaseResult | null>>(cacheKey);
 }
 
 export async function getPkgReleases(
diff --git a/lib/datasource/maven/index.spec.ts b/lib/datasource/maven/index.spec.ts
index 0bb37673b3..02891c2948 100644
--- a/lib/datasource/maven/index.spec.ts
+++ b/lib/datasource/maven/index.spec.ts
@@ -39,7 +39,6 @@ describe('datasource/maven', () => {
       password: 'password',
     });
     jest.resetAllMocks();
-    global.repoCache = {};
     nock.cleanAll();
     nock.disableNetConnect();
     nock('https://repo.maven.apache.org')
diff --git a/lib/datasource/npm/index.spec.ts b/lib/datasource/npm/index.spec.ts
index 02c30d180f..bc7b93f783 100644
--- a/lib/datasource/npm/index.spec.ts
+++ b/lib/datasource/npm/index.spec.ts
@@ -5,6 +5,7 @@ import * as npm from '.';
 import * as hostRules from '../../util/host-rules';
 import { DATASOURCE_FAILURE } from '../../constants/error-messages';
 import { getName } from '../../../test/util';
+import { clearRepoCache } from '../../util/cache';
 
 jest.mock('registry-auth-token');
 jest.mock('delay');
@@ -25,7 +26,7 @@ describe(getName(__filename), () => {
   delete process.env.NPM_TOKEN;
   beforeEach(() => {
     jest.resetAllMocks();
-    global.repoCache = {};
+    clearRepoCache();
     global.trustLevel = 'low';
     npm.resetCache();
     npm.setNpmrc();
diff --git a/lib/datasource/nuget/index.spec.ts b/lib/datasource/nuget/index.spec.ts
index 986835311d..aa303cc637 100644
--- a/lib/datasource/nuget/index.spec.ts
+++ b/lib/datasource/nuget/index.spec.ts
@@ -87,7 +87,6 @@ describe('datasource/nuget', () => {
     beforeEach(() => {
       jest.resetAllMocks();
       hostRules.hosts = jest.fn(() => []);
-      global.repoCache = {};
     });
 
     it(`can't detect nuget feed version`, async () => {
diff --git a/lib/datasource/orb/index.spec.ts b/lib/datasource/orb/index.spec.ts
index ea5da05f95..eee0c94d75 100644
--- a/lib/datasource/orb/index.spec.ts
+++ b/lib/datasource/orb/index.spec.ts
@@ -30,7 +30,6 @@ describe('datasource/orb', () => {
   describe('getReleases', () => {
     beforeEach(() => {
       jest.clearAllMocks();
-      global.repoCache = {};
       return global.renovateCache.rmAll();
     });
     it('returns null for empty result', async () => {
diff --git a/lib/datasource/packagist/index.spec.ts b/lib/datasource/packagist/index.spec.ts
index 355f976d84..48a15419dd 100644
--- a/lib/datasource/packagist/index.spec.ts
+++ b/lib/datasource/packagist/index.spec.ts
@@ -3,6 +3,7 @@ import _got from '../../util/got';
 import * as packagist from '.';
 import * as _hostRules from '../../util/host-rules';
 import * as composerVersioning from '../../versioning/composer';
+import { clearRepoCache } from '../../util/cache';
 
 jest.mock('../../util/got');
 jest.mock('../../util/host-rules');
@@ -27,7 +28,7 @@ describe('datasource/packagist', () => {
       jest.resetAllMocks();
       hostRules.find = jest.fn((input) => input);
       hostRules.hosts = jest.fn(() => []);
-      global.repoCache = {};
+      clearRepoCache();
       config = {
         versioning: composerVersioning.id,
         registryUrls: [
diff --git a/lib/datasource/packagist/index.ts b/lib/datasource/packagist/index.ts
index 80fd6929d2..4a84c982a8 100644
--- a/lib/datasource/packagist/index.ts
+++ b/lib/datasource/packagist/index.ts
@@ -1,12 +1,12 @@
 import is from '@sindresorhus/is';
 
 import URL from 'url';
-import delay from 'delay';
 import pAll from 'p-all';
 import { logger } from '../../logger';
 import { Http, HttpOptions } from '../../util/http';
 import * as hostRules from '../../util/host-rules';
 import { DatasourceError, GetReleasesConfig, ReleaseResult } from '../common';
+import { getRepoCached, setRepoCached } from '../../util/cache';
 
 export const id = 'packagist';
 
@@ -172,19 +172,8 @@ interface AllPackages {
 }
 
 async function getAllPackages(regUrl: string): Promise<AllPackages | null> {
-  let repoCacheResult = global.repoCache[`packagist-${regUrl}`];
-  // istanbul ignore if
-  if (repoCacheResult) {
-    while (repoCacheResult === 'pending') {
-      await delay(200);
-      repoCacheResult = global.repoCache[`packagist-${regUrl}`];
-    }
-    return repoCacheResult;
-  }
-  global.repoCache[`packagist-${regUrl}`] = 'pending';
   const registryMeta = await getRegistryMeta(regUrl);
   if (!registryMeta) {
-    global.repoCache[`packagist-${regUrl}`] = null;
     return null;
   }
   const {
@@ -224,10 +213,17 @@ async function getAllPackages(regUrl: string): Promise<AllPackages | null> {
     providerPackages,
     includesPackages,
   };
-  global.repoCache[`packagist-${regUrl}`] = allPackages;
   return allPackages;
 }
 
+function getAllCachedPackages(regUrl: string): Promise<AllPackages | null> {
+  const cacheKey = `packagist-${regUrl}`;
+  if (getRepoCached(cacheKey) === undefined) {
+    setRepoCached(cacheKey, getAllPackages(regUrl));
+  }
+  return getRepoCached(cacheKey);
+}
+
 async function packagistOrgLookup(name: string): Promise<ReleaseResult> {
   const cacheNamespace = 'datasource-packagist-org';
   const cachedResult = await renovateCache.get<ReleaseResult>(
@@ -262,7 +258,7 @@ async function packageLookup(
       const packagistResult = await packagistOrgLookup(name);
       return packagistResult;
     }
-    const allPackages = await getAllPackages(regUrl);
+    const allPackages = await getAllCachedPackages(regUrl);
     if (!allPackages) {
       return null;
     }
diff --git a/lib/datasource/pod/index.spec.ts b/lib/datasource/pod/index.spec.ts
index 7cec2c8a8a..d1fda1294a 100644
--- a/lib/datasource/pod/index.spec.ts
+++ b/lib/datasource/pod/index.spec.ts
@@ -4,6 +4,7 @@ import * as rubyVersioning from '../../versioning/ruby';
 import { getPkgReleases } from '..';
 import { mocked } from '../../../test/util';
 import { GotResponse } from '../../platform';
+import { clearRepoCache } from '../../util/cache';
 
 const api = mocked(_api);
 
@@ -20,7 +21,7 @@ describe('datasource/cocoapods', () => {
   describe('getReleases', () => {
     beforeEach(() => {
       jest.resetAllMocks();
-      global.repoCache = {};
+      clearRepoCache();
       return global.renovateCache.rmAll();
     });
 
diff --git a/lib/datasource/pypi/index.spec.ts b/lib/datasource/pypi/index.spec.ts
index 8b696f5f1b..739c6264bd 100644
--- a/lib/datasource/pypi/index.spec.ts
+++ b/lib/datasource/pypi/index.spec.ts
@@ -26,7 +26,6 @@ describe('datasource/pypi', () => {
     beforeEach(() => {
       process.env = { ...OLD_ENV };
       delete process.env.PIP_INDEX_URL;
-      global.repoCache = {};
     });
 
     afterEach(() => {
@@ -35,7 +34,6 @@ describe('datasource/pypi', () => {
 
     beforeEach(() => {
       jest.resetAllMocks();
-      global.repoCache = {};
     });
     it('returns null for empty result', async () => {
       got.mockReturnValueOnce({});
diff --git a/lib/datasource/ruby-version/index.spec.ts b/lib/datasource/ruby-version/index.spec.ts
index 2f26b3f29b..5db9f38e13 100644
--- a/lib/datasource/ruby-version/index.spec.ts
+++ b/lib/datasource/ruby-version/index.spec.ts
@@ -14,7 +14,6 @@ const rubyReleasesHtml = fs.readFileSync(
 describe('datasource/gradle', () => {
   describe('getReleases', () => {
     beforeEach(() => {
-      global.repoCache = {};
       return global.renovateCache.rmAll();
     });
     it('parses real data', async () => {
diff --git a/lib/datasource/rubygems/index.spec.ts b/lib/datasource/rubygems/index.spec.ts
index 5247219a48..09b63174ae 100644
--- a/lib/datasource/rubygems/index.spec.ts
+++ b/lib/datasource/rubygems/index.spec.ts
@@ -4,6 +4,7 @@ import railsVersions from './__fixtures__/rails/versions.json';
 import * as rubyVersioning from '../../versioning/ruby';
 import * as rubygems from '.';
 import { getPkgReleases } from '..';
+import { clearRepoCache } from '../../util/cache';
 
 const got: any = _got;
 
@@ -45,7 +46,7 @@ describe('datasource/rubygems', () => {
     });
 
     afterEach(() => {
-      global.repoCache = {};
+      clearRepoCache();
       process.env.RENOVATE_SKIP_CACHE = SKIP_CACHE;
     });
 
diff --git a/lib/datasource/terraform-module/index.spec.ts b/lib/datasource/terraform-module/index.spec.ts
index a5d9e06dc5..320f678b36 100644
--- a/lib/datasource/terraform-module/index.spec.ts
+++ b/lib/datasource/terraform-module/index.spec.ts
@@ -14,7 +14,6 @@ describe('datasource/terraform-module', () => {
   describe('getReleases', () => {
     beforeEach(() => {
       jest.clearAllMocks();
-      global.repoCache = {};
       return global.renovateCache.rmAll();
     });
     it('returns null for empty result', async () => {
diff --git a/lib/datasource/terraform-provider/index.spec.ts b/lib/datasource/terraform-provider/index.spec.ts
index 7d61edbc22..608e69a861 100644
--- a/lib/datasource/terraform-provider/index.spec.ts
+++ b/lib/datasource/terraform-provider/index.spec.ts
@@ -14,7 +14,6 @@ describe('datasource/terraform', () => {
   describe('getReleases', () => {
     beforeEach(() => {
       jest.clearAllMocks();
-      global.repoCache = {};
       return global.renovateCache.rmAll();
     });
     it('returns null for empty result', async () => {
diff --git a/lib/globals.d.ts b/lib/globals.d.ts
index b8d91df810..4bc09bb772 100644
--- a/lib/globals.d.ts
+++ b/lib/globals.d.ts
@@ -33,8 +33,6 @@ declare namespace NodeJS {
 
     renovateCache: Renovate.Cache;
 
-    repoCache: Record<string, any>;
-
     trustLevel?: string;
 
     updateRubyGemsVersions?: Promise<void>;
diff --git a/lib/manager/bundler/artifacts.spec.ts b/lib/manager/bundler/artifacts.spec.ts
index 00de11a3e3..66f25b97c4 100644
--- a/lib/manager/bundler/artifacts.spec.ts
+++ b/lib/manager/bundler/artifacts.spec.ts
@@ -49,7 +49,7 @@ describe('bundler.updateArtifacts()', () => {
     env.getChildProcessEnv.mockReturnValue(envMock.basic);
     bundlerHostRules.findAllAuthenticatable.mockReturnValue([]);
     resetPrefetchedImages();
-    global.repoCache = {};
+
     await setUtilConfig(config);
   });
   it('returns null by default', async () => {
diff --git a/lib/manager/bundler/artifacts.ts b/lib/manager/bundler/artifacts.ts
index 7042dd8cfd..3be189aebe 100644
--- a/lib/manager/bundler/artifacts.ts
+++ b/lib/manager/bundler/artifacts.ts
@@ -16,6 +16,7 @@ import {
   findAllAuthenticatable,
   getDomain,
 } from './host-rules';
+import { getRepoCached, setRepoCached } from '../../util/cache';
 
 const hostConfigVariablePrefix = 'BUNDLE_';
 
@@ -70,12 +71,12 @@ export async function updateArtifacts(
     config,
   } = updateArtifact;
   const { compatibility = {} } = config;
-
   logger.debug(`bundler.updateArtifacts(${packageFileName})`);
+  const existingError = getRepoCached<string>('bundlerArtifactsError');
   // istanbul ignore if
-  if (global.repoCache.bundlerArtifactsError) {
+  if (existingError) {
     logger.debug('Aborting Bundler artifacts due to previous failed attempt');
-    throw new Error(global.repoCache.bundlerArtifactsError);
+    throw new Error(existingError);
   }
   const lockFileName = `${packageFileName}.lock`;
   const existingLockFileContent = await platform.getFile(lockFileName);
@@ -176,7 +177,7 @@ export async function updateArtifacts(
         'Gemfile.lock update failed due to missing credentials - skipping branch'
       );
       // Do not generate these PRs because we don't yet support Bundler authentication
-      global.repoCache.bundlerArtifactsError = BUNDLER_INVALID_CREDENTIALS;
+      setRepoCached('bundlerArtifactsError', BUNDLER_INVALID_CREDENTIALS);
       throw new Error(BUNDLER_INVALID_CREDENTIALS);
     }
     const resolveMatchRe = new RegExp('\\s+(.*) was resolved to', 'g');
diff --git a/lib/util/cache.spec.ts b/lib/util/cache.spec.ts
index 14413bad8b..cd41ba573e 100644
--- a/lib/util/cache.spec.ts
+++ b/lib/util/cache.spec.ts
@@ -1,7 +1,11 @@
-import { getRepoCache } from './cache';
+import { clearRepoCache, getRepoCached, setRepoCached } from './cache';
 
 describe('getRepoCache', () => {
-  it('returns the global cache', () => {
-    expect(getRepoCache()).toBeDefined();
+  it('sets and gets repo cache', () => {
+    setRepoCached('key', 'value');
+    expect(getRepoCached('key')).toEqual('value');
+  });
+  it('clears repo cache', () => {
+    clearRepoCache();
   });
 });
diff --git a/lib/util/cache.ts b/lib/util/cache.ts
index d4282d9ded..1fd3b1863a 100644
--- a/lib/util/cache.ts
+++ b/lib/util/cache.ts
@@ -1,8 +1,13 @@
-export function getRepoCache(): Record<string, any> {
-  // eslint-disable-next-line no-return-assign
-  return global.repoCache ?? (global.repoCache = {});
-}
+let repoCache: Record<string, any> = {};
 
 export function clearRepoCache(): void {
-  global.repoCache = {};
+  repoCache = {};
+}
+
+export function getRepoCached<T = any>(key: string): T {
+  return repoCache[key];
+}
+
+export function setRepoCached(key: string, value: any): void {
+  repoCache[key] = value;
 }
diff --git a/lib/util/got/cache-get.ts b/lib/util/got/cache-get.ts
index 803a789ac2..987f05805c 100644
--- a/lib/util/got/cache-get.ts
+++ b/lib/util/got/cache-get.ts
@@ -1,17 +1,13 @@
 import crypto from 'crypto';
 import { create } from './util';
 import { clone } from '../clone';
+import { getRepoCached, setRepoCached } from '../cache';
 
-// global.repoCache is reset to {} every time a repository is initialized
 // With this caching, it means every GET request is cached during each repository run
 
 export default create({
   options: {},
   handler: (options, next) => {
-    if (!global.repoCache) {
-      return next(options);
-    }
-
     if (options.stream) {
       return next(options);
     }
@@ -26,13 +22,16 @@ export default create({
             JSON.stringify({ href: options.href, headers: options.headers })
         )
         .digest('hex');
-      if (!global.repoCache[cacheKey] || options.useCache === false) {
-        global.repoCache[cacheKey] = next(options).catch((err) => {
-          delete global.repoCache[cacheKey];
-          throw err;
-        });
+      if (!getRepoCached(cacheKey) || options.useCache === false) {
+        setRepoCached(
+          cacheKey,
+          next(options).catch((err) => {
+            setRepoCached(cacheKey, null);
+            throw err;
+          })
+        );
       }
-      return global.repoCache[cacheKey].then((response) => ({
+      return getRepoCached<Promise<any>>(cacheKey).then((response) => ({
         ...response,
         body: clone(response.body),
       }));
diff --git a/lib/util/got/index.spec.ts b/lib/util/got/index.spec.ts
index 514abab0ae..f061eb65c4 100644
--- a/lib/util/got/index.spec.ts
+++ b/lib/util/got/index.spec.ts
@@ -8,6 +8,7 @@ import {
   PLATFORM_TYPE_GITLAB,
   PLATFORM_TYPE_GITHUB,
 } from '../../constants/platforms';
+import { clearRepoCache } from '../cache';
 
 const baseUrl = 'https://api.github.com';
 
@@ -19,7 +20,7 @@ describe(getName(__filename), () => {
   afterEach(() => {
     nock.cleanAll();
     hostRules.clear();
-    global.repoCache = {};
+    clearRepoCache();
     nock.enableNetConnect();
   });
 
@@ -66,7 +67,6 @@ describe(getName(__filename), () => {
   it('uses private-token auth', async () => {
     const req = mock({ reqheaders: { 'private-token': 'XXX' } });
     hostRules.add({ baseUrl, token: 'XXX' });
-    global.repoCache = null;
     expect(await got({ hostType: PLATFORM_TYPE_GITLAB })).toMatchSnapshot();
     expect(req.isDone()).toBe(true);
   });
@@ -97,14 +97,13 @@ describe(getName(__filename), () => {
       await got({ hostType: PLATFORM_TYPE_GITHUB, method: 'HEAD' })
     ).toMatchSnapshot();
 
-    global.repoCache = {};
+    clearRepoCache();
 
     await expect(got({ hostType: PLATFORM_TYPE_GITHUB })).rejects.toThrowError(
       'not-found'
     );
 
     expect(req.isDone()).toBe(true);
-    expect(global.repoCache).toEqual({});
   });
 
   it('streams no cache', async () => {
@@ -130,6 +129,5 @@ describe(getName(__filename), () => {
 
     expect(data).toBe('{}');
     expect(req.isDone()).toBe(true);
-    expect(global.repoCache).toEqual({});
   });
 });
diff --git a/lib/util/http/index.spec.ts b/lib/util/http/index.spec.ts
index 5ab2db72ad..78dfc1938c 100644
--- a/lib/util/http/index.spec.ts
+++ b/lib/util/http/index.spec.ts
@@ -79,6 +79,5 @@ describe(getName(__filename), () => {
 
     expect(data).toBe('{}');
     expect(nock.isDone()).toBe(true);
-    expect(global.repoCache).toEqual({});
   });
 });
diff --git a/lib/workers/repository/init/index.ts b/lib/workers/repository/init/index.ts
index d347c6ea93..a43a3d4fb5 100644
--- a/lib/workers/repository/init/index.ts
+++ b/lib/workers/repository/init/index.ts
@@ -8,9 +8,10 @@ import { detectSemanticCommits } from './semantic';
 import { detectVulnerabilityAlerts } from './vulnerability';
 import { platform } from '../../../platform';
 import { RenovateConfig } from '../../../config';
+import { clearRepoCache } from '../../../util/cache';
 
 export async function initRepo(input: RenovateConfig): Promise<RenovateConfig> {
-  global.repoCache = {};
+  clearRepoCache();
   let config: RenovateConfig = {
     ...input,
     errors: [],
diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts
index 698a49a006..d3e9019303 100644
--- a/lib/workers/repository/process/lookup/index.spec.ts
+++ b/lib/workers/repository/process/lookup/index.spec.ts
@@ -20,6 +20,7 @@ import * as datasourcePackagist from '../../../../datasource/packagist';
 import * as datasourceDocker from '../../../../datasource/docker';
 import * as datasourceGithubTags from '../../../../datasource/github-tags';
 import * as datasourceGitSubmodules from '../../../../datasource/git-submodules';
+import { clearRepoCache } from '../../../../util/cache';
 
 jest.mock('../../../../datasource/docker');
 jest.mock('../../../../datasource/git-submodules');
@@ -37,7 +38,7 @@ describe('workers/repository/process/lookup', () => {
     config.manager = 'npm';
     config.versioning = npmVersioning.id;
     config.rangeStrategy = 'replace';
-    global.repoCache = {};
+    clearRepoCache();
     jest.resetAllMocks();
   });
 
diff --git a/test/globals.ts b/test/globals.ts
index 52d4ce0ff6..ad44bb591d 100644
--- a/test/globals.ts
+++ b/test/globals.ts
@@ -10,8 +10,6 @@ jest.mock('../lib/platform', () => ({
 }));
 jest.mock('../lib/logger');
 
-global.repoCache = {};
-
 const tmpDir = process.env.RENOVATE_TMPDIR || process.env.TMPDIR || tmpdir();
 const cacheDir = join(tmpDir, './renovate/cache/renovate');
 
-- 
GitLab