mirror of
https://github.com/actions/setup-java.git
synced 2026-07-30 17:19:27 +08:00
27f2c62824
* Verify JDK downloads with vendor checksums Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d * Handle missing vendor checksum values Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d * Preserve checksum error during cleanup failure Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d * Validate checksum metadata value types Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d * Clarify checksum documentation Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d * Expand vendor checksum verification Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d * Accept SHA-256 or SHA-512 for JetBrains checksum sibling JetBrains publishes a single, generically-named ".checksum" sibling whose digest algorithm isn't disclosed by the filename. Older JBR 11 builds (e.g. jbrsdk_nomod-11_0_16-*-b2043.64.tar.gz) publish a SHA-256 digest there, while newer builds publish SHA-512. The JetBrains installer previously assumed SHA-512 unconditionally, so verification failed with "Malformed sha512 checksum metadata ... expected a 128-character hexadecimal digest" for those older builds, breaking the jetbrains 11 e2e job on macOS and Windows. fetchChecksum now accepts a list of candidate algorithms and infers the actual algorithm from the returned digest's length, preferring the strongest match. The JetBrains installer passes ['sha512', 'sha256']; all other callers are unaffected since they already pass a single, vendor-disclosed algorithm. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d * Use SapMachine archive checksum files Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d
131 lines
3.8 KiB
TypeScript
131 lines
3.8 KiB
TypeScript
import {afterEach, describe, expect, it, jest} from '@jest/globals';
|
|
import {createHash} from 'crypto';
|
|
import fs from 'fs';
|
|
import os from 'os';
|
|
import path from 'path';
|
|
|
|
import {calculateChecksum, verifyChecksum} from '../src/checksum.js';
|
|
import type {ChecksumMetadata} from '../src/distributions/base-models.js';
|
|
|
|
const temporaryPaths: string[] = [];
|
|
|
|
async function temporaryFile(contents: string): Promise<string> {
|
|
const directory = await fs.promises.mkdtemp(
|
|
path.join(os.tmpdir(), 'setup-java-checksum-')
|
|
);
|
|
const file = path.join(directory, 'archive');
|
|
await fs.promises.writeFile(file, contents);
|
|
temporaryPaths.push(directory);
|
|
return file;
|
|
}
|
|
|
|
afterEach(async () => {
|
|
await Promise.all(
|
|
temporaryPaths
|
|
.splice(0)
|
|
.map(item => fs.promises.rm(item, {recursive: true, force: true}))
|
|
);
|
|
jest.restoreAllMocks();
|
|
});
|
|
|
|
describe('verifyChecksum', () => {
|
|
it.each(['sha256', 'sha512'] as const)(
|
|
'verifies a matching %s digest',
|
|
async algorithm => {
|
|
const contents = `jdk archive for ${algorithm}`;
|
|
const file = await temporaryFile(contents);
|
|
const value = createHash(algorithm).update(contents).digest('hex');
|
|
|
|
await expect(
|
|
verifyChecksum(
|
|
file,
|
|
{algorithm, value: value.toUpperCase()},
|
|
{distribution: 'Test', version: '21.0.1'}
|
|
)
|
|
).resolves.toBeUndefined();
|
|
}
|
|
);
|
|
|
|
it('reports mismatch context and both digests', async () => {
|
|
const file = await temporaryFile('corrupt archive');
|
|
const expected = 'a'.repeat(64);
|
|
const actual = await calculateChecksum(file, 'sha256');
|
|
|
|
await expect(
|
|
verifyChecksum(
|
|
file,
|
|
{algorithm: 'sha256', value: expected},
|
|
{distribution: 'Corretto', version: '21.0.8'}
|
|
)
|
|
).rejects.toThrow(
|
|
`Checksum verification failed for Corretto version 21.0.8: sha256 expected ${expected}, actual ${actual}.`
|
|
);
|
|
});
|
|
|
|
it('rejects malformed digest metadata before reading the file', async () => {
|
|
await expect(
|
|
verifyChecksum(
|
|
'/missing/archive',
|
|
{algorithm: 'sha512', value: 'not-a-digest'},
|
|
{distribution: 'Test', version: '17'}
|
|
)
|
|
).rejects.toThrow(
|
|
'Malformed sha512 checksum metadata: expected a 128-character hexadecimal digest.'
|
|
);
|
|
});
|
|
|
|
it.each([undefined, null, 123])(
|
|
'reports a malformed digest when the value is %p',
|
|
async value => {
|
|
const checksum = {
|
|
algorithm: 'sha256',
|
|
value
|
|
} as unknown as ChecksumMetadata;
|
|
|
|
await expect(
|
|
verifyChecksum('/missing/archive', checksum, {
|
|
distribution: 'Test',
|
|
version: '17'
|
|
})
|
|
).rejects.toThrow(
|
|
'Malformed sha256 checksum metadata: expected a 64-character hexadecimal digest.'
|
|
);
|
|
}
|
|
);
|
|
|
|
it('rejects unsupported algorithms without leaking source query parameters', async () => {
|
|
const checksum = {
|
|
algorithm: 'md5',
|
|
value: 'a'.repeat(32),
|
|
source: 'https://vendor.example/checksum.txt?token=secret-value#private'
|
|
} as unknown as ChecksumMetadata;
|
|
|
|
let message = '';
|
|
try {
|
|
await verifyChecksum('/missing/archive', checksum, {
|
|
distribution: 'Test',
|
|
version: '17'
|
|
});
|
|
} catch (error) {
|
|
message = (error as Error).message;
|
|
}
|
|
|
|
expect(message).toContain(
|
|
"Unsupported checksum algorithm 'md5' from https://vendor.example/checksum.txt"
|
|
);
|
|
expect(message).not.toContain('secret-value');
|
|
expect(message).not.toContain('token=');
|
|
expect(message).not.toContain('#private');
|
|
});
|
|
|
|
it('surfaces file read errors', async () => {
|
|
await expect(
|
|
verifyChecksum(
|
|
'/missing/archive',
|
|
{algorithm: 'sha256', value: 'a'.repeat(64)},
|
|
{distribution: 'Test', version: '17'}
|
|
)
|
|
).rejects.toMatchObject({code: 'ENOENT'});
|
|
});
|
|
});
|