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.
This commit is contained in:
daz 2023-06-03 14:09:52 -06:00
parent 680037c65b
commit c94d573317
No known key found for this signature in database
5 changed files with 76 additions and 61 deletions

View File

@ -5,7 +5,15 @@ description: 'Configures Gradle for use in GitHub actions, caching useful state
inputs: inputs:
gradle-version: 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 required: false
cache-disabled: cache-disabled:
@ -45,14 +53,6 @@ inputs:
description: Gradle command line arguments (supports multi-line input) description: Gradle command line arguments (supports multi-line input)
required: false 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: generate-job-summary:
description: When 'false', no Job Summary will be generated for the Job. description: When 'false', no Job Summary will be generated for the Job.
required: false required: false

View File

@ -1,30 +1,26 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import * as path from 'path'
import {parseArgsStringToArgv} from 'string-argv' import {parseArgsStringToArgv} from 'string-argv'
import * as setupGradle from './setup-gradle' import * as setupGradle from './setup-gradle'
import * as execution from './execution' 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. * The main entry point for the action, called by Github Actions for the step.
*/ */
export async function run(): Promise<void> { export async function run(): Promise<void> {
try { try {
const workspaceDirectory = process.env[`GITHUB_WORKSPACE`] || '' // Configure Gradle environment (Gradle User Home)
const buildRootDirectory = resolveBuildRootDirectory(workspaceDirectory) await setupGradle.setup()
await setupGradle.setup(buildRootDirectory) // Download and install Gradle if required
const executable = await provisioner.provisionGradle()
const executable = await provisionGradle(workspaceDirectory)
// executable will be undefined if using Gradle wrapper
if (executable !== undefined) {
core.addPath(path.dirname(executable))
}
// Only execute if arguments have been provided // Only execute if arguments have been provided
const args: string[] = parseCommandLineArguments() const args: string[] = parseCommandLineArguments()
if (args.length > 0) { if (args.length > 0) {
const buildRootDirectory = layout.buildRootDirectory()
await execution.executeGradleBuild(executable, buildRootDirectory, args) await execution.executeGradleBuild(executable, buildRootDirectory, args)
} }
} catch (error) { } catch (error) {
@ -37,27 +33,6 @@ export async function run(): Promise<void> {
run() run()
async function provisionGradle(workspaceDirectory: string): Promise<string | undefined> {
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[] { function parseCommandLineArguments(): string[] {
const input = core.getInput('arguments') const input = core.getInput('arguments')
return parseArgsStringToArgv(input) return parseArgsStringToArgv(input)

View File

@ -7,14 +7,36 @@ import * as cache from '@actions/cache'
import * as toolCache from '@actions/tool-cache' import * as toolCache from '@actions/tool-cache'
import * as gradlew from './gradlew' import * as gradlew from './gradlew'
import * as layout from './repository-layout'
import {handleCacheFailure, isCacheDisabled, isCacheReadOnly} from './cache-utils' import {handleCacheFailure, isCacheDisabled, isCacheReadOnly} from './cache-utils'
const gradleVersionsBaseUrl = 'https://services.gradle.org/versions' 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<string> { export async function provisionGradle(): Promise<string | undefined> {
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<string> {
core.addPath(path.dirname(executable))
return executable
}
async function installGradle(version: string): Promise<string> {
switch (version) { switch (version) {
case 'current': case 'current':
return gradleCurrent() return gradleCurrent()
@ -34,13 +56,13 @@ export async function gradleVersion(version: string): Promise<string> {
async function gradleCurrent(): Promise<string> { async function gradleCurrent(): Promise<string> {
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/current`) const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/current`)
return provisionGradle(versionInfo) return installGradleVersion(versionInfo)
} }
async function gradleReleaseCandidate(): Promise<string> { async function gradleReleaseCandidate(): Promise<string> {
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-candidate`) const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-candidate`)
if (versionInfo && versionInfo.version && versionInfo.downloadUrl) { if (versionInfo && versionInfo.version && versionInfo.downloadUrl) {
return provisionGradle(versionInfo) return installGradleVersion(versionInfo)
} }
core.info('No current release-candidate found, will fallback to current') core.info('No current release-candidate found, will fallback to current')
return gradleCurrent() return gradleCurrent()
@ -48,12 +70,12 @@ async function gradleReleaseCandidate(): Promise<string> {
async function gradleNightly(): Promise<string> { async function gradleNightly(): Promise<string> {
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/nightly`) const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/nightly`)
return provisionGradle(versionInfo) return installGradleVersion(versionInfo)
} }
async function gradleReleaseNightly(): Promise<string> { async function gradleReleaseNightly(): Promise<string> {
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-nightly`) const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-nightly`)
return provisionGradle(versionInfo) return installGradleVersion(versionInfo)
} }
async function gradle(version: string): Promise<string> { async function gradle(version: string): Promise<string> {
@ -61,7 +83,7 @@ async function gradle(version: string): Promise<string> {
if (!versionInfo) { if (!versionInfo) {
throw new Error(`Gradle version ${version} does not exists`) throw new Error(`Gradle version ${version} does not exists`)
} }
return provisionGradle(versionInfo) return installGradleVersion(versionInfo)
} }
async function gradleVersionDeclaration(url: string): Promise<GradleVersionInfo> { async function gradleVersionDeclaration(url: string): Promise<GradleVersionInfo> {
@ -75,7 +97,7 @@ async function findGradleVersionDeclaration(version: string): Promise<GradleVers
}) })
} }
async function provisionGradle(versionInfo: GradleVersionInfo): Promise<string> { async function installGradleVersion(versionInfo: GradleVersionInfo): Promise<string> {
return core.group(`Provision Gradle ${versionInfo.version}`, async () => { return core.group(`Provision Gradle ${versionInfo.version}`, async () => {
return locateGradleAndDownloadIfRequired(versionInfo) return locateGradleAndDownloadIfRequired(versionInfo)
}) })

16
src/repository-layout.ts Normal file
View File

@ -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
}

View File

@ -4,6 +4,7 @@ import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary'
import * as path from 'path' import * as path from 'path'
import * as os from 'os' import * as os from 'os'
import * as caches from './caches' import * as caches from './caches'
import * as layout from './repository-layout'
import {logJobSummary, writeJobSummary} from './job-summary' import {logJobSummary, writeJobSummary} from './job-summary'
import {loadBuildResults} from './build-results' import {loadBuildResults} from './build-results'
@ -15,17 +16,8 @@ const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
const CACHE_LISTENER = 'CACHE_LISTENER' const CACHE_LISTENER = 'CACHE_LISTENER'
const JOB_SUMMARY_ENABLED_PARAMETER = 'generate-job-summary' const JOB_SUMMARY_ENABLED_PARAMETER = 'generate-job-summary'
function shouldGenerateJobSummary(): boolean { export async function setup(): Promise<void> {
// Check if Job Summary is supported on this platform const gradleUserHome = await determineGradleUserHome()
if (!process.env[SUMMARY_ENV_VAR]) {
return false
}
return core.getBooleanInput(JOB_SUMMARY_ENABLED_PARAMETER)
}
export async function setup(buildRootDirectory: string): Promise<void> {
const gradleUserHome = await determineGradleUserHome(buildRootDirectory)
// Bypass setup on all but first action step in workflow. // Bypass setup on all but first action step in workflow.
if (process.env[GRADLE_SETUP_VAR]) { if (process.env[GRADLE_SETUP_VAR]) {
@ -68,9 +60,10 @@ export async function complete(): Promise<void> {
} }
} }
async function determineGradleUserHome(rootDir: string): Promise<string> { async function determineGradleUserHome(): Promise<string> {
const customGradleUserHome = process.env['GRADLE_USER_HOME'] const customGradleUserHome = process.env['GRADLE_USER_HOME']
if (customGradleUserHome) { if (customGradleUserHome) {
const rootDir = layout.workspaceDirectory()
return path.resolve(rootDir, customGradleUserHome) return path.resolve(rootDir, customGradleUserHome)
} }
@ -93,3 +86,12 @@ async function determineUserHome(): Promise<string> {
core.debug(`Determined user.home from java -version output: '${userHome}'`) core.debug(`Determined user.home from java -version output: '${userHome}'`)
return 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)
}