From 86543938fb4528bed04c86ce32d1750ee8aa40ec Mon Sep 17 00:00:00 2001 From: Sergio Zharinov <zharinov@users.noreply.github.com> Date: Thu, 30 Jan 2020 12:51:51 +0400 Subject: [PATCH] feat(cdnjs): Add caching for CDNJS datasource (#5259) --- lib/constants/data-binary-source.ts | 2 +- lib/datasource/cdnjs/index.ts | 17 ++++++- test/datasource/cdnjs.spec.ts | 44 +++++-------------- test/datasource/cdnjs/_fixtures/bulma.json | 17 ------- test/datasource/cdnjs/_fixtures/d3-force.json | 20 --------- 5 files changed, 28 insertions(+), 72 deletions(-) diff --git a/lib/constants/data-binary-source.ts b/lib/constants/data-binary-source.ts index 9f6d528d57..46021a4454 100644 --- a/lib/constants/data-binary-source.ts +++ b/lib/constants/data-binary-source.ts @@ -1,6 +1,6 @@ // Datasource export const DATASOURCE_CARGO = 'cargo'; -// export const DATASOURCE_CDNJS = 'cdnjs'; +export const DATASOURCE_CDNJS = 'cdnjs'; export const DATASOURCE_DART = 'dart'; export const DATASOURCE_DOCKER = 'docker'; export const DATASOURCE_GIT_SUBMODULES = 'gitSubmodules'; diff --git a/lib/datasource/cdnjs/index.ts b/lib/datasource/cdnjs/index.ts index acac254aa0..7184c8f06f 100644 --- a/lib/datasource/cdnjs/index.ts +++ b/lib/datasource/cdnjs/index.ts @@ -2,12 +2,16 @@ import { logger } from '../../logger'; import got from '../../util/got'; import { ReleaseResult, PkgReleaseConfig } from '../common'; import { DATASOURCE_FAILURE } from '../../constants/error-messages'; +import { DATASOURCE_CDNJS } from '../../constants/data-binary-source'; interface CdnjsAsset { version: string; files: string[]; } +const cacheNamespace = `datasource-${DATASOURCE_CDNJS}`; +const cacheMinutes = 60; + interface CdnjsResponse { homepage?: string; repository?: { @@ -28,7 +32,16 @@ export async function getPkgReleases({ const [depName, ...assetParts] = lookupName.split('/'); const assetName = assetParts.join('/'); - const url = `https://api.cdnjs.com/libraries/${depName}`; + + const cacheKey = depName; + const cachedResult = await renovateCache.get<ReleaseResult>( + cacheNamespace, + cacheKey + ); + // istanbul ignore if + if (cachedResult) return cachedResult; + + const url = `https://api.cdnjs.com/libraries/${depName}?fields=homepage,repository,assets`; try { const res = await got(url, { json: true }); @@ -51,6 +64,8 @@ export async function getPkgReleases({ if (homepage) result.homepage = homepage; if (repository && repository.url) result.sourceUrl = repository.url; + await renovateCache.set(cacheNamespace, cacheKey, result, cacheMinutes); + return result; } catch (err) { const errorData = { depName, err }; diff --git a/test/datasource/cdnjs.spec.ts b/test/datasource/cdnjs.spec.ts index 30991b70c7..f6c9d4262c 100644 --- a/test/datasource/cdnjs.spec.ts +++ b/test/datasource/cdnjs.spec.ts @@ -3,7 +3,8 @@ import _got from '../../lib/util/got'; import { getPkgReleases } from '../../lib/datasource/cdnjs'; import { DATASOURCE_FAILURE } from '../../lib/constants/error-messages'; -const got: any = _got; +const got: jest.Mock<any> = _got as any; +jest.mock('../../lib/util/got'); let res1 = fs.readFileSync( 'test/datasource/cdnjs/_fixtures/d3-force.json', @@ -17,55 +18,36 @@ let res2 = fs.readFileSync( ); res2 = JSON.parse(res2); -jest.mock('../../lib/util/got'); - describe('datasource/cdnjs', () => { describe('getPkgReleases', () => { beforeEach(() => { jest.clearAllMocks(); - global.repoCache = {}; return global.renovateCache.rmAll(); }); it('returns null for empty result', async () => { - got.mockReturnValueOnce(null); + got.mockResolvedValueOnce(null); expect(await getPkgReleases({ lookupName: 'foo/bar' })).toBeNull(); }); it('returns null for missing fields', async () => { - got.mockReturnValueOnce({}); + got.mockResolvedValueOnce({}); expect(await getPkgReleases({ lookupName: 'foo/bar' })).toBeNull(); }); it('returns null for 404', async () => { - got.mockImplementationOnce(() => - Promise.reject({ - statusCode: 404, - }) - ); + got.mockRejectedValueOnce({ statusCode: 404 }); expect(await getPkgReleases({ lookupName: 'foo/bar' })).toBeNull(); }); it('returns null for 401', async () => { - got.mockImplementationOnce(() => - Promise.reject({ - statusCode: 401, - }) - ); + got.mockRejectedValueOnce({ statusCode: 401 }); expect(await getPkgReleases({ lookupName: 'foo/bar' })).toBeNull(); }); it('throws for 429', async () => { - got.mockImplementationOnce(() => - Promise.reject({ - statusCode: 429, - }) - ); + got.mockRejectedValueOnce({ statusCode: 429 }); await expect( getPkgReleases({ lookupName: 'foo/bar' }) ).rejects.toThrowError(DATASOURCE_FAILURE); }); it('throws for 5xx', async () => { - got.mockImplementationOnce(() => - Promise.reject({ - statusCode: 502, - }) - ); + got.mockRejectedValueOnce({ statusCode: 502 }); await expect( getPkgReleases({ lookupName: 'foo/bar' }) ).rejects.toThrowError(DATASOURCE_FAILURE); @@ -77,21 +59,17 @@ describe('datasource/cdnjs', () => { expect(await getPkgReleases({ lookupName: 'foo/bar' })).toBeNull(); }); it('returns null with wrong auth token', async () => { - got.mockReturnValueOnce( - Promise.reject({ - statusCode: 401, - }) - ); + got.mockRejectedValueOnce({ statusCode: 401 }); const res = await getPkgReleases({ lookupName: 'foo/bar' }); expect(res).toBeNull(); }); it('processes real data', async () => { - got.mockReturnValueOnce({ body: res1 }); + got.mockResolvedValueOnce({ body: res1 }); const res = await getPkgReleases({ lookupName: 'd3-force/d3-force.js' }); expect(res).toMatchSnapshot(); }); it('filters releases by asset presence', async () => { - got.mockReturnValueOnce({ body: res2 }); + got.mockResolvedValueOnce({ body: res2 }); const res = await getPkgReleases({ lookupName: 'bulma/only/0.7.5/style.css', }); diff --git a/test/datasource/cdnjs/_fixtures/bulma.json b/test/datasource/cdnjs/_fixtures/bulma.json index b972a5fe3c..e1a4db5ecd 100644 --- a/test/datasource/cdnjs/_fixtures/bulma.json +++ b/test/datasource/cdnjs/_fixtures/bulma.json @@ -1,26 +1,9 @@ { - "name": "bulma", - "filename": "css/bulma.min.css", - "version": "0.8.0", - "description": "Modern CSS framework based on Flexbox", "repository": { "type": "git", "url": "git+https://github.com/jgthms/bulma.git" }, - "keywords": [ - "css", - "sass", - "flexbox", - "responsive", - "framework" - ], - "author": "bulma", "homepage": "http://bulma.io", - "autoupdate": { - "source": "npm", - "target": "bulma" - }, - "license": "MIT", "assets": [ { "version": "0.8.0", diff --git a/test/datasource/cdnjs/_fixtures/d3-force.json b/test/datasource/cdnjs/_fixtures/d3-force.json index 8d4ffd6ed6..a462418acd 100644 --- a/test/datasource/cdnjs/_fixtures/d3-force.json +++ b/test/datasource/cdnjs/_fixtures/d3-force.json @@ -1,29 +1,9 @@ { - "name": "d3-force", - "filename": "d3-force.min.js", - "version": "1.1.0", - "description": "Force-directed graph layout using velocity Verlet integration.", "repository": { "type": "git", "url": "https://github.com/d3/d3-force.git" }, - "keywords": [ - "d3", - "d3-module", - "layout", - "network", - "graph", - "force", - "verlet", - "infovis" - ], - "author": "d3-force", "homepage": "https://d3js.org/d3-force/", - "autoupdate": { - "source": "npm", - "target": "d3-force" - }, - "license": "BSD-3-Clause", "assets": [ { "version": "1.1.0", -- GitLab