From 62557f3635561c1c87913ef0282e1b50ebead1db Mon Sep 17 00:00:00 2001 From: daz Date: Thu, 11 Apr 2024 11:56:55 -0600 Subject: [PATCH] Enable wrapper validation with setup-gradle action --- .github/workflows/ci-integ-test.yml | 2 ++ .../integ-test-wrapper-validation.yml | 36 ++++++++++++++++--- setup-gradle/action.yml | 8 +++++ sources/src/configuration.ts | 4 +++ sources/src/dependency-graph.ts | 4 +-- sources/src/errors.ts | 6 ++-- sources/src/setup-gradle.ts | 15 ++++++++ sources/src/setup-gradle/main.ts | 6 ++++ 8 files changed, 72 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci-integ-test.yml b/.github/workflows/ci-integ-test.yml index b04db0b7..970c7da2 100644 --- a/.github/workflows/ci-integ-test.yml +++ b/.github/workflows/ci-integ-test.yml @@ -183,3 +183,5 @@ jobs: wrapper-validation: needs: [determine-suite, build-distribution] uses: ./.github/workflows/integ-test-wrapper-validation.yml + with: + runner-os: '["ubuntu-latest"]' diff --git a/.github/workflows/integ-test-wrapper-validation.yml b/.github/workflows/integ-test-wrapper-validation.yml index ce1df329..5dde6db8 100644 --- a/.github/workflows/integ-test-wrapper-validation.yml +++ b/.github/workflows/integ-test-wrapper-validation.yml @@ -1,12 +1,40 @@ -name: Test sample Kotlin DSL project +name: Test wrapper validation on: workflow_call: + inputs: + runner-os: + type: string + default: '["ubuntu-latest", "windows-latest", "macos-latest"]' jobs: - # Integration test for successful validation of wrappers + test-setup-gradle-validation: + strategy: + fail-fast: false + matrix: + os: ${{fromJSON(inputs.runner-os)}} + runs-on: ${{ matrix.os }} + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Initialize integ-test + uses: ./.github/actions/init-integ-test + + - name: Run wrapper-validation-action + id: setup-gradle + uses: ./setup-gradle + with: + validate-wrappers: true + continue-on-error: true + + - name: Check failure + run: | + if [ "${{ steps.setup-gradle.outcome}}" != "failure" ] ; then + echo "Expected validation to fail, but it didn't" + exit 1 + fi + test-validation-success: - name: 'Test: Validation success' runs-on: ubuntu-latest steps: - name: Checkout sources @@ -33,9 +61,7 @@ jobs: exit 1 fi - # Integration test for failing validation of wrappers test-validation-error: - name: 'Test: Validation error' runs-on: ubuntu-latest steps: - name: Checkout sources diff --git a/setup-gradle/action.yml b/setup-gradle/action.yml index 6a9ccc40..48ec0f34 100644 --- a/setup-gradle/action.yml +++ b/setup-gradle/action.yml @@ -100,6 +100,14 @@ inputs: description: Indicate that you agree to the Build ScanĀ® terms of use. This input value must be "yes". required: false + # Wrapper validation configuration + validate-wrappers: + description: | + When 'true', the action will perform the 'wrapper-validation' action automatically. + If the wrapper checksums are not valid, the action will fail. + required: false + default: false + # DEPRECATED ACTION INPUTS build-scan-terms-of-service-url: description: The URL to the Build ScanĀ® terms of use. This input must be set to 'https://gradle.com/terms-of-service'. diff --git a/sources/src/configuration.ts b/sources/src/configuration.ts index 0b23c618..f59cfbf7 100644 --- a/sources/src/configuration.ts +++ b/sources/src/configuration.ts @@ -261,6 +261,10 @@ export class GradleExecutionConfig { } } +export function doValidateWrappers(): boolean { + return getBooleanInput('validate-wrappers') +} + // Internal parameters export function getJobMatrix(): string { return core.getInput('workflow-job-context') diff --git a/sources/src/dependency-graph.ts b/sources/src/dependency-graph.ts index 41161914..a12fb130 100644 --- a/sources/src/dependency-graph.ts +++ b/sources/src/dependency-graph.ts @@ -9,7 +9,7 @@ import type {PullRequestEvent} from '@octokit/webhooks-types' import * as path from 'path' import fs from 'fs' -import {PostActionJobFailure} from './errors' +import {JobFailure} from './errors' import {DependencyGraphConfig, DependencyGraphOption, getGithubToken, getWorkspaceDirectory} from './configuration' const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_' @@ -208,7 +208,7 @@ function markProcessed(dependencyGraphFile: string): void { function warnOrFail(config: DependencyGraphConfig, option: String, error: unknown): void { if (!config.getDependencyGraphContinueOnFailure()) { - throw new PostActionJobFailure(error) + throw new JobFailure(error) } core.warning(`Failed to ${option} dependency graph. Will continue.\n${String(error)}`) diff --git a/sources/src/errors.ts b/sources/src/errors.ts index ad2e1e21..f3c4cb5d 100644 --- a/sources/src/errors.ts +++ b/sources/src/errors.ts @@ -1,6 +1,6 @@ import * as core from '@actions/core' -export class PostActionJobFailure extends Error { +export class JobFailure extends Error { constructor(error: unknown) { if (error instanceof Error) { super(error.message) @@ -21,6 +21,8 @@ export function handleMainActionError(error: unknown): void { core.info(err.stack) } } + } else if (error instanceof JobFailure) { + core.setFailed(String(error)) // No stack trace for JobFailure: these are known errors } else { core.setFailed(String(error)) if (error instanceof Error && error.stack) { @@ -30,7 +32,7 @@ export function handleMainActionError(error: unknown): void { } export function handlePostActionError(error: unknown): void { - if (error instanceof PostActionJobFailure) { + if (error instanceof JobFailure) { core.setFailed(String(error)) } else { core.warning(`Unhandled error in Gradle post-action - job will continue: ${error}`) diff --git a/sources/src/setup-gradle.ts b/sources/src/setup-gradle.ts index d4d3a334..bcf2d399 100644 --- a/sources/src/setup-gradle.ts +++ b/sources/src/setup-gradle.ts @@ -10,6 +10,8 @@ import {loadBuildResults, markBuildResultsProcessed} from './build-results' import {CacheListener, generateCachingReport} from './caching/cache-reporting' import {DaemonController} from './daemon-controller' import {BuildScanConfig, CacheConfig, SummaryConfig, getWorkspaceDirectory} from './configuration' +import {findInvalidWrapperJars} from './wrapper-validation/validate' +import {JobFailure} from './errors' const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED' const USER_HOME = 'USER_HOME' @@ -96,3 +98,16 @@ async function determineUserHome(): Promise { core.debug(`Determined user.home from java -version output: '${userHome}'`) return userHome } + +export async function checkNoInvalidWrapperJars(rootDir = getWorkspaceDirectory()): Promise { + const allowedChecksums = process.env['ALLOWED_GRADLE_WRAPPER_CHECKSUMS']?.split(',') || [] + const result = await findInvalidWrapperJars(rootDir, 1, false, allowedChecksums) + if (result.isValid()) { + core.info(result.toDisplayString()) + } else { + core.info(result.toDisplayString()) + throw new JobFailure( + `Gradle Wrapper Validation Failed!\n See https://github.com/gradle/actions/blob/main/docs/wrapper-validation.md#reporting-failures\n${result.toDisplayString()}` + ) + } +} diff --git a/sources/src/setup-gradle/main.ts b/sources/src/setup-gradle/main.ts index c66c47ec..f5bc5c45 100644 --- a/sources/src/setup-gradle/main.ts +++ b/sources/src/setup-gradle/main.ts @@ -6,6 +6,7 @@ import { CacheConfig, DependencyGraphConfig, GradleExecutionConfig, + doValidateWrappers, getActionId, setActionId } from '../configuration' @@ -25,6 +26,11 @@ export async function run(): Promise { setActionId('gradle/actions/setup-gradle') } + // Check for invalid wrapper JARs if requested + if (doValidateWrappers()) { + await setupGradle.checkNoInvalidWrapperJars() + } + // Configure Gradle environment (Gradle User Home) await setupGradle.setup(new CacheConfig(), new BuildScanConfig())