diff --git a/lib/util/http/github.spec.ts b/lib/util/http/github.spec.ts index 80d7752c2715d4ceb80c89cc4dd8bbb7038ca806..fe581b91e13222f1b200c7cb8c3bdfd5df867059 100644 --- a/lib/util/http/github.spec.ts +++ b/lib/util/http/github.spec.ts @@ -213,6 +213,69 @@ describe(getName(__filename), () => { } }`; + const page1 = { + data: { + repository: { + testItem: { + pageInfo: { + endCursor: 'cursor1', + hasNextPage: true, + }, + nodes: [ + { + number: 1, + state: 'OPEN', + title: 'title-1', + body: 'the body 1', + }, + ], + }, + }, + }, + }; + + const page2 = { + data: { + repository: { + testItem: { + pageInfo: { + endCursor: 'cursor2', + hasNextPage: true, + }, + nodes: [ + { + number: 2, + state: 'CLOSED', + title: 'title-2', + body: 'the body 2', + }, + ], + }, + }, + }, + }; + + const page3 = { + data: { + repository: { + testItem: { + pageInfo: { + endCursor: 'cursor3', + hasNextPage: false, + }, + nodes: [ + { + number: 3, + state: 'OPEN', + title: 'title-3', + body: 'the body 3', + }, + ], + }, + }, + }, + }; + it('strips path from baseUrl', async () => { setBaseUrl('https://ghe.mycompany.com/api/v3/'); const repository = { foo: 'foo', bar: 'bar' }; @@ -301,72 +364,29 @@ describe(getName(__filename), () => { httpMock .scope(githubApiHost) .post('/graphql') - .reply(200, { - data: { - repository: { - testItem: { - pageInfo: { - endCursor: 'cursor1', - hasNextPage: true, - }, - nodes: [ - { - number: 1, - state: 'OPEN', - title: 'title-1', - body: 'the body 1', - }, - ], - }, - }, - }, - }) + .reply(200, page1) .post('/graphql') - .reply(200, { - data: { - repository: { - testItem: { - pageInfo: { - endCursor: 'cursor2', - hasNextPage: true, - }, - nodes: [ - { - number: 2, - state: 'CLOSED', - title: 'title-2', - body: 'the body 2', - }, - ], - }, - }, - }, - }) + .reply(200, page2) .post('/graphql') - .reply(200, { - data: { - repository: { - testItem: { - pageInfo: { - endCursor: 'cursor3', - hasNextPage: false, - }, - nodes: [ - { - number: 3, - state: 'OPEN', - title: 'title-3', - body: 'the body 3', - }, - ], - }, - }, - }, - }); + .reply(200, page3); const items = await githubApi.queryRepoField(query, 'testItem'); expect(httpMock.getTrace()).toHaveLength(3); expect(items).toHaveLength(3); }); + it('limit result size', async () => { + httpMock + .scope(githubApiHost) + .post('/graphql') + .reply(200, page1) + .post('/graphql') + .reply(200, page2); + + const items = await githubApi.queryRepoField(query, 'testItem', { + limit: 2, + }); + expect(httpMock.getTrace()).toHaveLength(2); + expect(items).toHaveLength(2); + }); }); }); diff --git a/lib/util/http/github.ts b/lib/util/http/github.ts index 5c53567c394f854d88b68019cbd91c9444c2de69..491f086139cbb66846806758fb7b499af155c06b 100644 --- a/lib/util/http/github.ts +++ b/lib/util/http/github.ts @@ -124,6 +124,7 @@ function handleGotError( interface GraphqlOptions { paginate?: boolean; count?: number; + limit?: number; acceptHeader?: string; fromEnd?: boolean; } @@ -251,13 +252,14 @@ export class GithubHttp extends Http<GithubHttpOptions, GithubHttpOptions> { const { paginate = true } = options; let count = options.count || 100; + let limit = options.limit || 1000; let cursor: string = null; let isIterating = true; while (isIterating) { let query = queryOrig; if (paginate) { - let replacement = `$1${fieldName}$2(first: ${count}`; + let replacement = `$1${fieldName}$2(first: ${Math.min(count, limit)}`; replacement += cursor ? `, after: "${cursor}", ` : ', '; query = query.replace(regex, replacement); } @@ -267,7 +269,11 @@ export class GithubHttp extends Http<GithubHttpOptions, GithubHttpOptions> { result.push(...nodes); result.push(...edges); - if (paginate && pageInfo) { + limit = Math.max(0, limit - nodes.length - edges.length); + + if (limit === 0) { + isIterating = false; + } else if (paginate && pageInfo) { const { hasNextPage, endCursor } = pageInfo; if (hasNextPage && endCursor) { cursor = endCursor;