diff --git a/sources/src/wrapper-validation/checksums.ts b/sources/src/wrapper-validation/checksums.ts index 4220b0c2..a1835cb1 100644 --- a/sources/src/wrapper-validation/checksums.ts +++ b/sources/src/wrapper-validation/checksums.ts @@ -4,21 +4,27 @@ import fileWrapperChecksums from './wrapper-checksums.json' const httpc = new httpm.HttpClient('gradle/wrapper-validation-action', undefined, {allowRetries: true, maxRetries: 3}) -function getKnownValidChecksums(): Map> { - const versionsMap = new Map>() - for (const entry of fileWrapperChecksums) { - const checksum = entry.checksum +export class WrapperChecksums { + checksums = new Map>() + versions = new Set() - let versionNames = versionsMap.get(checksum) - if (versionNames === undefined) { - versionNames = new Set() - versionsMap.set(checksum, versionNames) + add(version: string, checksum: string): void { + if (this.checksums.has(checksum)) { + this.checksums.get(checksum)!.add(version) + } else { + this.checksums.set(checksum, new Set([version])) } - versionNames.add(entry.version) + this.versions.add(version) } +} - return versionsMap +function loadKnownChecksums(): WrapperChecksums { + const checksums = new WrapperChecksums() + for (const entry of fileWrapperChecksums) { + checksums.add(entry.version, entry.checksum) + } + return checksums } /** @@ -26,9 +32,12 @@ function getKnownValidChecksums(): Map> { * * Maps from the checksum to the names of the Gradle versions whose wrapper has this checksum. */ -export const KNOWN_VALID_CHECKSUMS = getKnownValidChecksums() +export const KNOWN_CHECKSUMS = loadKnownChecksums() -export async function fetchValidChecksums(allowSnapshots: boolean): Promise> { +export async function fetchUnknownChecksums( + allowSnapshots: boolean, + knownChecksums: WrapperChecksums +): Promise> { const all = await httpGetJsonArray('https://services.gradle.org/versions/all') const withChecksum = all.filter( entry => typeof entry === 'object' && entry != null && entry.hasOwnProperty('wrapperChecksumUrl') @@ -37,7 +46,11 @@ export async function fetchValidChecksums(allowSnapshots: boolean): Promise allowSnapshots || !entry.snapshot ) - const checksumUrls = allowed.map( + const notKnown = allowed.filter( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (entry: any) => !knownChecksums.versions.has(entry.version) + ) + const checksumUrls = notKnown.map( // eslint-disable-next-line @typescript-eslint/no-explicit-any (entry: any) => entry.wrapperChecksumUrl as string ) diff --git a/sources/src/wrapper-validation/validate.ts b/sources/src/wrapper-validation/validate.ts index add8e83d..13be7f65 100644 --- a/sources/src/wrapper-validation/validate.ts +++ b/sources/src/wrapper-validation/validate.ts @@ -8,7 +8,7 @@ export async function findInvalidWrapperJars( minWrapperCount: number, allowSnapshots: boolean, allowedChecksums: string[], - knownValidChecksums: Map> = checksums.KNOWN_VALID_CHECKSUMS + knownValidChecksums: checksums.WrapperChecksums = checksums.KNOWN_CHECKSUMS ): Promise { const wrapperJars = await find.findWrapperJars(gitRepoRoot) const result = new ValidationResult([], []) @@ -21,7 +21,7 @@ export async function findInvalidWrapperJars( const notYetValidatedWrappers = [] for (const wrapperJar of wrapperJars) { const sha = await hash.sha256File(resolve(gitRepoRoot, wrapperJar)) - if (allowedChecksums.includes(sha) || knownValidChecksums.has(sha)) { + if (allowedChecksums.includes(sha) || knownValidChecksums.checksums.has(sha)) { result.valid.push(new WrapperJar(wrapperJar, sha)) } else { notYetValidatedWrappers.push(new WrapperJar(wrapperJar, sha)) @@ -31,7 +31,7 @@ export async function findInvalidWrapperJars( // Otherwise fall back to fetching checksums from Gradle API and compare against them if (notYetValidatedWrappers.length > 0) { result.fetchedChecksums = true - const fetchedValidChecksums = await checksums.fetchValidChecksums(allowSnapshots) + const fetchedValidChecksums = await checksums.fetchUnknownChecksums(allowSnapshots, knownValidChecksums) for (const wrapperJar of notYetValidatedWrappers) { if (!fetchedValidChecksums.has(wrapperJar.checksum)) { diff --git a/sources/test/jest/wrapper-validation/checksums.test.ts b/sources/test/jest/wrapper-validation/checksums.test.ts index ce5f750e..91794c59 100644 --- a/sources/test/jest/wrapper-validation/checksums.test.ts +++ b/sources/test/jest/wrapper-validation/checksums.test.ts @@ -6,22 +6,22 @@ jest.setTimeout(30000) test('has loaded hardcoded wrapper jars checksums', async () => { // Sanity check that generated checksums file is not empty and was properly imported - expect(checksums.KNOWN_VALID_CHECKSUMS.size).toBeGreaterThan(10) + expect(checksums.KNOWN_CHECKSUMS.checksums.size).toBeGreaterThan(10) // Verify that checksums of arbitrary versions are contained expect( - checksums.KNOWN_VALID_CHECKSUMS.get( + checksums.KNOWN_CHECKSUMS.checksums.get( '660ab018b8e319e9ae779fdb1b7ac47d0321bde953bf0eb4545f14952cfdcaa3' ) ).toEqual(new Set(['4.10.3'])) expect( - checksums.KNOWN_VALID_CHECKSUMS.get( + checksums.KNOWN_CHECKSUMS.checksums.get( '28b330c20a9a73881dfe9702df78d4d78bf72368e8906c70080ab6932462fe9e' ) ).toEqual(new Set(['6.0-rc-1', '6.0-rc-2', '6.0-rc-3', '6.0', '6.0.1'])) }) test('fetches wrapper jars checksums', async () => { - const validChecksums = await checksums.fetchValidChecksums(false) + const validChecksums = await checksums.fetchUnknownChecksums(false, new checksums.WrapperChecksums) expect(validChecksums.size).toBeGreaterThan(10) // Verify that checksum of arbitrary version is contained expect( @@ -47,7 +47,7 @@ describe('retry', () => { code: 'ECONNREFUSED' }) - const validChecksums = await checksums.fetchValidChecksums(false) + const validChecksums = await checksums.fetchUnknownChecksums(false, new checksums.WrapperChecksums) expect(validChecksums.size).toBeGreaterThan(10) nock.isDone() }) diff --git a/sources/test/jest/wrapper-validation/validate.test.ts b/sources/test/jest/wrapper-validation/validate.test.ts index 5aacd101..42c0d87b 100644 --- a/sources/test/jest/wrapper-validation/validate.test.ts +++ b/sources/test/jest/wrapper-validation/validate.test.ts @@ -1,6 +1,7 @@ import * as path from 'path' import * as validate from '../../../src/wrapper-validation/validate' import {expect, test, jest} from '@jest/globals' +import { WrapperChecksums } from '../../../src/wrapper-validation/checksums' jest.setTimeout(30000) @@ -24,7 +25,7 @@ test('succeeds if all found wrapper jars are valid', async () => { }) test('succeeds if all found wrapper jars are valid (and checksums are fetched from Gradle API)', async () => { - const knownValidChecksums = new Map>() + const knownValidChecksums = new WrapperChecksums() const result = await validate.findInvalidWrapperJars( baseDir, 1, @@ -32,6 +33,7 @@ test('succeeds if all found wrapper jars are valid (and checksums are fetched fr ['e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'], knownValidChecksums ) + console.log(`fetchedChecksums = ${result.fetchedChecksums}`) expect(result.isValid()).toBe(true) // Should have fetched checksums because no known checksums were provided