Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions __tests__/distributors/adopt-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as core from '@actions/core';
describe('getAvailableVersions', () => {
let spyHttpClient: jest.SpyInstance;
let spyCoreError: jest.SpyInstance;
let spyCoreWarning: jest.SpyInstance;

beforeEach(() => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
Expand All @@ -26,6 +27,8 @@ describe('getAvailableVersions', () => {
// Mock core.error to suppress error logs
spyCoreError = jest.spyOn(core, 'error');
spyCoreError.mockImplementation(() => {});
spyCoreWarning = jest.spyOn(core, 'warning');
spyCoreWarning.mockImplementation(() => {});
});

afterEach(() => {
Expand Down Expand Up @@ -136,22 +139,19 @@ describe('getAvailableVersions', () => {
);

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
.mockReturnValueOnce({
statusCode: 200,
headers: {},
headers: {link: `<${nextPageUrl}>; rel="next"`},
result: manifestData as any
})
.mockReturnValueOnce({
statusCode: 200,
headers: {},
result: manifestData as any
})
.mockReturnValueOnce({
statusCode: 200,
headers: {},
result: []
});

const distribution = new AdoptDistribution(
Expand All @@ -166,6 +166,33 @@ describe('getAvailableVersions', () => {
const availableVersions = await distribution['getAvailableVersions']();
expect(availableVersions).not.toBeNull();
expect(availableVersions.length).toBe(manifestData.length * 2);
expect(spyHttpClient).toHaveBeenNthCalledWith(2, nextPageUrl);
});

it('stops pagination after 1000 pages as a safeguard', async () => {
const nextPageUrl = 'https://example.com/releases?page=2';
spyHttpClient.mockReturnValue({
statusCode: 200,
headers: {link: `<${nextPageUrl}>; rel="next"`},
result: [{version_data: {semver: '17.0.1'}, binaries: []}] as any
});

const distribution = new AdoptDistribution(
{
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
},
AdoptImplementation.Hotspot
);

await distribution['getAvailableVersions']();

expect(spyHttpClient).toHaveBeenCalledTimes(1000);
expect(spyCoreWarning).toHaveBeenCalledWith(
expect.stringContaining('Reached pagination safeguard limit (1000 pages)')
);
});

it.each([
Expand Down
36 changes: 30 additions & 6 deletions __tests__/distributors/semeru-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as core from '@actions/core';
describe('getAvailableVersions', () => {
let spyHttpClient: jest.SpyInstance;
let spyCoreError: jest.SpyInstance;
let spyCoreWarning: jest.SpyInstance;

beforeEach(() => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
Expand All @@ -20,6 +21,8 @@ describe('getAvailableVersions', () => {
// Mock core.error to suppress error logs
spyCoreError = jest.spyOn(core, 'error');
spyCoreError.mockImplementation(() => {});
spyCoreWarning = jest.spyOn(core, 'warning');
spyCoreWarning.mockImplementation(() => {});
});

afterEach(() => {
Expand Down Expand Up @@ -82,22 +85,19 @@ describe('getAvailableVersions', () => {
);

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
.mockReturnValueOnce({
statusCode: 200,
headers: {},
headers: {link: `<${nextPageUrl}>; rel="next"`},
result: manifestData as any
})
.mockReturnValueOnce({
statusCode: 200,
headers: {},
result: manifestData as any
})
.mockReturnValueOnce({
statusCode: 200,
headers: {},
result: []
});

const distribution = new SemeruDistribution({
Expand All @@ -109,6 +109,30 @@ describe('getAvailableVersions', () => {
const availableVersions = await distribution['getAvailableVersions']();
expect(availableVersions).not.toBeNull();
expect(availableVersions.length).toBe(manifestData.length * 2);
expect(spyHttpClient).toHaveBeenNthCalledWith(2, nextPageUrl);
});

it('stops pagination after 1000 pages as a safeguard', async () => {
const nextPageUrl = 'https://example.com/releases?page=2';
spyHttpClient.mockReturnValue({
statusCode: 200,
headers: {link: `<${nextPageUrl}>; rel="next"`},
result: [{version_data: {semver: '17.0.1'}, binaries: []}] as any
});

const distribution = new SemeruDistribution({
version: '8',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});

await distribution['getAvailableVersions']();

expect(spyHttpClient).toHaveBeenCalledTimes(1000);
expect(spyCoreWarning).toHaveBeenCalledWith(
expect.stringContaining('Reached pagination safeguard limit (1000 pages)')
);
});

it.each([
Expand Down
39 changes: 33 additions & 6 deletions __tests__/distributors/temurin-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as core from '@actions/core';
describe('getAvailableVersions', () => {
let spyHttpClient: jest.SpyInstance;
let spyCoreError: jest.SpyInstance;
let spyCoreWarning: jest.SpyInstance;

beforeEach(() => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
Expand All @@ -23,6 +24,8 @@ describe('getAvailableVersions', () => {
// Mock core.error to suppress error logs
spyCoreError = jest.spyOn(core, 'error');
spyCoreError.mockImplementation(() => {});
spyCoreWarning = jest.spyOn(core, 'warning');
spyCoreWarning.mockImplementation(() => {});
});

afterEach(() => {
Expand Down Expand Up @@ -93,22 +96,19 @@ describe('getAvailableVersions', () => {
);

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
.mockReturnValueOnce({
statusCode: 200,
headers: {},
headers: {link: `<${nextPageUrl}>; rel="next"`},
result: manifestData as any
})
.mockReturnValueOnce({
statusCode: 200,
headers: {},
result: manifestData as any
})
.mockReturnValueOnce({
statusCode: 200,
headers: {},
result: []
});

const distribution = new TemurinDistribution(
Expand All @@ -123,6 +123,33 @@ describe('getAvailableVersions', () => {
const availableVersions = await distribution['getAvailableVersions']();
expect(availableVersions).not.toBeNull();
expect(availableVersions.length).toBe(manifestData.length * 2);
expect(spyHttpClient).toHaveBeenNthCalledWith(2, nextPageUrl);
});

it('stops pagination after 1000 pages as a safeguard', async () => {
const nextPageUrl = 'https://example.com/releases?page=2';
spyHttpClient.mockReturnValue({
statusCode: 200,
headers: {link: `<${nextPageUrl}>; rel="next"`},
result: [{version_data: {semver: '17.0.1'}, binaries: []}] as any
});

const distribution = new TemurinDistribution(
{
version: '8',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
},
TemurinImplementation.Hotspot
);

await distribution['getAvailableVersions']();

expect(spyHttpClient).toHaveBeenCalledTimes(1000);
expect(spyCoreWarning).toHaveBeenCalledWith(
expect.stringContaining('Reached pagination safeguard limit (1000 pages)')
);
});

it.each([
Expand Down
22 changes: 22 additions & 0 deletions __tests__/util.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as fs from 'fs';
import * as path from 'path';
import {
convertVersionToSemver,
getNextPageUrlFromLinkHeader,
getVersionFromFileContent,
isVersionSatisfies,
isCacheFeatureAvailable,
Expand Down Expand Up @@ -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('.sdkmanrc', () => {
it.each([
Expand Down
18 changes: 17 additions & 1 deletion dist/cleanup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51888,7 +51888,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.renameWinArchive = exports.getGitHubHttpHeaders = exports.convertVersionToSemver = exports.getVersionFromFileContent = exports.isCacheFeatureAvailable = exports.isGhes = exports.isJobStatusSuccess = exports.getToolcachePath = exports.isVersionSatisfies = exports.getDownloadArchiveExtension = exports.extractJdkFile = exports.getVersionFromToolcachePath = exports.getBooleanInput = exports.getTempDir = void 0;
exports.renameWinArchive = exports.getNextPageUrlFromLinkHeader = exports.getGitHubHttpHeaders = exports.convertVersionToSemver = exports.getVersionFromFileContent = exports.isCacheFeatureAvailable = exports.isGhes = exports.isJobStatusSuccess = exports.getToolcachePath = exports.isVersionSatisfies = exports.getDownloadArchiveExtension = exports.extractJdkFile = exports.getVersionFromToolcachePath = exports.getBooleanInput = exports.getTempDir = void 0;
const os_1 = __importDefault(__nccwpck_require__(22037));
const path_1 = __importDefault(__nccwpck_require__(71017));
const fs = __importStar(__nccwpck_require__(57147));
Expand Down Expand Up @@ -52055,6 +52055,22 @@ function getGitHubHttpHeaders() {
return headers;
}
exports.getGitHubHttpHeaders = getGitHubHttpHeaders;
function getNextPageUrlFromLinkHeader(headers) {
var _a, _b;
if (!headers) {
return null;
}
const linkHeader = (_a = headers.link) !== null && _a !== void 0 ? _a : headers.Link;
if (!linkHeader) {
return null;
}
const normalizedLinkHeader = Array.isArray(linkHeader)
? linkHeader.join(',')
: linkHeader;
const nextLinkMatch = normalizedLinkHeader.match(/<([^>]+)>\s*;\s*rel="?next"?/i);
return (_b = nextLinkMatch === null || nextLinkMatch === void 0 ? void 0 : nextLinkMatch[1]) !== null && _b !== void 0 ? _b : null;
}
exports.getNextPageUrlFromLinkHeader = getNextPageUrlFromLinkHeader;
// Rename archive to add extension because after downloading
// archive does not contain extension type and it leads to some issues
// on Windows runners without PowerShell Core.
Expand Down
Loading
Loading