diff --git a/.gitignore b/.gitignore index 0a04613..c5546c9 100644 --- a/.gitignore +++ b/.gitignore @@ -99,3 +99,5 @@ __tests__/runner/* lib/**/* .idea +*.iml + diff --git a/__tests__/validate.test.ts b/__tests__/validate.test.ts index a0f210e..e3df5ee 100644 --- a/__tests__/validate.test.ts +++ b/__tests__/validate.test.ts @@ -1,26 +1,71 @@ import * as path from 'path' import * as validate from '../src/validate' -test('validates wrapper jars', async () => { - const invalidWrapperJars = await validate.findInvalidWrapperJars( - path.resolve('.'), - 3, - false, - [] +const baseDir = path.resolve('.') + +test('succeeds if all found wrapper jars are valid', async () => { + const result = await validate.findInvalidWrapperJars(baseDir, 3, false, [ + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' + ]) + + expect(result.isValid()).toBe(true) + + expect(result.toDisplayString()).toBe( + '✓ Found known Gradle Wrapper JAR files:\n' + + ' e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 __tests__/data/invalid/gradle-wrapper.jar\n' + + ' e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 __tests__/data/invalid/gradlе-wrapper.jar\n' + // homoglyph + ' 3888c76faa032ea8394b8a54e04ce2227ab1f4be64f65d450f8509fe112d38ce __tests__/data/valid/gradle-wrapper.jar' ) - expect(invalidWrapperJars.length).toBe(2) - expect(invalidWrapperJars[0]).toEqual( - new validate.InvalidWrapperJar( +}) + +test('fails if invalid wrapper jars are found', async () => { + const result = await validate.findInvalidWrapperJars(baseDir, 3, false, []) + + expect(result.isValid()).toBe(false) + + expect(result.valid).toEqual([ + new validate.WrapperJar( + '__tests__/data/valid/gradle-wrapper.jar', + '3888c76faa032ea8394b8a54e04ce2227ab1f4be64f65d450f8509fe112d38ce' + ) + ]) + + expect(result.invalid).toEqual([ + new validate.WrapperJar( '__tests__/data/invalid/gradle-wrapper.jar', 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' + ), + new validate.WrapperJar( + '__tests__/data/invalid/gradlе-wrapper.jar', // homoglyph + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' ) + ]) + + expect(result.toDisplayString()).toBe( + '✗ Found unknown Gradle Wrapper JAR files:\n' + + ' e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 __tests__/data/invalid/gradle-wrapper.jar\n' + + ' e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 __tests__/data/invalid/gradlе-wrapper.jar\n' + // homoglyph + '✓ Found known Gradle Wrapper JAR files:\n' + + ' 3888c76faa032ea8394b8a54e04ce2227ab1f4be64f65d450f8509fe112d38ce __tests__/data/valid/gradle-wrapper.jar' ) }) test('fails if not enough wrapper jars are found', async () => { - await expect( - validate.findInvalidWrapperJars(path.resolve('.'), 4, false, []) - ).rejects.toThrowError( + const result = await validate.findInvalidWrapperJars(baseDir, 4, false, []) + + expect(result.isValid()).toBe(false) + + expect(result.errors).toEqual([ 'Expected to find at least 4 Gradle Wrapper JARs but got only 3' + ]) + + expect(result.toDisplayString()).toBe( + '✗ Found unknown Gradle Wrapper JAR files:\n' + + ' e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 __tests__/data/invalid/gradle-wrapper.jar\n' + + ' e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 __tests__/data/invalid/gradlе-wrapper.jar\n' + // homoglyph + '✗ Other validation errors:\n' + + ' Expected to find at least 4 Gradle Wrapper JARs but got only 3\n' + + '✓ Found known Gradle Wrapper JAR files:\n' + + ' 3888c76faa032ea8394b8a54e04ce2227ab1f4be64f65d450f8509fe112d38ce __tests__/data/valid/gradle-wrapper.jar' ) }) diff --git a/dist/index.js b/dist/index.js index 3b70a1e..ed7ff4b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -340,13 +340,12 @@ const validate = __importStar(__webpack_require__(474)); function run() { return __awaiter(this, void 0, void 0, function* () { try { - const minWrapperCount = +core.getInput('min-wrapper-count'); - const allowSnapshots = core.getInput('allow-snapshots') === 'true'; - const allowChecksums = core.getInput('allow-checksums').split(','); - const invalidWrapperJars = yield validate.findInvalidWrapperJars(path.resolve('.'), minWrapperCount, allowSnapshots, allowChecksums); - if (invalidWrapperJars.length > 0) { - const list = invalidWrapperJars.map(invalid => `${invalid.checksum} ${invalid.path}`); - core.setFailed(`Found unknown Gradle Wrapper JAR files\n${list.join('\n- ')}`); + const result = yield validate.findInvalidWrapperJars(path.resolve('.'), +core.getInput('min-wrapper-count'), core.getInput('allow-snapshots') === 'true', core.getInput('allow-checksums').split(',')); + if (result.isValid()) { + core.info(result.toDisplayString()); + } + else { + core.setFailed(result.toDisplayString()); } } catch (error) { @@ -976,32 +975,68 @@ const hash = __importStar(__webpack_require__(652)); function findInvalidWrapperJars(gitRepoRoot, minWrapperCount, allowSnapshots, allowChecksums) { return __awaiter(this, void 0, void 0, function* () { const wrapperJars = yield find.findWrapperJars(gitRepoRoot); + const result = new ValidationResult([], []); if (wrapperJars.length < minWrapperCount) { - throw new Error(`Expected to find at least ${minWrapperCount} Gradle Wrapper JARs but got only ${wrapperJars.length}`); + result.errors.push(`Expected to find at least ${minWrapperCount} Gradle Wrapper JARs but got only ${wrapperJars.length}`); } if (wrapperJars.length > 0) { const validChecksums = yield checksums.fetchValidChecksums(allowSnapshots); validChecksums.push(...allowChecksums); - const invalidWrapperJars = []; for (const wrapperJar of wrapperJars) { const sha = yield hash.sha256File(wrapperJar); if (!validChecksums.includes(sha)) { - invalidWrapperJars.push(new InvalidWrapperJar(wrapperJar, sha)); + result.invalid.push(new WrapperJar(wrapperJar, sha)); + } + else { + result.valid.push(new WrapperJar(wrapperJar, sha)); } } - return invalidWrapperJars; } - return []; + return result; }); } exports.findInvalidWrapperJars = findInvalidWrapperJars; -class InvalidWrapperJar { +class ValidationResult { + constructor(valid, invalid) { + this.errors = []; + this.valid = valid; + this.invalid = invalid; + } + isValid() { + return this.invalid.length === 0 && this.errors.length === 0; + } + toDisplayString() { + let displayString = ''; + if (this.invalid.length > 0) { + displayString += `✗ Found unknown Gradle Wrapper JAR files:\n${ValidationResult.toDisplayList(this.invalid)}`; + } + if (this.errors.length > 0) { + if (displayString.length > 0) + displayString += '\n'; + displayString += `✗ Other validation errors:\n ${this.errors.join(`\n `)}`; + } + if (this.valid.length > 0) { + if (displayString.length > 0) + displayString += '\n'; + displayString += `✓ Found known Gradle Wrapper JAR files:\n${ValidationResult.toDisplayList(this.valid)}`; + } + return displayString; + } + static toDisplayList(wrapperJars) { + return ` ${wrapperJars.map(wj => wj.toDisplayString()).join(`\n `)}`; + } +} +exports.ValidationResult = ValidationResult; +class WrapperJar { constructor(path, checksum) { this.path = path; this.checksum = checksum; } + toDisplayString() { + return `${this.checksum} ${this.path}`; + } } -exports.InvalidWrapperJar = InvalidWrapperJar; +exports.WrapperJar = WrapperJar; /***/ }), @@ -1069,7 +1104,8 @@ function findWrapperJars(baseDir) { const files = yield recursivelyListFiles(baseDir); return files .filter(file => unhomoglyph_1.default(file).endsWith('gradle-wrapper.jar')) - .map(wrapperJar => path.relative(baseDir, wrapperJar)); + .map(wrapperJar => path.relative(baseDir, wrapperJar)) + .sort((a, b) => a.localeCompare(b)); }); } exports.findWrapperJars = findWrapperJars; diff --git a/src/find.ts b/src/find.ts index d71a4d1..66f14b9 100644 --- a/src/find.ts +++ b/src/find.ts @@ -10,6 +10,7 @@ export async function findWrapperJars(baseDir: string): Promise { return files .filter(file => unhomoglyph(file).endsWith('gradle-wrapper.jar')) .map(wrapperJar => path.relative(baseDir, wrapperJar)) + .sort((a, b) => a.localeCompare(b)) } async function recursivelyListFiles(baseDir: string): Promise { diff --git a/src/main.ts b/src/main.ts index 76a6299..653dba0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,22 +5,16 @@ import * as validate from './validate' export async function run(): Promise { try { - const minWrapperCount = +core.getInput('min-wrapper-count') - const allowSnapshots = core.getInput('allow-snapshots') === 'true' - const allowChecksums = core.getInput('allow-checksums').split(',') - const invalidWrapperJars = await validate.findInvalidWrapperJars( + const result = await validate.findInvalidWrapperJars( path.resolve('.'), - minWrapperCount, - allowSnapshots, - allowChecksums + +core.getInput('min-wrapper-count'), + core.getInput('allow-snapshots') === 'true', + core.getInput('allow-checksums').split(',') ) - if (invalidWrapperJars.length > 0) { - const list = invalidWrapperJars.map( - invalid => `${invalid.checksum} ${invalid.path}` - ) - core.setFailed( - `Found unknown Gradle Wrapper JAR files\n${list.join('\n- ')}` - ) + if (result.isValid()) { + core.info(result.toDisplayString()) + } else { + core.setFailed(result.toDisplayString()) } } catch (error) { core.setFailed(error.message) diff --git a/src/validate.ts b/src/validate.ts index 0be80e8..f10a771 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -7,33 +7,80 @@ export async function findInvalidWrapperJars( minWrapperCount: number, allowSnapshots: boolean, allowChecksums: string[] -): Promise { +): Promise { const wrapperJars = await find.findWrapperJars(gitRepoRoot) + const result = new ValidationResult([], []) if (wrapperJars.length < minWrapperCount) { - throw new Error( + result.errors.push( `Expected to find at least ${minWrapperCount} Gradle Wrapper JARs but got only ${wrapperJars.length}` ) } if (wrapperJars.length > 0) { const validChecksums = await checksums.fetchValidChecksums(allowSnapshots) validChecksums.push(...allowChecksums) - const invalidWrapperJars: InvalidWrapperJar[] = [] for (const wrapperJar of wrapperJars) { const sha = await hash.sha256File(wrapperJar) if (!validChecksums.includes(sha)) { - invalidWrapperJars.push(new InvalidWrapperJar(wrapperJar, sha)) + result.invalid.push(new WrapperJar(wrapperJar, sha)) + } else { + result.valid.push(new WrapperJar(wrapperJar, sha)) } } - return invalidWrapperJars } - return [] + return result } -export class InvalidWrapperJar { +export class ValidationResult { + valid: WrapperJar[] + invalid: WrapperJar[] + errors: string[] = [] + + constructor(valid: WrapperJar[], invalid: WrapperJar[]) { + this.valid = valid + this.invalid = invalid + } + + isValid(): boolean { + return this.invalid.length === 0 && this.errors.length === 0 + } + + toDisplayString(): string { + let displayString = '' + if (this.invalid.length > 0) { + displayString += `✗ Found unknown Gradle Wrapper JAR files:\n${ValidationResult.toDisplayList( + this.invalid + )}` + } + if (this.errors.length > 0) { + if (displayString.length > 0) displayString += '\n' + displayString += `✗ Other validation errors:\n ${this.errors.join( + `\n ` + )}` + } + if (this.valid.length > 0) { + if (displayString.length > 0) displayString += '\n' + displayString += `✓ Found known Gradle Wrapper JAR files:\n${ValidationResult.toDisplayList( + this.valid + )}` + } + return displayString + } + + private static toDisplayList(wrapperJars: WrapperJar[]): string { + return ` ${wrapperJars.map(wj => wj.toDisplayString()).join(`\n `)}` + } +} + +export class WrapperJar { path: string checksum: string + constructor(path: string, checksum: string) { this.path = path this.checksum = checksum } + + toDisplayString(): string { + return `${this.checksum} ${this.path}` + } }