Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only fetch checksums for unknown wrapper versions #292

Merged
merged 2 commits into from
Jul 16, 2024
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: 26 additions & 13 deletions sources/src/wrapper-validation/checksums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,40 @@ import fileWrapperChecksums from './wrapper-checksums.json'

const httpc = new httpm.HttpClient('gradle/wrapper-validation-action', undefined, {allowRetries: true, maxRetries: 3})

function getKnownValidChecksums(): Map<string, Set<string>> {
const versionsMap = new Map<string, Set<string>>()
for (const entry of fileWrapperChecksums) {
const checksum = entry.checksum
export class WrapperChecksums {
checksums = new Map<string, Set<string>>()
versions = new Set<string>()

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
}

/**
* Known checksums from previously published Wrapper versions.
*
* 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<Set<string>> {
export async function fetchUnknownChecksums(
allowSnapshots: boolean,
knownChecksums: WrapperChecksums
): Promise<Set<string>> {
const all = await httpGetJsonArray('https://services.gradle.org/versions/all')
const withChecksum = all.filter(
entry => typeof entry === 'object' && entry != null && entry.hasOwnProperty('wrapperChecksumUrl')
Expand All @@ -37,7 +46,11 @@ export async function fetchValidChecksums(allowSnapshots: boolean): Promise<Set<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(entry: any) => 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
)
Expand Down
6 changes: 3 additions & 3 deletions sources/src/wrapper-validation/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export async function findInvalidWrapperJars(
minWrapperCount: number,
allowSnapshots: boolean,
allowedChecksums: string[],
knownValidChecksums: Map<string, Set<string>> = checksums.KNOWN_VALID_CHECKSUMS
knownValidChecksums: checksums.WrapperChecksums = checksums.KNOWN_CHECKSUMS
): Promise<ValidationResult> {
const wrapperJars = await find.findWrapperJars(gitRepoRoot)
const result = new ValidationResult([], [])
Expand All @@ -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))
Expand All @@ -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)) {
Expand Down
10 changes: 5 additions & 5 deletions sources/test/jest/wrapper-validation/checksums.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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()
})
Expand Down
4 changes: 3 additions & 1 deletion sources/test/jest/wrapper-validation/validate.test.ts
Original file line number Diff line number Diff line change
@@ -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)

Expand All @@ -24,14 +25,15 @@ 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<string, Set<string>>()
const knownValidChecksums = new WrapperChecksums()
const result = await validate.findInvalidWrapperJars(
baseDir,
1,
false,
['e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'],
knownValidChecksums
)
console.log(`fetchedChecksums = ${result.fetchedChecksums}`)

expect(result.isValid()).toBe(true)
// Should have fetched checksums because no known checksums were provided
Expand Down
Loading