From c94d573317836997310532b120670ea89556f3c5 Mon Sep 17 00:00:00 2001 From: daz Date: Sat, 3 Jun 2023 14:09:52 -0600 Subject: [PATCH] Refactor action execution for reuse Introducing new actions for the GitHub dependency graph will involve reuse of much of the action infrastructure. This commit reorganises things a little to facilitate reuse. --- action.yml | 18 +++++++++--------- src/main.ts | 39 +++++++-------------------------------- src/provision.ts | 38 ++++++++++++++++++++++++++++++-------- src/repository-layout.ts | 16 ++++++++++++++++ src/setup-gradle.ts | 26 ++++++++++++++------------ 5 files changed, 76 insertions(+), 61 deletions(-) create mode 100644 src/repository-layout.ts diff --git a/action.yml b/action.yml index 40bf45e..dbd21f9 100644 --- a/action.yml +++ b/action.yml @@ -5,7 +5,15 @@ description: 'Configures Gradle for use in GitHub actions, caching useful state inputs: gradle-version: - description: Gradle version to use + description: Gradle version to use. If specified, this Gradle version will be downloaded, added to the PATH and used for invoking Gradle. + required: false + + gradle-executable: + description: Path to the Gradle executable. If specified, this executable will be added to the PATH and used for invoking Gradle. + required: false + + build-root-directory: + description: Path to the root directory of the build. Default is the root of the GitHub workspace. required: false cache-disabled: @@ -45,14 +53,6 @@ inputs: description: Gradle command line arguments (supports multi-line input) required: false - build-root-directory: - description: Path to the root directory of the build - required: false - - gradle-executable: - description: Path to the Gradle executable - required: false - generate-job-summary: description: When 'false', no Job Summary will be generated for the Job. required: false diff --git a/src/main.ts b/src/main.ts index e62cc6f..b871db0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,30 +1,26 @@ import * as core from '@actions/core' -import * as path from 'path' import {parseArgsStringToArgv} from 'string-argv' import * as setupGradle from './setup-gradle' import * as execution from './execution' -import * as provision from './provision' +import * as provisioner from './provision' +import * as layout from './repository-layout' /** * The main entry point for the action, called by Github Actions for the step. */ export async function run(): Promise { try { - const workspaceDirectory = process.env[`GITHUB_WORKSPACE`] || '' - const buildRootDirectory = resolveBuildRootDirectory(workspaceDirectory) + // Configure Gradle environment (Gradle User Home) + await setupGradle.setup() - await setupGradle.setup(buildRootDirectory) - - const executable = await provisionGradle(workspaceDirectory) - // executable will be undefined if using Gradle wrapper - if (executable !== undefined) { - core.addPath(path.dirname(executable)) - } + // Download and install Gradle if required + const executable = await provisioner.provisionGradle() // Only execute if arguments have been provided const args: string[] = parseCommandLineArguments() if (args.length > 0) { + const buildRootDirectory = layout.buildRootDirectory() await execution.executeGradleBuild(executable, buildRootDirectory, args) } } catch (error) { @@ -37,27 +33,6 @@ export async function run(): Promise { run() -async function provisionGradle(workspaceDirectory: string): Promise { - const gradleVersion = core.getInput('gradle-version') - if (gradleVersion !== '' && gradleVersion !== 'wrapper') { - return path.resolve(await provision.gradleVersion(gradleVersion)) - } - - const gradleExecutable = core.getInput('gradle-executable') - if (gradleExecutable !== '') { - return path.resolve(workspaceDirectory, gradleExecutable) - } - - return undefined -} - -function resolveBuildRootDirectory(baseDirectory: string): string { - const buildRootDirectory = core.getInput('build-root-directory') - const resolvedBuildRootDirectory = - buildRootDirectory === '' ? path.resolve(baseDirectory) : path.resolve(baseDirectory, buildRootDirectory) - return resolvedBuildRootDirectory -} - function parseCommandLineArguments(): string[] { const input = core.getInput('arguments') return parseArgsStringToArgv(input) diff --git a/src/provision.ts b/src/provision.ts index 96612b2..410a7cf 100644 --- a/src/provision.ts +++ b/src/provision.ts @@ -7,14 +7,36 @@ import * as cache from '@actions/cache' import * as toolCache from '@actions/tool-cache' import * as gradlew from './gradlew' +import * as layout from './repository-layout' import {handleCacheFailure, isCacheDisabled, isCacheReadOnly} from './cache-utils' const gradleVersionsBaseUrl = 'https://services.gradle.org/versions' /** - * @return Gradle executable path + * Install any configured version of Gradle, adding the executable to the PATH. + * @return Installed Gradle executable or undefined if no version configured. */ -export async function gradleVersion(version: string): Promise { +export async function provisionGradle(): Promise { + const gradleVersion = core.getInput('gradle-version') + if (gradleVersion !== '' && gradleVersion !== 'wrapper') { + return addToPath(path.resolve(await installGradle(gradleVersion))) + } + + const gradleExecutable = core.getInput('gradle-executable') + if (gradleExecutable !== '') { + const workspaceDirectory = layout.workspaceDirectory() + return addToPath(path.resolve(workspaceDirectory, gradleExecutable)) + } + + return undefined +} + +async function addToPath(executable: string): Promise { + core.addPath(path.dirname(executable)) + return executable +} + +async function installGradle(version: string): Promise { switch (version) { case 'current': return gradleCurrent() @@ -34,13 +56,13 @@ export async function gradleVersion(version: string): Promise { async function gradleCurrent(): Promise { const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/current`) - return provisionGradle(versionInfo) + return installGradleVersion(versionInfo) } async function gradleReleaseCandidate(): Promise { const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-candidate`) if (versionInfo && versionInfo.version && versionInfo.downloadUrl) { - return provisionGradle(versionInfo) + return installGradleVersion(versionInfo) } core.info('No current release-candidate found, will fallback to current') return gradleCurrent() @@ -48,12 +70,12 @@ async function gradleReleaseCandidate(): Promise { async function gradleNightly(): Promise { const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/nightly`) - return provisionGradle(versionInfo) + return installGradleVersion(versionInfo) } async function gradleReleaseNightly(): Promise { const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-nightly`) - return provisionGradle(versionInfo) + return installGradleVersion(versionInfo) } async function gradle(version: string): Promise { @@ -61,7 +83,7 @@ async function gradle(version: string): Promise { if (!versionInfo) { throw new Error(`Gradle version ${version} does not exists`) } - return provisionGradle(versionInfo) + return installGradleVersion(versionInfo) } async function gradleVersionDeclaration(url: string): Promise { @@ -75,7 +97,7 @@ async function findGradleVersionDeclaration(version: string): Promise { +async function installGradleVersion(versionInfo: GradleVersionInfo): Promise { return core.group(`Provision Gradle ${versionInfo.version}`, async () => { return locateGradleAndDownloadIfRequired(versionInfo) }) diff --git a/src/repository-layout.ts b/src/repository-layout.ts new file mode 100644 index 0000000..a0ac09e --- /dev/null +++ b/src/repository-layout.ts @@ -0,0 +1,16 @@ +import * as core from '@actions/core' +import * as path from 'path' + +export function workspaceDirectory(): string { + return process.env[`GITHUB_WORKSPACE`] || '' +} + +export function buildRootDirectory(): string { + const baseDirectory = workspaceDirectory() + const buildRootDirectoryInput = core.getInput('build-root-directory') + const resolvedBuildRootDirectory = + buildRootDirectoryInput === '' + ? path.resolve(baseDirectory) + : path.resolve(baseDirectory, buildRootDirectoryInput) + return resolvedBuildRootDirectory +} diff --git a/src/setup-gradle.ts b/src/setup-gradle.ts index 6c8762c..79529de 100644 --- a/src/setup-gradle.ts +++ b/src/setup-gradle.ts @@ -4,6 +4,7 @@ import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary' import * as path from 'path' import * as os from 'os' import * as caches from './caches' +import * as layout from './repository-layout' import {logJobSummary, writeJobSummary} from './job-summary' import {loadBuildResults} from './build-results' @@ -15,17 +16,8 @@ const GRADLE_USER_HOME = 'GRADLE_USER_HOME' const CACHE_LISTENER = 'CACHE_LISTENER' const JOB_SUMMARY_ENABLED_PARAMETER = 'generate-job-summary' -function shouldGenerateJobSummary(): boolean { - // Check if Job Summary is supported on this platform - if (!process.env[SUMMARY_ENV_VAR]) { - return false - } - - return core.getBooleanInput(JOB_SUMMARY_ENABLED_PARAMETER) -} - -export async function setup(buildRootDirectory: string): Promise { - const gradleUserHome = await determineGradleUserHome(buildRootDirectory) +export async function setup(): Promise { + const gradleUserHome = await determineGradleUserHome() // Bypass setup on all but first action step in workflow. if (process.env[GRADLE_SETUP_VAR]) { @@ -68,9 +60,10 @@ export async function complete(): Promise { } } -async function determineGradleUserHome(rootDir: string): Promise { +async function determineGradleUserHome(): Promise { const customGradleUserHome = process.env['GRADLE_USER_HOME'] if (customGradleUserHome) { + const rootDir = layout.workspaceDirectory() return path.resolve(rootDir, customGradleUserHome) } @@ -93,3 +86,12 @@ async function determineUserHome(): Promise { core.debug(`Determined user.home from java -version output: '${userHome}'`) return userHome } + +function shouldGenerateJobSummary(): boolean { + // Check if Job Summary is supported on this platform + if (!process.env[SUMMARY_ENV_VAR]) { + return false + } + + return core.getBooleanInput(JOB_SUMMARY_ENABLED_PARAMETER) +}