mirror of
https://github.com/gradle/actions
synced 2024-11-27 11:52:24 +00:00
Only fetch checksums for unknown wrapper versions (#292)
The checksum values for most wrapper versions are hard-coded into the action. These known checksum values are first used for validation: only if none of the known values work do we download checksums. Previously, we blindly downloaded all of the checksum values in this case: we now only download the checksums for versions that are not in our "known" set. Fixes #171
This commit is contained in:
parent
01254b3eaa
commit
dff3ef9b8d
4 changed files with 37 additions and 22 deletions
|
@ -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<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
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,9 +32,12 @@ function getKnownValidChecksums(): Map<string, Set<string>> {
|
|||
*
|
||||
* 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')
|
||||
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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([], [])
|
||||
|
@ -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)) {
|
||||
|
|
|
@ -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()
|
||||
})
|
||||
|
|
|
@ -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<string, Set<string>>()
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue