diff --git a/lib/util/http/github.spec.ts b/lib/util/http/github.spec.ts index 26d2714252801e4dc8a5bb5a070d79e4367f34c7..1a36c4efcf82c4161e60ba38ae6d70c0ec5cc6ea 100644 --- a/lib/util/http/github.spec.ts +++ b/lib/util/http/github.spec.ts @@ -80,21 +80,21 @@ describe('util/http/github', () => { }); it('paginates', async () => { - const url = '/some-url'; + const url = '/some-url?per_page=2'; httpMock .scope(githubApiHost) .get(url) - .reply(200, ['a'], { - link: `<${url}?page=2>; rel="next", <${url}?page=3>; rel="last"`, + .reply(200, ['a', 'b'], { + link: `<${url}&page=2>; rel="next", <${url}&page=3>; rel="last"`, }) - .get(`${url}?page=2`) - .reply(200, ['b', 'c'], { - link: `<${url}?page=3>; rel="next", <${url}?page=3>; rel="last"`, + .get(`${url}&page=2`) + .reply(200, ['c', 'd'], { + link: `<${url}&page=3>; rel="next", <${url}&page=3>; rel="last"`, }) - .get(`${url}?page=3`) - .reply(200, ['d']); - const res = await githubApi.getJson('some-url', { paginate: true }); - expect(res.body).toEqual(['a', 'b', 'c', 'd']); + .get(`${url}&page=3`) + .reply(200, ['e']); + const res = await githubApi.getJson(url, { paginate: true }); + expect(res.body).toEqual(['a', 'b', 'c', 'd', 'e']); const trace = httpMock.getTrace(); expect(trace).toHaveLength(3); }); diff --git a/lib/util/http/github.ts b/lib/util/http/github.ts index ec0e949a687e4296b85aebf14dd28e019862df3d..dd5373602a2a33021dc36c48f11cce28740a64f0 100644 --- a/lib/util/http/github.ts +++ b/lib/util/http/github.ts @@ -210,31 +210,24 @@ export class GithubHttp extends Http<GithubHttpOptions, GithubHttpOptions> { if (opts.paginate) { // Check if result is paginated const pageLimit = opts.pageLimit ?? 10; - const linkHeader = - result?.headers?.link && - parseLinkHeader(result.headers.link as string); + const linkHeader = parseLinkHeader(result?.headers?.link); if (linkHeader?.next && linkHeader?.last) { - let lastPage = +linkHeader.last.page; + let lastPage = parseInt(linkHeader.last.page, 10); // istanbul ignore else: needs a test if (!process.env.RENOVATE_PAGINATE_ALL && opts.paginate !== 'all') { lastPage = Math.min(pageLimit, lastPage); } - const pageNumbers = Array.from( - new Array(lastPage), - (x, i) => i + 1 - ).slice(1); - const queue = pageNumbers.map( - (page) => (): Promise<HttpResponse<T>> => { + const queue = Array.from(new Array(lastPage), (_, i) => `${i + 1}`) + .slice(1) + .map((pageNumber) => (): Promise<HttpResponse<T>> => { const nextUrl = new URL(linkHeader.next.url, baseUrl); - nextUrl.search = ''; - nextUrl.searchParams.set('page', page.toString()); + nextUrl.searchParams.set('page', pageNumber); return this.request<T>( nextUrl, { ...opts, paginate: false }, okToRetry ); - } - ); + }); const pages = await pAll(queue, { concurrency: 5 }); if (opts.paginationField && is.plainObject(result.body)) { const paginatedResult = result.body[opts.paginationField];