import * as core from '@actions/core' import * as github from '@actions/github' import * as cache from '@actions/cache' import * as deprecator from './deprecation-collector' import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary' import {parseArgsStringToArgv} from 'string-argv' import path from 'path' const ACTION_ID_VAR = 'GRADLE_ACTION_ID' export class DependencyGraphConfig { getDependencyGraphOption(): DependencyGraphOption { const val = core.getInput('dependency-graph') switch (val.toLowerCase().trim()) { case 'disabled': return DependencyGraphOption.Disabled case 'generate': return DependencyGraphOption.Generate case 'generate-and-submit': return DependencyGraphOption.GenerateAndSubmit case 'generate-and-upload': return DependencyGraphOption.GenerateAndUpload case 'download-and-submit': return DependencyGraphOption.DownloadAndSubmit case 'clear': return DependencyGraphOption.Clear } throw TypeError( `The value '${val}' is not valid for 'dependency-graph'. Valid values are: [disabled, generate, generate-and-submit, generate-and-upload, download-and-submit, clear]. The default value is 'disabled'.` ) } getDependencyGraphContinueOnFailure(): boolean { return getBooleanInput('dependency-graph-continue-on-failure', true) } getArtifactRetentionDays(): number { const val = core.getInput('artifact-retention-days') return parseNumericInput('artifact-retention-days', val, 0) // Zero indicates that the default repository settings should be used } getJobCorrelator(): string { return DependencyGraphConfig.constructJobCorrelator(github.context.workflow, github.context.job, getJobMatrix()) } static constructJobCorrelator(workflow: string, jobId: string, matrixJson: string): string { const matrixString = this.describeMatrix(matrixJson) const label = matrixString ? `${workflow}-${jobId}-${matrixString}` : `${workflow}-${jobId}` return this.sanitize(label) } private static describeMatrix(matrixJson: string): string { core.debug(`Got matrix json: ${matrixJson}`) const matrix = JSON.parse(matrixJson) if (matrix) { return Object.values(matrix).join('-') } return '' } private static sanitize(value: string): string { return value .replace(/[^a-zA-Z0-9_-\s]/g, '') .replace(/\s+/g, '_') .toLowerCase() } } export enum DependencyGraphOption { Disabled = 'disabled', Generate = 'generate', GenerateAndSubmit = 'generate-and-submit', GenerateAndUpload = 'generate-and-upload', DownloadAndSubmit = 'download-and-submit', Clear = 'clear' } export class CacheConfig { isCacheDisabled(): boolean { if (!cache.isFeatureAvailable()) { return true } return getBooleanInput('cache-disabled') } isCacheReadOnly(): boolean { return !this.isCacheWriteOnly() && getBooleanInput('cache-read-only') } isCacheWriteOnly(): boolean { return getBooleanInput('cache-write-only') } isCacheOverwriteExisting(): boolean { return getBooleanInput('cache-overwrite-existing') } isCacheStrictMatch(): boolean { return getBooleanInput('gradle-home-cache-strict-match') } isCacheCleanupEnabled(): boolean { return getBooleanInput('gradle-home-cache-cleanup') && !this.isCacheReadOnly() } getCacheEncryptionKey(): string { return core.getInput('cache-encryption-key') } getCacheIncludes(): string[] { return core.getMultilineInput('gradle-home-cache-includes') } getCacheExcludes(): string[] { return core.getMultilineInput('gradle-home-cache-excludes') } } export class SummaryConfig { shouldGenerateJobSummary(hasFailure: boolean): boolean { // Check if Job Summary is supported on this platform if (!process.env[SUMMARY_ENV_VAR]) { return false } // Check if Job Summary is disabled using the deprecated input if (!this.isJobSummaryEnabled()) { return false } return this.shouldAddJobSummary(this.getJobSummaryOption(), hasFailure) } shouldAddPRComment(hasFailure: boolean): boolean { return this.shouldAddJobSummary(this.getPRCommentOption(), hasFailure) } private shouldAddJobSummary(option: JobSummaryOption, hasFailure: boolean): boolean { switch (option) { case JobSummaryOption.Always: return true case JobSummaryOption.Never: return false case JobSummaryOption.OnFailure: return hasFailure } } private isJobSummaryEnabled(): boolean { return getBooleanInput('generate-job-summary', true) } private getJobSummaryOption(): JobSummaryOption { return this.parseJobSummaryOption('add-job-summary') } private getPRCommentOption(): JobSummaryOption { return this.parseJobSummaryOption('add-job-summary-as-pr-comment') } private parseJobSummaryOption(paramName: string): JobSummaryOption { const val = core.getInput(paramName) switch (val.toLowerCase().trim()) { case 'never': return JobSummaryOption.Never case 'always': return JobSummaryOption.Always case 'on-failure': return JobSummaryOption.OnFailure } throw TypeError( `The value '${val}' is not valid for ${paramName}. Valid values are: [never, always, on-failure].` ) } } export enum JobSummaryOption { Never = 'never', Always = 'always', OnFailure = 'on-failure' } export class BuildScanConfig { getBuildScanPublishEnabled(): boolean { return getBooleanInput('build-scan-publish') && this.verifyTermsOfUseAgreement() } getBuildScanTermsOfUseUrl(): string { return this.getTermsOfUseProp('build-scan-terms-of-use-url', 'build-scan-terms-of-service-url') } getBuildScanTermsOfUseAgree(): string { return this.getTermsOfUseProp('build-scan-terms-of-use-agree', 'build-scan-terms-of-service-agree') } private verifyTermsOfUseAgreement(): boolean { if ( (this.getBuildScanTermsOfUseUrl() !== 'https://gradle.com/terms-of-service' && this.getBuildScanTermsOfUseUrl() !== 'https://gradle.com/help/legal-terms-of-use') || this.getBuildScanTermsOfUseAgree() !== 'yes' ) { core.warning( `Terms of use at 'https://gradle.com/help/legal-terms-of-use' must be agreed in order to publish build scans.` ) return false } return true } /** * TODO @bigdaz: remove support for the deprecated input property in the next major release of the action */ private getTermsOfUseProp(newPropName: string, oldPropName: string): string { const newProp = core.getInput(newPropName) if (newProp !== '') { return newProp } const oldProp = core.getInput(oldPropName) if (oldProp !== '') { deprecator.recordDeprecation('The `build-scan-terms-of-service` input parameters have been renamed') return oldProp } return core.getInput(oldPropName) } } export class GradleExecutionConfig { getGradleVersion(): string { return core.getInput('gradle-version') } getBuildRootDirectory(): string { const baseDirectory = getWorkspaceDirectory() const buildRootDirectoryInput = core.getInput('build-root-directory') const resolvedBuildRootDirectory = buildRootDirectoryInput === '' ? path.resolve(baseDirectory) : path.resolve(baseDirectory, buildRootDirectoryInput) return resolvedBuildRootDirectory } getArguments(): string[] { const input = core.getInput('arguments') if (input.length !== 0) { deprecator.recordDeprecation( 'Using the action to execute Gradle via the `arguments` parameter is deprecated' ) } return parseArgsStringToArgv(input) } getDependencyResolutionTask(): string { return core.getInput('dependency-resolution-task') || ':ForceDependencyResolutionPlugin_resolveAllDependencies' } getAdditionalArguments(): string { return core.getInput('additional-arguments') } } // Internal parameters export function getJobMatrix(): string { return core.getInput('workflow-job-context') } export function getGithubToken(): string { return core.getInput('github-token', {required: true}) } export function getWorkspaceDirectory(): string { return process.env[`GITHUB_WORKSPACE`] || '' } export function getActionId(): string | undefined { return process.env[ACTION_ID_VAR] } export function setActionId(id: string): void { core.exportVariable(ACTION_ID_VAR, id) } export function parseNumericInput(paramName: string, paramValue: string, paramDefault: number): number { if (paramValue.length === 0) { return paramDefault } const numericValue = parseInt(paramValue) if (isNaN(numericValue)) { throw TypeError(`The value '${paramValue}' is not a valid numeric value for '${paramName}'.`) } return numericValue } function getBooleanInput(paramName: string, paramDefault = false): boolean { const paramValue = core.getInput(paramName) switch (paramValue.toLowerCase().trim()) { case '': return paramDefault case 'false': return false case 'true': return true } throw TypeError(`The value '${paramValue} is not valid for '${paramName}. Valid values are: [true, false]`) }