Skip to content

Commit 0756542

Browse files
Refactor error handling and improve test logging for installers (#989)
* Refactor error handling for version not found cases across multiple installers * Mock core.error in tests to suppress error logs * fix(graalvm): improve error messages for EA version not found scenarios * refactor(tests): update error messages for version not found scenarios * fix(graalvm): enhance error messages for version not found scenarios * fix(graalvm): improve error messages for version not found scenarios with updated download URL * fix(graalvm): improve error handling for EA version not found scenarios with clearer messages
1 parent 1d018f9 commit 0756542

34 files changed

+414
-176
lines changed

__tests__/cache.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ describe('dependency cache', () => {
1717
let spyWarning: jest.SpyInstance<void, Parameters<typeof core.warning>>;
1818
let spyDebug: jest.SpyInstance<void, Parameters<typeof core.debug>>;
1919
let spySaveState: jest.SpyInstance<void, Parameters<typeof core.saveState>>;
20+
let spyCoreError: jest.SpyInstance;
2021

2122
beforeEach(() => {
2223
workspace = mkdtempSync(join(tmpdir(), 'setup-java-cache-'));
@@ -51,13 +52,21 @@ describe('dependency cache', () => {
5152

5253
spySaveState = jest.spyOn(core, 'saveState');
5354
spySaveState.mockImplementation(() => null);
55+
56+
// Mock core.error to suppress error logs
57+
spyCoreError = jest.spyOn(core, 'error');
58+
spyCoreError.mockImplementation(() => {});
5459
});
5560

5661
afterEach(() => {
5762
process.chdir(ORIGINAL_CWD);
5863
process.env['GITHUB_WORKSPACE'] = ORIGINAL_GITHUB_WORKSPACE;
5964
process.env['RUNNER_OS'] = ORIGINAL_RUNNER_OS;
6065
resetState();
66+
67+
jest.resetAllMocks();
68+
jest.clearAllMocks();
69+
jest.restoreAllMocks();
6170
});
6271

6372
describe('restore', () => {

__tests__/cleanup-java.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,32 @@ describe('cleanup', () => {
1111
Parameters<typeof cache.saveCache>
1212
>;
1313
let spyJobStatusSuccess: jest.SpyInstance;
14+
let spyCoreError: jest.SpyInstance;
1415

1516
beforeEach(() => {
1617
spyWarning = jest.spyOn(core, 'warning');
1718
spyWarning.mockImplementation(() => null);
19+
1820
spyInfo = jest.spyOn(core, 'info');
1921
spyInfo.mockImplementation(() => null);
22+
2023
spyCacheSave = jest.spyOn(cache, 'saveCache');
24+
2125
spyJobStatusSuccess = jest.spyOn(util, 'isJobStatusSuccess');
2226
spyJobStatusSuccess.mockReturnValue(true);
27+
28+
// Mock core.error to suppress error logs
29+
spyCoreError = jest.spyOn(core, 'error');
30+
spyCoreError.mockImplementation(() => {});
31+
2332
createStateForSuccessfulRestore();
2433
});
34+
2535
afterEach(() => {
2636
resetState();
37+
jest.resetAllMocks();
38+
jest.clearAllMocks();
39+
jest.restoreAllMocks();
2740
});
2841

2942
it('does not fail nor warn even when the save process throws a ReserveCacheError', async () => {

__tests__/distributors/adopt-installer.test.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ import {JavaInstallerOptions} from '../../src/distributions/base-models';
99
import os from 'os';
1010

1111
import manifestData from '../data/adopt.json';
12+
import * as core from '@actions/core';
1213

1314
describe('getAvailableVersions', () => {
1415
let spyHttpClient: jest.SpyInstance;
16+
let spyCoreError: jest.SpyInstance;
1517

1618
beforeEach(() => {
1719
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
@@ -20,6 +22,10 @@ describe('getAvailableVersions', () => {
2022
headers: {},
2123
result: []
2224
});
25+
26+
// Mock core.error to suppress error logs
27+
spyCoreError = jest.spyOn(core, 'error');
28+
spyCoreError.mockImplementation(() => {});
2329
});
2430

2531
afterEach(() => {
@@ -262,7 +268,7 @@ describe('findPackageForDownload', () => {
262268
distribution['getAvailableVersions'] = async () => manifestData as any;
263269
await expect(
264270
distribution['findPackageForDownload']('9.0.8')
265-
).rejects.toThrow(/Could not find satisfied version for SemVer */);
271+
).rejects.toThrow(/No matching version found for SemVer */);
266272
});
267273

268274
it('version is not found', async () => {
@@ -277,7 +283,7 @@ describe('findPackageForDownload', () => {
277283
);
278284
distribution['getAvailableVersions'] = async () => manifestData as any;
279285
await expect(distribution['findPackageForDownload']('7.x')).rejects.toThrow(
280-
/Could not find satisfied version for SemVer */
286+
/No matching version found for SemVer */
281287
);
282288
});
283289

@@ -293,7 +299,7 @@ describe('findPackageForDownload', () => {
293299
);
294300
distribution['getAvailableVersions'] = async () => [];
295301
await expect(distribution['findPackageForDownload']('11')).rejects.toThrow(
296-
/Could not find satisfied version for SemVer */
302+
/No matching version found for SemVer */
297303
);
298304
});
299305
});

__tests__/distributors/base-installer.test.ts

Lines changed: 107 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class EmptyJavaBase extends JavaBase {
3838
): Promise<JavaDownloadRelease> {
3939
const availableVersion = '11.0.9';
4040
if (!semver.satisfies(availableVersion, range)) {
41-
throw new Error('Available version not found');
41+
throw this.createVersionNotFoundError(range, [availableVersion]);
4242
}
4343

4444
return {
@@ -248,6 +248,7 @@ describe('setupJava', () => {
248248
let spyCoreExportVariable: jest.SpyInstance;
249249
let spyCoreAddPath: jest.SpyInstance;
250250
let spyCoreSetOutput: jest.SpyInstance;
251+
let spyCoreError: jest.SpyInstance;
251252

252253
beforeEach(() => {
253254
spyGetToolcachePath = jest.spyOn(util, 'getToolcachePath');
@@ -287,6 +288,10 @@ describe('setupJava', () => {
287288
spyCoreSetOutput = jest.spyOn(core, 'setOutput');
288289
spyCoreSetOutput.mockImplementation(() => undefined);
289290

291+
// Mock core.error to suppress error logs
292+
spyCoreError = jest.spyOn(core, 'error');
293+
spyCoreError.mockImplementation(() => undefined);
294+
290295
jest.spyOn(os, 'arch').mockReturnValue('x86' as ReturnType<typeof os.arch>);
291296
});
292297

@@ -530,19 +535,16 @@ describe('setupJava', () => {
530535
checkLatest: false
531536
}
532537
]
533-
])(
534-
'should throw an error for Available version not found for %s',
535-
async input => {
536-
mockJavaBase = new EmptyJavaBase(input);
537-
await expect(mockJavaBase.setupJava()).rejects.toThrow(
538-
'Available version not found'
539-
);
540-
expect(spyTcFindAllVersions).toHaveBeenCalled();
541-
expect(spyCoreAddPath).not.toHaveBeenCalled();
542-
expect(spyCoreExportVariable).not.toHaveBeenCalled();
543-
expect(spyCoreSetOutput).not.toHaveBeenCalled();
544-
}
545-
);
538+
])('should throw an error for version not found for %s', async input => {
539+
mockJavaBase = new EmptyJavaBase(input);
540+
await expect(mockJavaBase.setupJava()).rejects.toThrow(
541+
`No matching version found for SemVer '${input.version}'`
542+
);
543+
expect(spyTcFindAllVersions).toHaveBeenCalled();
544+
expect(spyCoreAddPath).not.toHaveBeenCalled();
545+
expect(spyCoreExportVariable).not.toHaveBeenCalled();
546+
expect(spyCoreSetOutput).not.toHaveBeenCalled();
547+
});
546548
});
547549

548550
describe('normalizeVersion', () => {
@@ -570,6 +572,97 @@ describe('normalizeVersion', () => {
570572
});
571573
});
572574

575+
describe('createVersionNotFoundError', () => {
576+
it('should include all required fields in error message without available versions', () => {
577+
const mockJavaBase = new EmptyJavaBase({
578+
version: '17.0.5',
579+
architecture: 'x64',
580+
packageType: 'jdk',
581+
checkLatest: false
582+
});
583+
584+
const error = (mockJavaBase as any).createVersionNotFoundError('17.0.5');
585+
586+
expect(error.message).toContain(
587+
"No matching version found for SemVer '17.0.5'"
588+
);
589+
expect(error.message).toContain('Distribution: Empty');
590+
expect(error.message).toContain('Package type: jdk');
591+
expect(error.message).toContain('Architecture: x64');
592+
});
593+
594+
it('should include available versions when provided', () => {
595+
const mockJavaBase = new EmptyJavaBase({
596+
version: '17.0.5',
597+
architecture: 'x64',
598+
packageType: 'jdk',
599+
checkLatest: false
600+
});
601+
602+
const availableVersions = ['11.0.1', '11.0.2', '17.0.1', '17.0.2'];
603+
const error = (mockJavaBase as any).createVersionNotFoundError(
604+
'17.0.5',
605+
availableVersions
606+
);
607+
608+
expect(error.message).toContain(
609+
"No matching version found for SemVer '17.0.5'"
610+
);
611+
expect(error.message).toContain('Distribution: Empty');
612+
expect(error.message).toContain('Package type: jdk');
613+
expect(error.message).toContain('Architecture: x64');
614+
expect(error.message).toContain(
615+
'Available versions: 11.0.1, 11.0.2, 17.0.1, 17.0.2'
616+
);
617+
});
618+
619+
it('should truncate available versions when there are many', () => {
620+
const mockJavaBase = new EmptyJavaBase({
621+
version: '17.0.5',
622+
architecture: 'x64',
623+
packageType: 'jdk',
624+
checkLatest: false
625+
});
626+
627+
// Create 60 versions to test truncation
628+
const availableVersions = Array.from({length: 60}, (_, i) => `11.0.${i}`);
629+
const error = (mockJavaBase as any).createVersionNotFoundError(
630+
'17.0.5',
631+
availableVersions
632+
);
633+
634+
expect(error.message).toContain('Available versions:');
635+
expect(error.message).toContain('...');
636+
expect(error.message).toContain('(showing first 50 of 60 versions');
637+
});
638+
639+
it('should include additional context when provided', () => {
640+
const mockJavaBase = new EmptyJavaBase({
641+
version: '17.0.5',
642+
architecture: 'x64',
643+
packageType: 'jdk',
644+
checkLatest: false
645+
});
646+
647+
const availableVersions = ['11.0.1', '11.0.2'];
648+
const additionalContext = 'Platform: linux';
649+
const error = (mockJavaBase as any).createVersionNotFoundError(
650+
'17.0.5',
651+
availableVersions,
652+
additionalContext
653+
);
654+
655+
expect(error.message).toContain(
656+
"No matching version found for SemVer '17.0.5'"
657+
);
658+
expect(error.message).toContain('Distribution: Empty');
659+
expect(error.message).toContain('Package type: jdk');
660+
expect(error.message).toContain('Architecture: x64');
661+
expect(error.message).toContain('Platform: linux');
662+
expect(error.message).toContain('Available versions: 11.0.1, 11.0.2');
663+
});
664+
});
665+
573666
describe('getToolcacheVersionName', () => {
574667
const DummyJavaBase = JavaBase as any;
575668

__tests__/distributors/corretto-installer.test.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ import {JavaInstallerOptions} from '../../src/distributions/base-models';
44
import {CorrettoDistribution} from '../../src/distributions/corretto/installer';
55
import * as util from '../../src/util';
66
import os from 'os';
7-
import {isGeneratorFunction} from 'util/types';
7+
import * as core from '@actions/core';
88

99
import manifestData from '../data/corretto.json';
1010

1111
describe('getAvailableVersions', () => {
1212
let spyHttpClient: jest.SpyInstance;
1313
let spyGetDownloadArchiveExtension: jest.SpyInstance;
14+
let spyCoreError: jest.SpyInstance;
1415

1516
beforeEach(() => {
1617
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
@@ -23,6 +24,10 @@ describe('getAvailableVersions', () => {
2324
util,
2425
'getDownloadArchiveExtension'
2526
);
27+
28+
// Mock core.error to suppress error logs
29+
spyCoreError = jest.spyOn(core, 'error');
30+
spyCoreError.mockImplementation(() => {});
2631
});
2732

2833
afterEach(() => {
@@ -198,7 +203,7 @@ describe('getAvailableVersions', () => {
198203

199204
await expect(
200205
distribution['findPackageForDownload'](version)
201-
).rejects.toThrow("Could not find satisfied version for SemVer '4'");
206+
).rejects.toThrow("No matching version found for SemVer '4'");
202207
});
203208

204209
it.each([

__tests__/distributors/dragonwell-installer.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import {HttpClient} from '@actions/http-client';
22
import {DragonwellDistribution} from '../../src/distributions/dragonwell/installer';
33
import * as utils from '../../src/util';
4+
import * as core from '@actions/core';
45

56
import manifestData from '../data/dragonwell.json';
67

78
describe('getAvailableVersions', () => {
89
let spyHttpClient: jest.SpyInstance;
910
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
11+
let spyCoreError: jest.SpyInstance;
1012

1113
beforeEach(() => {
1214
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
@@ -21,6 +23,10 @@ describe('getAvailableVersions', () => {
2123
'getDownloadArchiveExtension'
2224
);
2325
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');
26+
27+
// Mock core.error to suppress error logs
28+
spyCoreError = jest.spyOn(core, 'error');
29+
spyCoreError.mockImplementation(() => {});
2430
});
2531

2632
afterEach(() => {
@@ -232,7 +238,7 @@ describe('getAvailableVersions', () => {
232238
await expect(
233239
distribution['findPackageForDownload'](jdkVersion)
234240
).rejects.toThrow(
235-
`Couldn't find any satisfied version for the specified java-version: "${jdkVersion}" and architecture: "${arch}".`
241+
`No matching version found for SemVer '${jdkVersion}'`
236242
);
237243
}
238244
);

0 commit comments

Comments
 (0)