diff --git a/lib/config/presets/gitlab.spec.ts b/lib/config/presets/gitlab.spec.ts index ff3a357901b5bca34e8b2e2fab903bff7c9dba2e..64b6db804b5e0ad1266afd1b1209543911d87b9b 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 5780818d57289669e19cc88e5ab4e5b755a7467d..2820554006d6eb539d138dd4294460d5cf4480e8 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 868478c0eaf060d185c0e8ab008616d229d1976e..7ba07ce6b8b8937f51afd6259f72337cc4a707b0 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 176ab304c9652aa83ebe6b9a98e7e34b72f84b23..ecf31c4e764765196b8d565d5e56815ebce27a22 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 e4a63bb018002150d005f8ff31d36e9ecc14f5bc..95124ba2e25f1e2e8ed8fed89ccfde50bb3b982f 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 24909e0b8549e94332269de2093e7f62efb8e8e2..f6620f750e9509a9e8d88e4ca0ba08a76059dff7 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 a902d97f704d80ac7c00bf060d43bcba139c3acc..535f956a9dacf50b0c2538e9f6a222ea692e935b 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 1655cd3bf64d69ce1dec4b524387437943f21888..8119c027c03478bc267ec0b74d3a45638343cee4 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 baa74f48de909855cc7a72e957f522c9f234a56b..5d345590c238482801a7d0b55bb6c3359fcab676 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 5b3c72a5cde2f175638a7db222f1a598e856e0f4..38d5de888d831557611e3c1f5ca6b73fbdf65b25 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 23f7351972fd642b3d1fe35fad63e2cf541a9f1b..2df73da159f63bc8fdb96baaa414c40e4c08750a 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 5c7e2eeea6957b7b80636c06522b2ed52085bf97..956c1ccca6bb51e2853ab203dcf45ef5c43e81d7 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 0a165808e61b8b09fa47a9da840058fd4a82a1a2..9d53a528397ed97736022da5213e446911fce90d 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 7122b79fd49a7b008dfcfbd2c11ec1bd21639ba6..39028e02ec8f39d82e00f0ec6d16c4dbc9857fe3 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 0bb37673b382bf957568207a8227d34d170850a8..02891c2948eae8f4090b3f4be1de9e3969154dd6 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 02c30d180fd65cfc809c5fce20fe31892c6c36ad..bc7b93f78397635b79adb2514d33987917693bfc 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 986835311df6da90797ebd22aa9c13c402f1064f..aa303cc6377071ffbaddace322afd96ba60954ef 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 ea5da05f9554b012207739c96faf41b5a402040f..eee0c94d7535218c6701361043772486b952b6b1 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 355f976d845f7c1b565d0997fb30af2ff9aabd72..48a15419dd3d5f91a2f06334cc29335fcdc6fb3b 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 80fd6929d2f1c0d48b72a15eb523942108d605d3..4a84c982a8c59ce56ee3d034075aec6b2bb13633 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 7cec2c8a8a036a4d8d3e5d9f159a564c5c014d9b..d1fda1294a4abdde8b006f5b0afb9a98b12546b8 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 8b696f5f1be4a692c897d3708c9a53806a8d99c5..739c6264bd6757449e055f9fbffb21ccb4ab4784 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 2f26b3f29b0207b951d403d099b812ebf43df425..5db9f38e134adf808da494ad2d66e701e92f27c1 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 5247219a4812ab5f27f26ea1ca33f9327b5b9a68..09b63174aead28891c9c46eb6b306b494bd72125 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 a5d9e06dc5bd510ea09f36774fadf2d7200c1522..320f678b363cbee0d6a55837509e4bc1764ab7e8 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 7d61edbc22f52a2fa3b02e29b92c07ff8844c596..608e69a8616be2568ff1151b65d0f9e738f0f8e6 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 b8d91df810d6c7fe100da8f689fd936fcdec1869..4bc09bb772d361cc76b3dcef4fc13812d882a19b 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 00de11a3e3660a1fcf4ee5c61ad754325809c6dd..66f25b97c4ea0d8f89ac409a12a6dbf078336a6e 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 7042dd8cfd301450997bee692da8a8a3779df089..3be189aebe8079426c639ddb1baf0d07b50bfd69 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 14413bad8b2a61f1776a640d2841c7dd68ee4cc9..cd41ba573e9649b7dc17dd0714a626807bc762d9 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 d4282d9dedd47148528190fe082b4c6b7596d3b7..1fd3b1863adfd4bbfa0f5c85f6b72bfb3edab049 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 803a789ac22cb8115d87f391853a85cdf80391f0..987f05805c2031f5ebb3ac8b4f060171e228c6ec 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 514abab0ae58fcc316be2e3760f4acbe5e73d9e1..f061eb65c42beb7d3c088aadb0883ec8c025e851 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 5ab2db72adddf811a4b51e4c595155c57e8b87da..78dfc1938c75f23cf69fe7c6f2381488e239b9ec 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 d347c6ea93bd49c372992df5e6b0fd859f6ca22b..a43a3d4fb58636cb07dd4e6dfced09bcd73528e2 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 698a49a0062b4ba51bcfdb8fd556f92fd7fd0934..d3e901930340cbe8877620e539adf7cf2af4b8b2 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 52d4ce0ff639ec7b772b7a31f9917471590abe7b..ad44bb591dcbbd0c67bec5ad255697f9889a46b1 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');