From 8785f70b93e876ba5187c7083be055e43e771e65 Mon Sep 17 00:00:00 2001 From: Michael Kriese <michael.kriese@visualon.de> Date: Mon, 6 Sep 2021 21:07:52 +0200 Subject: [PATCH] fix(core/http): fallback to github /gitlab hosttype (#11605) * fix(core/http): fallback to github /gitlab hosttype * fix: remove generic host rule * Update lib/util/http/index.ts Co-authored-by: Rhys Arkins <rhys@arkins.net> --- .../platform.spec.ts} | 31 ++++++++--- lib/constants/platforms.ts | 13 +++++ .../github/__snapshots__/index.spec.ts.snap | 27 ---------- lib/platform/github/index.spec.ts | 11 ---- lib/platform/github/index.ts | 8 +-- lib/types/github.ts | 8 --- lib/types/index.ts | 1 - lib/types/platform/gitlab/index.spec.ts | 25 --------- lib/types/platform/gitlab/index.ts | 7 --- lib/util/http/auth.ts | 12 +++-- lib/util/http/host-rules.spec.ts | 41 +++++++++++++++ lib/util/http/host-rules.ts | 51 ++++++++++++++++--- lib/util/http/index.spec.ts | 7 +++ lib/util/http/index.ts | 16 ++++-- 14 files changed, 149 insertions(+), 109 deletions(-) rename lib/{types/github.spec.ts => constants/platform.spec.ts} (50%) delete mode 100644 lib/types/github.ts delete mode 100644 lib/types/platform/gitlab/index.spec.ts diff --git a/lib/types/github.spec.ts b/lib/constants/platform.spec.ts similarity index 50% rename from lib/types/github.spec.ts rename to lib/constants/platform.spec.ts index 8e79ef350a..22984c3e06 100644 --- a/lib/types/github.spec.ts +++ b/lib/constants/platform.spec.ts @@ -1,13 +1,32 @@ -import { - PLATFORM_TYPE_GITHUB, - PLATFORM_TYPE_GITLAB, -} from '../constants/platforms'; import { id as GH_RELEASES_DS } from '../datasource/github-releases'; import { id as GH_TAGS_DS } from '../datasource/github-tags'; +import { GitlabReleasesDatasource } from '../datasource/gitlab-releases'; +import { id as GL_TAGS_DS } from '../datasource/gitlab-tags'; import { id as POD_DS } from '../datasource/pod'; -import { GITHUB_API_USING_HOST_TYPES } from './github'; +import { + GITHUB_API_USING_HOST_TYPES, + GITLAB_API_USING_HOST_TYPES, + PLATFORM_TYPE_GITHUB, + PLATFORM_TYPE_GITLAB, +} from './platforms'; + +describe('constants/platform', () => { + it('should be part of the GITLAB_API_USING_HOST_TYPES', () => { + expect(GITLAB_API_USING_HOST_TYPES.includes(GL_TAGS_DS)).toBeTrue(); + expect( + GITLAB_API_USING_HOST_TYPES.includes(GitlabReleasesDatasource.id) + ).toBeTrue(); + expect( + GITLAB_API_USING_HOST_TYPES.includes(PLATFORM_TYPE_GITLAB) + ).toBeTrue(); + }); + + it('should be not part of the GITLAB_API_USING_HOST_TYPES ', () => { + expect( + GITLAB_API_USING_HOST_TYPES.includes(PLATFORM_TYPE_GITHUB) + ).toBeFalse(); + }); -describe('types/github', () => { it('should be part of the GITHUB_API_USING_HOST_TYPES ', () => { expect(GITHUB_API_USING_HOST_TYPES.includes(GH_TAGS_DS)).toBeTrue(); expect(GITHUB_API_USING_HOST_TYPES.includes(GH_RELEASES_DS)).toBeTrue(); diff --git a/lib/constants/platforms.ts b/lib/constants/platforms.ts index 07b779c55e..94725ae52d 100644 --- a/lib/constants/platforms.ts +++ b/lib/constants/platforms.ts @@ -4,3 +4,16 @@ export const PLATFORM_TYPE_BITBUCKET_SERVER = 'bitbucket-server'; export const PLATFORM_TYPE_GITEA = 'gitea'; export const PLATFORM_TYPE_GITHUB = 'github'; export const PLATFORM_TYPE_GITLAB = 'gitlab'; + +export const GITHUB_API_USING_HOST_TYPES = [ + PLATFORM_TYPE_GITHUB, + 'github-releases', + 'github-tags', + 'pod', +]; + +export const GITLAB_API_USING_HOST_TYPES = [ + PLATFORM_TYPE_GITLAB, + 'gitlab-releases', + 'gitlab-tags', +]; diff --git a/lib/platform/github/__snapshots__/index.spec.ts.snap b/lib/platform/github/__snapshots__/index.spec.ts.snap index 57149d2ed2..37ff4dedb2 100644 --- a/lib/platform/github/__snapshots__/index.spec.ts.snap +++ b/lib/platform/github/__snapshots__/index.spec.ts.snap @@ -6875,33 +6875,6 @@ Array [ ] `; -exports[`platform/github/index initPlatform() should add initialized platform with predefined generic host rule for github api 1`] = ` -Object { - "endpoint": "https://api.github.com/", - "gitAuthor": "renovate@whitesourcesoftware.com", - "renovateUsername": "renovate-bot", -} -`; - -exports[`platform/github/index initPlatform() should add initialized platform with predefined generic host rule for github api 2`] = ` -[MockFunction] { - "calls": Array [ - Array [ - Object { - "matchHost": "api.github.com", - "token": "abc123", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - exports[`platform/github/index initPlatform() should support custom endpoint 1`] = ` Object { "endpoint": "https://ghe.renovatebot.com/", diff --git a/lib/platform/github/index.spec.ts b/lib/platform/github/index.spec.ts index ff04c1f864..23271d258b 100644 --- a/lib/platform/github/index.spec.ts +++ b/lib/platform/github/index.spec.ts @@ -129,17 +129,6 @@ describe('platform/github/index', () => { ).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot(); }); - - it('should add initialized platform with predefined generic host rule for github api', async () => { - expect( - await github.initPlatform({ - token: 'abc123', - username: 'renovate-bot', - gitAuthor: 'renovate@whitesourcesoftware.com', - } as any) - ).toMatchSnapshot(); - expect(hostRules.add).toMatchSnapshot(); - }); }); describe('getRepos', () => { diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts index f45144e82a..76c599a40a 100644 --- a/lib/platform/github/index.ts +++ b/lib/platform/github/index.ts @@ -23,7 +23,7 @@ import * as git from '../../util/git'; import * as hostRules from '../../util/host-rules'; import * as githubHttp from '../../util/http/github'; import { sanitize } from '../../util/sanitize'; -import { ensureTrailingSlash, parseUrl } from '../../util/url'; +import { ensureTrailingSlash } from '../../util/url'; import type { AggregatedVulnerabilities, BranchStatusConfig, @@ -115,12 +115,6 @@ export async function initPlatform({ renovateUsername, }; - // Generic github hostRule that per default all datasources using github api are enabled - const genericGithubHostRule = { - matchHost: parseUrl(defaults.endpoint).hostname, - token, - }; - hostRules.add(genericGithubHostRule); return platformConfig; } diff --git a/lib/types/github.ts b/lib/types/github.ts deleted file mode 100644 index 9281983377..0000000000 --- a/lib/types/github.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { PLATFORM_TYPE_GITHUB } from '../constants/platforms'; - -export const GITHUB_API_USING_HOST_TYPES = [ - PLATFORM_TYPE_GITHUB, - 'github-releases', - 'github-tags', - 'pod', -]; diff --git a/lib/types/index.ts b/lib/types/index.ts index a89dd31798..e1e0fa9d42 100644 --- a/lib/types/index.ts +++ b/lib/types/index.ts @@ -4,4 +4,3 @@ export * from './versioning'; export * from './branch-status'; export * from './vulnerability-alert'; export * from './pr-state'; -export * from './github'; diff --git a/lib/types/platform/gitlab/index.spec.ts b/lib/types/platform/gitlab/index.spec.ts deleted file mode 100644 index 945f2e4476..0000000000 --- a/lib/types/platform/gitlab/index.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { - PLATFORM_TYPE_GITHUB, - PLATFORM_TYPE_GITLAB, -} from '../../../constants/platforms'; -import { GitlabReleasesDatasource } from '../../../datasource/gitlab-releases'; -import { id as GL_TAGS_DS } from '../../../datasource/gitlab-tags'; -import { GITLAB_API_USING_HOST_TYPES } from './index'; - -describe('types/platform/gitlab/index', () => { - it('should be part of the GITLAB_API_USING_HOST_TYPES', () => { - expect(GITLAB_API_USING_HOST_TYPES.includes(GL_TAGS_DS)).toBeTrue(); - expect( - GITLAB_API_USING_HOST_TYPES.includes(GitlabReleasesDatasource.id) - ).toBeTrue(); - expect( - GITLAB_API_USING_HOST_TYPES.includes(PLATFORM_TYPE_GITLAB) - ).toBeTrue(); - }); - - it('should be not part of the GITLAB_API_USING_HOST_TYPES ', () => { - expect( - GITLAB_API_USING_HOST_TYPES.includes(PLATFORM_TYPE_GITHUB) - ).toBeFalse(); - }); -}); diff --git a/lib/types/platform/gitlab/index.ts b/lib/types/platform/gitlab/index.ts index 999f9149b1..a67df13e1a 100644 --- a/lib/types/platform/gitlab/index.ts +++ b/lib/types/platform/gitlab/index.ts @@ -1,4 +1,3 @@ -import { PLATFORM_TYPE_GITLAB } from '../../../constants/platforms'; import { GitTreeNode } from '../../git'; export type GitLabBranch = { @@ -13,9 +12,3 @@ export type GitlabTreeNode = { id: string; name: string; } & GitTreeNode; - -export const GITLAB_API_USING_HOST_TYPES = [ - PLATFORM_TYPE_GITLAB, - 'gitlab-releases', - 'gitlab-tags', -]; diff --git a/lib/util/http/auth.ts b/lib/util/http/auth.ts index b3a5383dfc..a8dfc3f42f 100644 --- a/lib/util/http/auth.ts +++ b/lib/util/http/auth.ts @@ -1,9 +1,11 @@ import is from '@sindresorhus/is'; -import { NormalizedOptions } from 'got'; -import { PLATFORM_TYPE_GITEA } from '../../constants/platforms'; -import { GITHUB_API_USING_HOST_TYPES } from '../../types'; -import { GITLAB_API_USING_HOST_TYPES } from '../../types/platform/gitlab'; -import { GotOptions } from './types'; +import type { NormalizedOptions } from 'got'; +import { + GITHUB_API_USING_HOST_TYPES, + GITLAB_API_USING_HOST_TYPES, + PLATFORM_TYPE_GITEA, +} from '../../constants/platforms'; +import type { GotOptions } from './types'; export function applyAuthorization(inOptions: GotOptions): GotOptions { const options: GotOptions = { ...inOptions }; diff --git a/lib/util/http/host-rules.spec.ts b/lib/util/http/host-rules.spec.ts index ea59b0461f..a46e6d3230 100644 --- a/lib/util/http/host-rules.spec.ts +++ b/lib/util/http/host-rules.spec.ts @@ -36,6 +36,11 @@ describe('util/http/host-rules', () => { authType: 'Basic', token: 'XXX', }); + + hostRules.add({ + hostType: 'gitlab-tags', + token: 'abc', + }); }); afterEach(() => { @@ -111,4 +116,40 @@ describe('util/http/host-rules', () => { } `); }); + + it('noAuth', () => { + expect(applyHostRules(url, { ...options, noAuth: true })) + .toMatchInlineSnapshot(` + Object { + "hostType": "github", + "noAuth": true, + } + `); + }); + + it('fallback to github', () => { + expect(applyHostRules(url, { ...options, hostType: 'github-tags' })) + .toMatchInlineSnapshot(` + Object { + "context": Object { + "authType": undefined, + }, + "hostType": "github-tags", + "token": "token", + } + `); + }); + + it('fallback to gitlab', () => { + expect(applyHostRules(url, { ...options, hostType: 'gitlab-tags' })) + .toMatchInlineSnapshot(` + Object { + "context": Object { + "authType": undefined, + }, + "hostType": "gitlab-tags", + "token": "abc", + } + `); + }); }); diff --git a/lib/util/http/host-rules.ts b/lib/util/http/host-rules.ts index 975a2ae541..d327f0418e 100644 --- a/lib/util/http/host-rules.ts +++ b/lib/util/http/host-rules.ts @@ -1,17 +1,54 @@ +import { + GITHUB_API_USING_HOST_TYPES, + GITLAB_API_USING_HOST_TYPES, + PLATFORM_TYPE_GITHUB, + PLATFORM_TYPE_GITLAB, +} from '../../constants/platforms'; import { logger } from '../../logger'; import { hasProxy } from '../../proxy'; +import type { HostRule } from '../../types'; import * as hostRules from '../host-rules'; -import { GotOptions } from './types'; +import type { GotOptions } from './types'; -// Apply host rules to requests +function findMatchingRules(options: GotOptions, url: string): HostRule { + const { hostType } = options; + let res = hostRules.find({ hostType, url }); + + // Fallback to `github` hostType + if ( + GITHUB_API_USING_HOST_TYPES.includes(hostType) && + hostType !== PLATFORM_TYPE_GITHUB + ) { + res = { + ...hostRules.find({ + hostType: PLATFORM_TYPE_GITHUB, + url, + }), + ...res, + }; + } + + // Fallback to `gitlab` hostType + if ( + GITLAB_API_USING_HOST_TYPES.includes(hostType) && + hostType !== PLATFORM_TYPE_GITLAB + ) { + res = { + ...hostRules.find({ + hostType: PLATFORM_TYPE_GITLAB, + url, + }), + ...res, + }; + } + return res; +} + +// Apply host rules to requests export function applyHostRules(url: string, inOptions: GotOptions): GotOptions { const options: GotOptions = { ...inOptions }; - const foundRules = - hostRules.find({ - hostType: options.hostType, - url, - }) || /* istanbul ignore next: can only happen in tests */ {}; + const foundRules = findMatchingRules(options, url); const { username, password, token, enabled, authType } = foundRules; if (options.noAuth) { logger.trace({ url }, `Authorization disabled`); diff --git a/lib/util/http/index.spec.ts b/lib/util/http/index.spec.ts index d7c7531a46..c42837687d 100644 --- a/lib/util/http/index.spec.ts +++ b/lib/util/http/index.spec.ts @@ -208,4 +208,11 @@ describe('util/http/index', () => { expect(bar).toBeTrue(); expect(baz).toBeTrue(); }); + + it('getBuffer', async () => { + httpMock.scope(baseUrl).get('/').reply(200, Buffer.from('test')); + const res = await http.getBuffer('http://renovate.com'); + expect(res.body).toBeInstanceOf(Buffer); + expect(res.body.toString('utf-8')).toEqual('test'); + }); }); diff --git a/lib/util/http/index.ts b/lib/util/http/index.ts index a3530c9526..d9c727ecab 100644 --- a/lib/util/http/index.ts +++ b/lib/util/http/index.ts @@ -53,12 +53,16 @@ export interface HttpResponse<T = string> { authorization?: boolean; } -function cloneResponse<T>(response: any): HttpResponse<T> { +function cloneResponse<T extends Buffer | string | any>( + response: HttpResponse<T> +): HttpResponse<T> { + const { body, statusCode, headers } = response; // clone body and headers so that the cached result doesn't get accidentally mutated + // Don't use json clone for buffers return { - statusCode: response.statusCode, - body: clone<T>(response.body), - headers: clone(response.headers), + statusCode, + body: body instanceof Buffer ? (body.slice() as T) : clone<T>(body), + headers: clone(headers), authorization: !!response.authorization, }; } @@ -95,7 +99,8 @@ async function gotRoutine<T>( // Cheat the TS compiler using `as` to pick a specific overload. // Otherwise it doesn't typecheck. const resp = await got<T>(url, options as GotJSONOptions); - const duration = resp.timings.phases.total || 0; + const duration = + resp.timings.phases.total || /* istanbul ignore next: can't be tested */ 0; const httpRequests = memCache.get('http-requests') || []; httpRequests.push({ ...requestStats, duration }); @@ -166,6 +171,7 @@ export class Http<GetOptions = HttpOptions, PostOptions = HttpPostOptions> { resPromise = memCache.get(cacheKey); } + // istanbul ignore else: no cache tests if (!resPromise) { const startTime = Date.now(); const queueTask = (): Promise<Response<T>> => { -- GitLab