mirror of
https://github.com/actions/setup-java.git
synced 2026-06-23 12:27:43 +00:00
Use Link headers for Adoptium pagination
This commit is contained in:
parent
b622de1dfa
commit
dc9d954508
@ -136,22 +136,19 @@ describe('getAvailableVersions', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
it('load available versions', async () => {
|
it('load available versions', async () => {
|
||||||
|
const nextPageUrl =
|
||||||
|
'https://api.adoptopenjdk.net/v3/assets/version/%5B1.0,100.0%5D?page=1&page_size=20';
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
spyHttpClient
|
spyHttpClient
|
||||||
.mockReturnValueOnce({
|
.mockReturnValueOnce({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: {},
|
headers: {link: `<${nextPageUrl}>; rel="next"`},
|
||||||
result: manifestData as any
|
result: manifestData as any
|
||||||
})
|
})
|
||||||
.mockReturnValueOnce({
|
.mockReturnValueOnce({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: {},
|
headers: {},
|
||||||
result: manifestData as any
|
result: manifestData as any
|
||||||
})
|
|
||||||
.mockReturnValueOnce({
|
|
||||||
statusCode: 200,
|
|
||||||
headers: {},
|
|
||||||
result: []
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const distribution = new AdoptDistribution(
|
const distribution = new AdoptDistribution(
|
||||||
@ -166,6 +163,7 @@ describe('getAvailableVersions', () => {
|
|||||||
const availableVersions = await distribution['getAvailableVersions']();
|
const availableVersions = await distribution['getAvailableVersions']();
|
||||||
expect(availableVersions).not.toBeNull();
|
expect(availableVersions).not.toBeNull();
|
||||||
expect(availableVersions.length).toBe(manifestData.length * 2);
|
expect(availableVersions.length).toBe(manifestData.length * 2);
|
||||||
|
expect(spyHttpClient).toHaveBeenNthCalledWith(2, nextPageUrl);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
|
|||||||
@ -82,22 +82,19 @@ describe('getAvailableVersions', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
it('load available versions', async () => {
|
it('load available versions', async () => {
|
||||||
|
const nextPageUrl =
|
||||||
|
'https://api.adoptopenjdk.net/v3/assets/version/%5B1.0,100.0%5D?page=1&page_size=20';
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
spyHttpClient
|
spyHttpClient
|
||||||
.mockReturnValueOnce({
|
.mockReturnValueOnce({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: {},
|
headers: {link: `<${nextPageUrl}>; rel="next"`},
|
||||||
result: manifestData as any
|
result: manifestData as any
|
||||||
})
|
})
|
||||||
.mockReturnValueOnce({
|
.mockReturnValueOnce({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: {},
|
headers: {},
|
||||||
result: manifestData as any
|
result: manifestData as any
|
||||||
})
|
|
||||||
.mockReturnValueOnce({
|
|
||||||
statusCode: 200,
|
|
||||||
headers: {},
|
|
||||||
result: []
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const distribution = new SemeruDistribution({
|
const distribution = new SemeruDistribution({
|
||||||
@ -109,6 +106,7 @@ describe('getAvailableVersions', () => {
|
|||||||
const availableVersions = await distribution['getAvailableVersions']();
|
const availableVersions = await distribution['getAvailableVersions']();
|
||||||
expect(availableVersions).not.toBeNull();
|
expect(availableVersions).not.toBeNull();
|
||||||
expect(availableVersions.length).toBe(manifestData.length * 2);
|
expect(availableVersions.length).toBe(manifestData.length * 2);
|
||||||
|
expect(spyHttpClient).toHaveBeenNthCalledWith(2, nextPageUrl);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
|
|||||||
@ -93,22 +93,19 @@ describe('getAvailableVersions', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
it('load available versions', async () => {
|
it('load available versions', async () => {
|
||||||
|
const nextPageUrl =
|
||||||
|
'https://api.adoptium.net/v3/assets/version/%5B1.0,100.0%5D?page=1&page_size=20';
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
spyHttpClient
|
spyHttpClient
|
||||||
.mockReturnValueOnce({
|
.mockReturnValueOnce({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: {},
|
headers: {link: `<${nextPageUrl}>; rel="next"`},
|
||||||
result: manifestData as any
|
result: manifestData as any
|
||||||
})
|
})
|
||||||
.mockReturnValueOnce({
|
.mockReturnValueOnce({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: {},
|
headers: {},
|
||||||
result: manifestData as any
|
result: manifestData as any
|
||||||
})
|
|
||||||
.mockReturnValueOnce({
|
|
||||||
statusCode: 200,
|
|
||||||
headers: {},
|
|
||||||
result: []
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const distribution = new TemurinDistribution(
|
const distribution = new TemurinDistribution(
|
||||||
@ -123,6 +120,7 @@ describe('getAvailableVersions', () => {
|
|||||||
const availableVersions = await distribution['getAvailableVersions']();
|
const availableVersions = await distribution['getAvailableVersions']();
|
||||||
expect(availableVersions).not.toBeNull();
|
expect(availableVersions).not.toBeNull();
|
||||||
expect(availableVersions.length).toBe(manifestData.length * 2);
|
expect(availableVersions.length).toBe(manifestData.length * 2);
|
||||||
|
expect(spyHttpClient).toHaveBeenNthCalledWith(2, nextPageUrl);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import * as fs from 'fs';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import {
|
import {
|
||||||
convertVersionToSemver,
|
convertVersionToSemver,
|
||||||
|
getNextPageUrlFromLinkHeader,
|
||||||
getVersionFromFileContent,
|
getVersionFromFileContent,
|
||||||
isVersionSatisfies,
|
isVersionSatisfies,
|
||||||
isCacheFeatureAvailable,
|
isCacheFeatureAvailable,
|
||||||
@ -85,6 +86,27 @@ describe('convertVersionToSemver', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getNextPageUrlFromLinkHeader', () => {
|
||||||
|
it.each([
|
||||||
|
[
|
||||||
|
{
|
||||||
|
link: '<https://api.adoptium.net/v3/info/release_versions?page=1&page_size=10>; rel="next"'
|
||||||
|
},
|
||||||
|
'https://api.adoptium.net/v3/info/release_versions?page=1&page_size=10'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
Link: '<https://example.com/last?page=5>; rel="last", <https://example.com/next?page=2>; rel="next"'
|
||||||
|
},
|
||||||
|
'https://example.com/next?page=2'
|
||||||
|
],
|
||||||
|
[{link: '<https://example.com/last?page=5>; rel="last"'}, null],
|
||||||
|
[undefined, null]
|
||||||
|
])('returns %s -> %s', (headers, expected) => {
|
||||||
|
expect(getNextPageUrlFromLinkHeader(headers)).toBe(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('getVersionFromFileContent', () => {
|
describe('getVersionFromFileContent', () => {
|
||||||
describe('.sdkmanrc', () => {
|
describe('.sdkmanrc', () => {
|
||||||
it.each([
|
it.each([
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import {
|
|||||||
} from '../base-models';
|
} from '../base-models';
|
||||||
import {
|
import {
|
||||||
extractJdkFile,
|
extractJdkFile,
|
||||||
|
getNextPageUrlFromLinkHeader,
|
||||||
getDownloadArchiveExtension,
|
getDownloadArchiveExtension,
|
||||||
isVersionSatisfies,
|
isVersionSatisfies,
|
||||||
renameWinArchive
|
renameWinArchive
|
||||||
@ -125,30 +126,23 @@ export class AdoptDistribution extends JavaBase {
|
|||||||
`jvm_impl=${this.jvmImpl.toLowerCase()}`
|
`jvm_impl=${this.jvmImpl.toLowerCase()}`
|
||||||
].join('&');
|
].join('&');
|
||||||
|
|
||||||
// need to iterate through all pages to retrieve the list of all versions
|
const requestArguments = `${baseRequestArguments}&page_size=20&page=0`;
|
||||||
// Adopt API doesn't provide way to retrieve the count of pages to iterate so infinity loop
|
let availableVersionsUrl = `https://api.adoptopenjdk.net/v3/assets/version/${versionRange}?${requestArguments}`;
|
||||||
let page_index = 0;
|
|
||||||
const availableVersions: IAdoptAvailableVersions[] = [];
|
const availableVersions: IAdoptAvailableVersions[] = [];
|
||||||
while (true) {
|
if (core.isDebug()) {
|
||||||
const requestArguments = `${baseRequestArguments}&page_size=20&page=${page_index}`;
|
core.debug(`Gathering available versions from '${availableVersionsUrl}'`);
|
||||||
const availableVersionsUrl = `https://api.adoptopenjdk.net/v3/assets/version/${versionRange}?${requestArguments}`;
|
}
|
||||||
if (core.isDebug() && page_index === 0) {
|
|
||||||
// url is identical except page_index so print it once for debug
|
|
||||||
core.debug(
|
|
||||||
`Gathering available versions from '${availableVersionsUrl}'`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const paginationPage = (
|
while (availableVersionsUrl) {
|
||||||
await this.http.getJson<IAdoptAvailableVersions[]>(availableVersionsUrl)
|
const response =
|
||||||
).result;
|
await this.http.getJson<IAdoptAvailableVersions[]>(availableVersionsUrl);
|
||||||
|
const paginationPage = response.result;
|
||||||
|
availableVersionsUrl = getNextPageUrlFromLinkHeader(response.headers);
|
||||||
if (paginationPage === null || paginationPage.length === 0) {
|
if (paginationPage === null || paginationPage.length === 0) {
|
||||||
// break infinity loop because we have reached end of pagination
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
availableVersions.push(...paginationPage);
|
availableVersions.push(...paginationPage);
|
||||||
page_index++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import {
|
import {
|
||||||
extractJdkFile,
|
extractJdkFile,
|
||||||
|
getNextPageUrlFromLinkHeader,
|
||||||
getDownloadArchiveExtension,
|
getDownloadArchiveExtension,
|
||||||
isVersionSatisfies,
|
isVersionSatisfies,
|
||||||
renameWinArchive
|
renameWinArchive
|
||||||
@ -155,32 +156,24 @@ export class SemeruDistribution extends JavaBase {
|
|||||||
`jvm_impl=openj9`
|
`jvm_impl=openj9`
|
||||||
].join('&');
|
].join('&');
|
||||||
|
|
||||||
// need to iterate through all pages to retrieve the list of all versions
|
const requestArguments = `${baseRequestArguments}&page_size=20&page=0`;
|
||||||
// Adoptium API doesn't provide way to retrieve the count of pages to iterate so infinity loop
|
let availableVersionsUrl = `https://api.adoptopenjdk.net/v3/assets/version/${versionRange}?${requestArguments}`;
|
||||||
let page_index = 0;
|
|
||||||
const availableVersions: ISemeruAvailableVersions[] = [];
|
const availableVersions: ISemeruAvailableVersions[] = [];
|
||||||
while (true) {
|
if (core.isDebug()) {
|
||||||
const requestArguments = `${baseRequestArguments}&page_size=20&page=${page_index}`;
|
core.debug(`Gathering available versions from '${availableVersionsUrl}'`);
|
||||||
const availableVersionsUrl = `https://api.adoptopenjdk.net/v3/assets/version/${versionRange}?${requestArguments}`;
|
}
|
||||||
if (core.isDebug() && page_index === 0) {
|
|
||||||
// url is identical except page_index so print it once for debug
|
|
||||||
core.debug(
|
|
||||||
`Gathering available versions from '${availableVersionsUrl}'`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const paginationPage = (
|
while (availableVersionsUrl) {
|
||||||
await this.http.getJson<ISemeruAvailableVersions[]>(
|
const response = await this.http.getJson<ISemeruAvailableVersions[]>(
|
||||||
availableVersionsUrl
|
availableVersionsUrl
|
||||||
)
|
);
|
||||||
).result;
|
const paginationPage = response.result;
|
||||||
|
availableVersionsUrl = getNextPageUrlFromLinkHeader(response.headers);
|
||||||
if (paginationPage === null || paginationPage.length === 0) {
|
if (paginationPage === null || paginationPage.length === 0) {
|
||||||
// break infinity loop because we have reached end of pagination
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
availableVersions.push(...paginationPage);
|
availableVersions.push(...paginationPage);
|
||||||
page_index++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import {
|
|||||||
} from '../base-models';
|
} from '../base-models';
|
||||||
import {
|
import {
|
||||||
extractJdkFile,
|
extractJdkFile,
|
||||||
|
getNextPageUrlFromLinkHeader,
|
||||||
getDownloadArchiveExtension,
|
getDownloadArchiveExtension,
|
||||||
isVersionSatisfies,
|
isVersionSatisfies,
|
||||||
renameWinArchive
|
renameWinArchive
|
||||||
@ -123,32 +124,25 @@ export class TemurinDistribution extends JavaBase {
|
|||||||
`jvm_impl=${this.jvmImpl.toLowerCase()}`
|
`jvm_impl=${this.jvmImpl.toLowerCase()}`
|
||||||
].join('&');
|
].join('&');
|
||||||
|
|
||||||
// need to iterate through all pages to retrieve the list of all versions
|
const requestArguments = `${baseRequestArguments}&page_size=20&page=0`;
|
||||||
// Adoptium API doesn't provide way to retrieve the count of pages to iterate so infinity loop
|
let availableVersionsUrl = `https://api.adoptium.net/v3/assets/version/${versionRange}?${requestArguments}`;
|
||||||
let page_index = 0;
|
|
||||||
const availableVersions: ITemurinAvailableVersions[] = [];
|
const availableVersions: ITemurinAvailableVersions[] = [];
|
||||||
while (true) {
|
if (core.isDebug()) {
|
||||||
const requestArguments = `${baseRequestArguments}&page_size=20&page=${page_index}`;
|
core.debug(`Gathering available versions from '${availableVersionsUrl}'`);
|
||||||
const availableVersionsUrl = `https://api.adoptium.net/v3/assets/version/${versionRange}?${requestArguments}`;
|
}
|
||||||
if (core.isDebug() && page_index === 0) {
|
|
||||||
// url is identical except page_index so print it once for debug
|
while (availableVersionsUrl) {
|
||||||
core.debug(
|
const response = await this.http.getJson<ITemurinAvailableVersions[]>(
|
||||||
`Gathering available versions from '${availableVersionsUrl}'`
|
availableVersionsUrl
|
||||||
);
|
);
|
||||||
}
|
const paginationPage = response.result;
|
||||||
|
availableVersionsUrl = getNextPageUrlFromLinkHeader(response.headers);
|
||||||
|
|
||||||
const paginationPage = (
|
|
||||||
await this.http.getJson<ITemurinAvailableVersions[]>(
|
|
||||||
availableVersionsUrl
|
|
||||||
)
|
|
||||||
).result;
|
|
||||||
if (paginationPage === null || paginationPage.length === 0) {
|
if (paginationPage === null || paginationPage.length === 0) {
|
||||||
// break infinity loop because we have reached end of pagination
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
availableVersions.push(...paginationPage);
|
availableVersions.push(...paginationPage);
|
||||||
page_index++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
|
|||||||
22
src/util.ts
22
src/util.ts
@ -201,6 +201,28 @@ export function getGitHubHttpHeaders(): OutgoingHttpHeaders {
|
|||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getNextPageUrlFromLinkHeader(
|
||||||
|
headers?: Record<string, string | string[] | undefined>
|
||||||
|
): string | null {
|
||||||
|
if (!headers) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const linkHeader = headers.link ?? headers.Link;
|
||||||
|
if (!linkHeader) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizedLinkHeader = Array.isArray(linkHeader)
|
||||||
|
? linkHeader.join(',')
|
||||||
|
: linkHeader;
|
||||||
|
const nextLinkMatch = normalizedLinkHeader.match(
|
||||||
|
/<([^>]+)>\s*;\s*rel="?next"?/i
|
||||||
|
);
|
||||||
|
|
||||||
|
return nextLinkMatch?.[1] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
// Rename archive to add extension because after downloading
|
// Rename archive to add extension because after downloading
|
||||||
// archive does not contain extension type and it leads to some issues
|
// archive does not contain extension type and it leads to some issues
|
||||||
// on Windows runners without PowerShell Core.
|
// on Windows runners without PowerShell Core.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user