gradle/sources/src/configuration.ts

308 lines
9.9 KiB
TypeScript

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]`)
}