From 9779d77eb11b28f6579de4da8076a9ce939ee91b Mon Sep 17 00:00:00 2001 From: Lukas Eipert <leipert@users.noreply.github.com> Date: Mon, 8 Jul 2019 16:43:39 +0200 Subject: [PATCH] feat(gitlab): Improve performance for projects with a lot of branches (#3936) 1. `findPr` also includes the `source_branch` API parameter which shortens execution time considerably 2. `getPrList` also filters `author_id` for the renovate's user --- lib/platform/common.ts | 1 + lib/platform/gitlab/index.ts | 55 ++++++++++++++++++------------ test/platform/gitlab/index.spec.ts | 36 ++++++++++++------- 3 files changed, 58 insertions(+), 34 deletions(-) diff --git a/lib/platform/common.ts b/lib/platform/common.ts index a8703c70df..512ac0e8d9 100644 --- a/lib/platform/common.ts +++ b/lib/platform/common.ts @@ -4,6 +4,7 @@ export interface IGotApiOptions { useCache?: boolean; hostType?: string; body?: any; + query?: string | { [key: string]: string | number } | URLSearchParams; } export interface IGotApi<TOptions extends object = any> { diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts index 18ae6192ae..1308558f48 100644 --- a/lib/platform/gitlab/index.ts +++ b/lib/platform/gitlab/index.ts @@ -1,4 +1,4 @@ -import URL from 'url'; +import URL, { URLSearchParams } from 'url'; import is from '@sindresorhus/is'; import api from './gl-got-wrapper'; @@ -22,6 +22,8 @@ const defaults = { endpoint: 'https://gitlab.com/api/v4/', }; +let authorId: number; + export async function initPlatform({ endpoint, token, @@ -42,7 +44,9 @@ export async function initPlatform({ logger.info('Using default GitLab endpoint: ' + res.endpoint); } try { - res.gitAuthor = (await api.get(`user`, { token })).body.email; + const user = (await api.get(`user`, { token })).body; + res.gitAuthor = user.email; + authorId = user.id; } catch (err) { logger.info( { err }, @@ -203,8 +207,13 @@ export async function getBranchPr(branchName: string) { if (!(await branchExists(branchName))) { return null; } - const urlString = `projects/${config.repository}/merge_requests?state=opened&per_page=100`; - const res = await api.get(urlString, { paginate: true }); + const query = new URLSearchParams({ + per_page: '100', + state: 'opened', + source_branch: branchName, + }); + const urlString = `projects/${config.repository}/merge_requests`; + const res = await api.get(urlString, { query, paginate: true }); logger.debug(`Got res with ${res.body.length} results`); let pr: any = null; res.body.forEach((result: { source_branch: string }) => { @@ -590,25 +599,29 @@ export async function ensureCommentRemoval(issueNo: number, topic: string) { } } +const mapPullRequests = (pr: { + iid: number; + source_branch: string; + title: string; + state: string; + created_at: string; +}) => ({ + number: pr.iid, + branchName: pr.source_branch, + title: pr.title, + state: pr.state === 'opened' ? 'open' : pr.state, + createdAt: pr.created_at, +}); + export async function getPrList() { if (!config.prList) { - const urlString = `projects/${config.repository}/merge_requests?per_page=100`; - const res = await api.get(urlString, { paginate: true }); - config.prList = res.body.map( - (pr: { - iid: number; - source_branch: string; - title: string; - state: string; - created_at: string; - }) => ({ - number: pr.iid, - branchName: pr.source_branch, - title: pr.title, - state: pr.state === 'opened' ? 'open' : pr.state, - createdAt: pr.created_at, - }) - ); + const query = new URLSearchParams({ + per_page: '100', + author_id: `${authorId}`, + }); + const urlString = `projects/${config.repository}/merge_requests`; + const res = await api.get(urlString, { query, paginate: true }); + config.prList = res.body.map(mapPullRequests); } return config.prList; } diff --git a/test/platform/gitlab/index.spec.ts b/test/platform/gitlab/index.spec.ts index 71485c73a6..104212f266 100644 --- a/test/platform/gitlab/index.spec.ts +++ b/test/platform/gitlab/index.spec.ts @@ -260,13 +260,13 @@ describe('platform/gitlab', () => { // branchExists body: [], } as any); - const pr = await gitlab.getBranchPr('somebranch'); + const pr = await gitlab.getBranchPr('some-branch'); expect(pr).toBeNull(); }); it('should return the PR object', async () => { await initRepo(); api.get.mockReturnValueOnce({ - body: [{ number: 91, source_branch: 'somebranch' }], + body: [{ iid: 91, source_branch: 'some-branch', state: 'opened' }], } as any); api.get.mockReturnValueOnce({ body: { @@ -284,7 +284,7 @@ describe('platform/gitlab', () => { api.get.mockReturnValueOnce({ body: [] } as any); // get branch commit api.get.mockReturnValueOnce({ body: [{ status: 'success' }] } as any); // get commit statuses api.get.mockReturnValueOnce({ body: 'foo' } as any); - const pr = await gitlab.getBranchPr('somebranch'); + const pr = await gitlab.getBranchPr('some-branch'); expect(pr).toMatchSnapshot(); }); }); @@ -633,7 +633,7 @@ describe('platform/gitlab', () => { api.get.mockResolvedValueOnce({ body: [ { - number: 1, + iid: 1, source_branch: 'branch-a', title: 'branch a pr', state: 'opened', @@ -647,7 +647,7 @@ describe('platform/gitlab', () => { api.get.mockReturnValueOnce({ body: [ { - number: 1, + iid: 1, source_branch: 'branch-a', title: 'branch a pr', state: 'merged', @@ -657,25 +657,35 @@ describe('platform/gitlab', () => { const res = await gitlab.findPr('branch-a', null, '!open'); expect(res).toBeDefined(); }); - it('caches pr list', async () => { + + it('returns true if open and with title', async () => { api.get.mockReturnValueOnce({ body: [ { - number: 1, + iid: 1, source_branch: 'branch-a', title: 'branch a pr', state: 'opened', }, ], } as any); - let res = await gitlab.findPr('branch-a', null); - expect(res).toBeDefined(); - res = await gitlab.findPr('branch-a', 'branch a pr'); + const res = await gitlab.findPr('branch-a', 'branch a pr', 'open'); expect(res).toBeDefined(); - res = await gitlab.findPr('branch-a', 'branch a pr', 'open'); + }); + + it('returns true with title', async () => { + api.get.mockReturnValueOnce({ + body: [ + { + iid: 1, + source_branch: 'branch-a', + title: 'branch a pr', + state: 'opened', + }, + ], + } as any); + const res = await gitlab.findPr('branch-a', 'branch a pr'); expect(res).toBeDefined(); - res = await gitlab.findPr('branch-b'); - expect(res).not.toBeDefined(); }); }); describe('createPr(branchName, title, body)', () => { -- GitLab