mirror of
https://github.com/gradle/actions
synced 2024-11-23 18:02:13 +00:00
Replace static config methods with config types
This will allow different entry points to have different inputs.
This commit is contained in:
parent
ed4d086d37
commit
cfd20ecc0a
16 changed files with 337 additions and 323 deletions
|
@ -1,30 +1,18 @@
|
|||
import * as core from '@actions/core'
|
||||
import {getBuildScanPublishEnabled, getBuildScanTermsOfUseUrl, getBuildScanTermsOfUseAgree} from './input-params'
|
||||
import {BuildScanConfig} from './input-params'
|
||||
|
||||
export function setup(): void {
|
||||
export function setup(config: BuildScanConfig): void {
|
||||
maybeExportVariable('DEVELOCITY_INJECTION_INIT_SCRIPT_NAME', 'gradle-actions.inject-develocity.init.gradle')
|
||||
maybeExportVariable('DEVELOCITY_AUTO_INJECTION_CUSTOM_VALUE', 'gradle-actions')
|
||||
if (getBuildScanPublishEnabled() && verifyTermsOfUseAgreement()) {
|
||||
if (config.getBuildScanPublishEnabled()) {
|
||||
maybeExportVariable('DEVELOCITY_INJECTION_ENABLED', 'true')
|
||||
maybeExportVariable('DEVELOCITY_PLUGIN_VERSION', '3.17')
|
||||
maybeExportVariable('DEVELOCITY_CCUD_PLUGIN_VERSION', '1.13')
|
||||
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_URL', getBuildScanTermsOfUseUrl())
|
||||
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_AGREE', getBuildScanTermsOfUseAgree())
|
||||
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_URL', config.getBuildScanTermsOfUseUrl())
|
||||
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_AGREE', config.getBuildScanTermsOfUseAgree())
|
||||
}
|
||||
}
|
||||
|
||||
function verifyTermsOfUseAgreement(): boolean {
|
||||
if (
|
||||
(getBuildScanTermsOfUseUrl() !== 'https://gradle.com/terms-of-service' &&
|
||||
getBuildScanTermsOfUseUrl() !== 'https://gradle.com/help/legal-terms-of-use') ||
|
||||
getBuildScanTermsOfUseAgree() !== 'yes'
|
||||
) {
|
||||
core.warning(`Terms of use must be agreed in order to publish build scans.`)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function maybeExportVariable(variableName: string, value: unknown): void {
|
||||
if (!process.env[variableName]) {
|
||||
core.exportVariable(variableName, value)
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as glob from '@actions/glob'
|
|||
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import * as params from './input-params'
|
||||
import {CacheConfig} from './input-params'
|
||||
import {CacheListener} from './cache-reporting'
|
||||
import {saveCache, restoreCache, cacheDebug, isCacheDebuggingEnabled, tryDelete, generateCacheKey} from './cache-utils'
|
||||
import {GradleHomeEntryExtractor, ConfigurationCacheEntryExtractor} from './cache-extract-entries'
|
||||
|
@ -14,15 +14,17 @@ const RESTORED_CACHE_KEY_KEY = 'restored-cache-key'
|
|||
export const META_FILE_DIR = '.setup-gradle'
|
||||
|
||||
export class GradleStateCache {
|
||||
private cacheConfig: CacheConfig
|
||||
private cacheName: string
|
||||
private cacheDescription: string
|
||||
|
||||
protected readonly userHome: string
|
||||
protected readonly gradleUserHome: string
|
||||
|
||||
constructor(userHome: string, gradleUserHome: string) {
|
||||
constructor(userHome: string, gradleUserHome: string, cacheConfig: CacheConfig) {
|
||||
this.userHome = userHome
|
||||
this.gradleUserHome = gradleUserHome
|
||||
this.cacheConfig = cacheConfig
|
||||
this.cacheName = 'gradle'
|
||||
this.cacheDescription = 'Gradle User Home'
|
||||
}
|
||||
|
@ -31,7 +33,7 @@ export class GradleStateCache {
|
|||
this.initializeGradleUserHome()
|
||||
|
||||
// Export the GRADLE_ENCRYPTION_KEY variable if provided
|
||||
const encryptionKey = params.getCacheEncryptionKey()
|
||||
const encryptionKey = this.cacheConfig.getCacheEncryptionKey()
|
||||
if (encryptionKey) {
|
||||
core.exportVariable('GRADLE_ENCRYPTION_KEY', encryptionKey)
|
||||
}
|
||||
|
@ -52,7 +54,7 @@ export class GradleStateCache {
|
|||
async restore(listener: CacheListener): Promise<void> {
|
||||
const entryListener = listener.entry(this.cacheDescription)
|
||||
|
||||
const cacheKey = generateCacheKey(this.cacheName)
|
||||
const cacheKey = generateCacheKey(this.cacheName, this.cacheConfig)
|
||||
|
||||
cacheDebug(
|
||||
`Requesting ${this.cacheDescription} with
|
||||
|
@ -82,8 +84,8 @@ export class GradleStateCache {
|
|||
*/
|
||||
async afterRestore(listener: CacheListener): Promise<void> {
|
||||
await this.debugReportGradleUserHomeSize('as restored from cache')
|
||||
await new GradleHomeEntryExtractor(this.gradleUserHome).restore(listener)
|
||||
await new ConfigurationCacheEntryExtractor(this.gradleUserHome).restore(listener)
|
||||
await new GradleHomeEntryExtractor(this.gradleUserHome, this.cacheConfig).restore(listener)
|
||||
await new ConfigurationCacheEntryExtractor(this.gradleUserHome, this.cacheConfig).restore(listener)
|
||||
await this.debugReportGradleUserHomeSize('after restoring common artifacts')
|
||||
}
|
||||
|
||||
|
@ -95,7 +97,7 @@ export class GradleStateCache {
|
|||
* it is saved with the exact key.
|
||||
*/
|
||||
async save(listener: CacheListener): Promise<void> {
|
||||
const cacheKey = generateCacheKey(this.cacheName).key
|
||||
const cacheKey = generateCacheKey(this.cacheName, this.cacheConfig).key
|
||||
const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY)
|
||||
const gradleHomeEntryListener = listener.entry(this.cacheDescription)
|
||||
|
||||
|
@ -133,8 +135,8 @@ export class GradleStateCache {
|
|||
await this.debugReportGradleUserHomeSize('before saving common artifacts')
|
||||
await this.deleteExcludedPaths()
|
||||
await Promise.all([
|
||||
new GradleHomeEntryExtractor(this.gradleUserHome).extract(listener),
|
||||
new ConfigurationCacheEntryExtractor(this.gradleUserHome).extract(listener)
|
||||
new GradleHomeEntryExtractor(this.gradleUserHome, this.cacheConfig).extract(listener),
|
||||
new ConfigurationCacheEntryExtractor(this.gradleUserHome, this.cacheConfig).extract(listener)
|
||||
])
|
||||
await this.debugReportGradleUserHomeSize(
|
||||
"after extracting common artifacts (only 'caches' and 'notifications' will be stored)"
|
||||
|
@ -145,7 +147,7 @@ export class GradleStateCache {
|
|||
* Delete any file paths that are excluded by the `gradle-home-cache-excludes` parameter.
|
||||
*/
|
||||
private async deleteExcludedPaths(): Promise<void> {
|
||||
const rawPaths: string[] = params.getCacheExcludes()
|
||||
const rawPaths: string[] = this.cacheConfig.getCacheExcludes()
|
||||
rawPaths.push('caches/*/cc-keystore')
|
||||
const resolvedPaths = rawPaths.map(x => path.resolve(this.gradleUserHome, x))
|
||||
|
||||
|
@ -168,7 +170,7 @@ export class GradleStateCache {
|
|||
* but this can be overridden by the `gradle-home-cache-includes` parameter.
|
||||
*/
|
||||
protected getCachePath(): string[] {
|
||||
const rawPaths: string[] = params.getCacheIncludes()
|
||||
const rawPaths: string[] = this.cacheConfig.getCacheIncludes()
|
||||
rawPaths.push(META_FILE_DIR)
|
||||
const resolvedPaths = rawPaths.map(x => this.resolveCachePath(x))
|
||||
cacheDebug(`Using cache paths: ${resolvedPaths}`)
|
||||
|
|
|
@ -4,12 +4,19 @@ import * as core from '@actions/core'
|
|||
import * as glob from '@actions/glob'
|
||||
import * as semver from 'semver'
|
||||
|
||||
import * as params from './input-params'
|
||||
|
||||
import {META_FILE_DIR} from './cache-base'
|
||||
import {CacheEntryListener, CacheListener} from './cache-reporting'
|
||||
import {cacheDebug, getCacheKeyPrefix, hashFileNames, restoreCache, saveCache, tryDelete} from './cache-utils'
|
||||
import {
|
||||
cacheDebug,
|
||||
getCacheKeyPrefix,
|
||||
hashFileNames,
|
||||
isCacheDebuggingEnabled,
|
||||
restoreCache,
|
||||
saveCache,
|
||||
tryDelete
|
||||
} from './cache-utils'
|
||||
import {BuildResult, loadBuildResults} from './build-results'
|
||||
import {CacheConfig} from './input-params'
|
||||
|
||||
const SKIP_RESTORE_VAR = 'GRADLE_BUILD_ACTION_SKIP_RESTORE'
|
||||
|
||||
|
@ -80,12 +87,14 @@ class ExtractedCacheEntryDefinition {
|
|||
* for more efficient storage.
|
||||
*/
|
||||
abstract class AbstractEntryExtractor {
|
||||
protected readonly cacheConfig: CacheConfig
|
||||
protected readonly gradleUserHome: string
|
||||
private extractorName: string
|
||||
|
||||
constructor(gradleUserHome: string, extractorName: string) {
|
||||
constructor(gradleUserHome: string, extractorName: string, cacheConfig: CacheConfig) {
|
||||
this.gradleUserHome = gradleUserHome
|
||||
this.extractorName = extractorName
|
||||
this.cacheConfig = cacheConfig
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -261,7 +270,7 @@ abstract class AbstractEntryExtractor {
|
|||
|
||||
// Run actions sequentially if debugging is enabled
|
||||
private async awaitForDebugging(p: Promise<ExtractedCacheEntry>): Promise<ExtractedCacheEntry> {
|
||||
if (params.isCacheDebuggingEnabled()) {
|
||||
if (isCacheDebuggingEnabled()) {
|
||||
await p
|
||||
}
|
||||
return p
|
||||
|
@ -306,8 +315,8 @@ abstract class AbstractEntryExtractor {
|
|||
}
|
||||
|
||||
export class GradleHomeEntryExtractor extends AbstractEntryExtractor {
|
||||
constructor(gradleUserHome: string) {
|
||||
super(gradleUserHome, 'gradle-home')
|
||||
constructor(gradleUserHome: string, cacheConfig: CacheConfig) {
|
||||
super(gradleUserHome, 'gradle-home', cacheConfig)
|
||||
}
|
||||
|
||||
async extract(listener: CacheListener): Promise<void> {
|
||||
|
@ -363,8 +372,8 @@ export class GradleHomeEntryExtractor extends AbstractEntryExtractor {
|
|||
}
|
||||
|
||||
export class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
||||
constructor(gradleUserHome: string) {
|
||||
super(gradleUserHome, 'configuration-cache')
|
||||
constructor(gradleUserHome: string, cacheConfig: CacheConfig) {
|
||||
super(gradleUserHome, 'configuration-cache', cacheConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -377,7 +386,7 @@ export class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
|||
return
|
||||
}
|
||||
|
||||
if (!params.getCacheEncryptionKey()) {
|
||||
if (!this.cacheConfig.getCacheEncryptionKey()) {
|
||||
this.markNotRestored(listener, 'Encryption Key was not provided')
|
||||
return
|
||||
}
|
||||
|
@ -399,7 +408,7 @@ export class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
|||
}
|
||||
|
||||
async extract(listener: CacheListener): Promise<void> {
|
||||
if (!params.getCacheEncryptionKey()) {
|
||||
if (!this.cacheConfig.getCacheEncryptionKey()) {
|
||||
const cacheEntryDefinitions = this.getExtractedCacheEntryDefinitions()
|
||||
if (cacheEntryDefinitions.length > 0) {
|
||||
core.info('Not saving configuration-cache state, as no encryption key was provided')
|
||||
|
|
|
@ -7,9 +7,8 @@ import * as crypto from 'crypto'
|
|||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
|
||||
import * as params from './input-params'
|
||||
|
||||
import {CacheEntryListener} from './cache-reporting'
|
||||
import {CacheConfig, getJobMatrix} from './input-params'
|
||||
|
||||
const CACHE_PROTOCOL_VERSION = 'v9-'
|
||||
|
||||
|
@ -22,31 +21,11 @@ const CACHE_KEY_JOB_EXECUTION_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION
|
|||
const SEGMENT_DOWNLOAD_TIMEOUT_VAR = 'SEGMENT_DOWNLOAD_TIMEOUT_MINS'
|
||||
const SEGMENT_DOWNLOAD_TIMEOUT_DEFAULT = 10 * 60 * 1000 // 10 minutes
|
||||
|
||||
export function isCacheDisabled(): boolean {
|
||||
if (!cache.isFeatureAvailable()) {
|
||||
export function isCacheDebuggingEnabled(): boolean {
|
||||
if (core.isDebug()) {
|
||||
return true
|
||||
}
|
||||
return params.isCacheDisabled()
|
||||
}
|
||||
|
||||
export function isCacheReadOnly(): boolean {
|
||||
return !isCacheWriteOnly() && params.isCacheReadOnly()
|
||||
}
|
||||
|
||||
export function isCacheWriteOnly(): boolean {
|
||||
return params.isCacheWriteOnly()
|
||||
}
|
||||
|
||||
export function isCacheOverwriteExisting(): boolean {
|
||||
return params.isCacheOverwriteExisting()
|
||||
}
|
||||
|
||||
export function isCacheDebuggingEnabled(): boolean {
|
||||
return params.isCacheDebuggingEnabled()
|
||||
}
|
||||
|
||||
export function isCacheCleanupEnabled(): boolean {
|
||||
return params.isCacheCleanupEnabled()
|
||||
return process.env['GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED'] ? true : false
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,7 +59,7 @@ export class CacheKey {
|
|||
* - Any previous key for this Job (any matrix)
|
||||
* - Any previous key for this cache on the current OS
|
||||
*/
|
||||
export function generateCacheKey(cacheName: string): CacheKey {
|
||||
export function generateCacheKey(cacheName: string, config: CacheConfig): CacheKey {
|
||||
const cacheKeyBase = `${getCacheKeyPrefix()}${CACHE_PROTOCOL_VERSION}${cacheName}`
|
||||
|
||||
// At the most general level, share caches for all executions on the same OS
|
||||
|
@ -95,7 +74,7 @@ export function generateCacheKey(cacheName: string): CacheKey {
|
|||
// Exact match on Git SHA
|
||||
const cacheKey = `${cacheKeyForJobContext}-${getCacheKeyJobExecution()}`
|
||||
|
||||
if (params.isCacheStrictMatch()) {
|
||||
if (config.isCacheStrictMatch()) {
|
||||
return new CacheKey(cacheKey, [cacheKeyForJobContext])
|
||||
}
|
||||
|
||||
|
@ -125,7 +104,7 @@ function getCacheKeyJobInstance(): string {
|
|||
// By default, we hash the workflow name and the full `matrix` data for the run, to uniquely identify this job invocation
|
||||
// The only way we can obtain the `matrix` data is via the `workflow-job-context` parameter in action.yml.
|
||||
const workflowName = github.context.workflow
|
||||
const workflowJobContext = params.getJobMatrix()
|
||||
const workflowJobContext = getJobMatrix()
|
||||
return hashStrings([workflowName, workflowJobContext])
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
import * as core from '@actions/core'
|
||||
import {
|
||||
isCacheCleanupEnabled,
|
||||
isCacheDisabled,
|
||||
isCacheReadOnly,
|
||||
isCacheWriteOnly,
|
||||
isCacheOverwriteExisting
|
||||
} from './cache-utils'
|
||||
import {CacheListener} from './cache-reporting'
|
||||
import {DaemonController} from './daemon-controller'
|
||||
import {GradleStateCache} from './cache-base'
|
||||
import {CacheCleaner} from './cache-cleaner'
|
||||
import {CacheConfig} from './input-params'
|
||||
|
||||
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'
|
||||
|
||||
export async function restore(userHome: string, gradleUserHome: string, cacheListener: CacheListener): Promise<void> {
|
||||
export async function restore(
|
||||
userHome: string,
|
||||
gradleUserHome: string,
|
||||
cacheListener: CacheListener,
|
||||
cacheConfig: CacheConfig
|
||||
): Promise<void> {
|
||||
// Bypass restore cache on all but first action step in workflow.
|
||||
if (process.env[CACHE_RESTORED_VAR]) {
|
||||
core.info('Cache only restored on first action step.')
|
||||
|
@ -21,9 +20,9 @@ export async function restore(userHome: string, gradleUserHome: string, cacheLis
|
|||
}
|
||||
core.exportVariable(CACHE_RESTORED_VAR, true)
|
||||
|
||||
const gradleStateCache = new GradleStateCache(userHome, gradleUserHome)
|
||||
const gradleStateCache = new GradleStateCache(userHome, gradleUserHome, cacheConfig)
|
||||
|
||||
if (isCacheDisabled()) {
|
||||
if (cacheConfig.isCacheDisabled()) {
|
||||
core.info('Cache is disabled: will not restore state from previous builds.')
|
||||
// Initialize the Gradle User Home even when caching is disabled.
|
||||
gradleStateCache.init()
|
||||
|
@ -32,7 +31,7 @@ export async function restore(userHome: string, gradleUserHome: string, cacheLis
|
|||
}
|
||||
|
||||
if (gradleStateCache.cacheOutputExists()) {
|
||||
if (!isCacheOverwriteExisting()) {
|
||||
if (!cacheConfig.isCacheOverwriteExisting()) {
|
||||
core.info('Gradle User Home already exists: will not restore from cache.')
|
||||
// Initialize pre-existing Gradle User Home.
|
||||
gradleStateCache.init()
|
||||
|
@ -47,7 +46,7 @@ export async function restore(userHome: string, gradleUserHome: string, cacheLis
|
|||
// Mark the state as restored so that post-action will perform save.
|
||||
core.saveState(CACHE_RESTORED_VAR, true)
|
||||
|
||||
if (isCacheWriteOnly()) {
|
||||
if (cacheConfig.isCacheWriteOnly()) {
|
||||
core.info('Cache is write-only: will not restore from cache.')
|
||||
cacheListener.cacheWriteOnly = true
|
||||
return
|
||||
|
@ -57,7 +56,7 @@ export async function restore(userHome: string, gradleUserHome: string, cacheLis
|
|||
await gradleStateCache.restore(cacheListener)
|
||||
})
|
||||
|
||||
if (isCacheCleanupEnabled() && !isCacheReadOnly()) {
|
||||
if (cacheConfig.isCacheCleanupEnabled()) {
|
||||
core.info('Preparing cache for cleanup.')
|
||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||
await cacheCleaner.prepare()
|
||||
|
@ -68,9 +67,10 @@ export async function save(
|
|||
userHome: string,
|
||||
gradleUserHome: string,
|
||||
cacheListener: CacheListener,
|
||||
daemonController: DaemonController
|
||||
daemonController: DaemonController,
|
||||
cacheConfig: CacheConfig
|
||||
): Promise<void> {
|
||||
if (isCacheDisabled()) {
|
||||
if (cacheConfig.isCacheDisabled()) {
|
||||
core.info('Cache is disabled: will not save state for later builds.')
|
||||
return
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ export async function save(
|
|||
return
|
||||
}
|
||||
|
||||
if (isCacheReadOnly()) {
|
||||
if (cacheConfig.isCacheReadOnly()) {
|
||||
core.info('Cache is read-only: will not save state for use in subsequent builds.')
|
||||
cacheListener.cacheReadOnly = true
|
||||
return
|
||||
|
@ -88,7 +88,7 @@ export async function save(
|
|||
|
||||
await daemonController.stopAllDaemons()
|
||||
|
||||
if (isCacheCleanupEnabled()) {
|
||||
if (cacheConfig.isCacheCleanupEnabled()) {
|
||||
core.info('Forcing cache cleanup.')
|
||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||
try {
|
||||
|
@ -99,6 +99,6 @@ export async function save(
|
|||
}
|
||||
|
||||
await core.group('Caching Gradle state', async () => {
|
||||
return new GradleStateCache(userHome, gradleUserHome).save(cacheListener)
|
||||
return new GradleStateCache(userHome, gradleUserHome, cacheConfig).save(cacheListener)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -11,31 +11,26 @@ import fs from 'fs'
|
|||
|
||||
import * as layout from './repository-layout'
|
||||
import {PostActionJobFailure} from './errors'
|
||||
import {
|
||||
DependencyGraphOption,
|
||||
getDependencyGraphContinueOnFailure,
|
||||
getGithubToken,
|
||||
getJobMatrix,
|
||||
getArtifactRetentionDays
|
||||
} from './input-params'
|
||||
import {DependencyGraphConfig, DependencyGraphOption, getGithubToken} from './input-params'
|
||||
|
||||
const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_'
|
||||
|
||||
export async function setup(option: DependencyGraphOption): Promise<void> {
|
||||
export async function setup(config: DependencyGraphConfig): Promise<void> {
|
||||
const option = config.getDependencyGraphOption()
|
||||
if (option === DependencyGraphOption.Disabled) {
|
||||
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'false')
|
||||
return
|
||||
}
|
||||
// Download and submit early, for compatability with dependency review.
|
||||
if (option === DependencyGraphOption.DownloadAndSubmit) {
|
||||
await downloadAndSubmitDependencyGraphs()
|
||||
await downloadAndSubmitDependencyGraphs(config)
|
||||
return
|
||||
}
|
||||
|
||||
core.info('Enabling dependency graph generation')
|
||||
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true')
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', getDependencyGraphContinueOnFailure())
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator())
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', config.getDependencyGraphContinueOnFailure())
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', config.getJobCorrelator())
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId)
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref)
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext())
|
||||
|
@ -58,12 +53,13 @@ function maybeExportVariable(variableName: string, value: unknown): void {
|
|||
}
|
||||
}
|
||||
|
||||
export async function complete(option: DependencyGraphOption): Promise<void> {
|
||||
export async function complete(config: DependencyGraphConfig): Promise<void> {
|
||||
if (isRunningInActEnvironment()) {
|
||||
core.info('Dependency graph upload and submit not supported in the ACT environment.')
|
||||
return
|
||||
}
|
||||
|
||||
const option = config.getDependencyGraphOption()
|
||||
try {
|
||||
switch (option) {
|
||||
case DependencyGraphOption.Disabled:
|
||||
|
@ -75,10 +71,10 @@ export async function complete(option: DependencyGraphOption): Promise<void> {
|
|||
await submitDependencyGraphs(await findGeneratedDependencyGraphFiles())
|
||||
return
|
||||
case DependencyGraphOption.GenerateAndUpload:
|
||||
await uploadDependencyGraphs(await findGeneratedDependencyGraphFiles())
|
||||
await uploadDependencyGraphs(await findGeneratedDependencyGraphFiles(), config)
|
||||
}
|
||||
} catch (e) {
|
||||
warnOrFail(option, e)
|
||||
warnOrFail(config, option, e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +83,7 @@ async function findGeneratedDependencyGraphFiles(): Promise<string[]> {
|
|||
return await findDependencyGraphFiles(workspaceDirectory)
|
||||
}
|
||||
|
||||
async function uploadDependencyGraphs(dependencyGraphFiles: string[]): Promise<void> {
|
||||
async function uploadDependencyGraphs(dependencyGraphFiles: string[], config: DependencyGraphConfig): Promise<void> {
|
||||
const workspaceDirectory = layout.workspaceDirectory()
|
||||
|
||||
const artifactClient = new DefaultArtifactClient()
|
||||
|
@ -96,12 +92,12 @@ async function uploadDependencyGraphs(dependencyGraphFiles: string[]): Promise<v
|
|||
core.info(`Uploading dependency graph file: ${relativePath}`)
|
||||
const artifactName = `${DEPENDENCY_GRAPH_PREFIX}${path.basename(dependencyGraphFile)}`
|
||||
await artifactClient.uploadArtifact(artifactName, [dependencyGraphFile], workspaceDirectory, {
|
||||
retentionDays: getArtifactRetentionDays()
|
||||
retentionDays: config.getArtifactRetentionDays()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadAndSubmitDependencyGraphs(): Promise<void> {
|
||||
async function downloadAndSubmitDependencyGraphs(config: DependencyGraphConfig): Promise<void> {
|
||||
if (isRunningInActEnvironment()) {
|
||||
core.info('Dependency graph download and submit not supported in the ACT environment.')
|
||||
return
|
||||
|
@ -110,7 +106,7 @@ async function downloadAndSubmitDependencyGraphs(): Promise<void> {
|
|||
try {
|
||||
await submitDependencyGraphs(await downloadDependencyGraphs())
|
||||
} catch (e) {
|
||||
warnOrFail(DependencyGraphOption.DownloadAndSubmit, e)
|
||||
warnOrFail(config, DependencyGraphOption.DownloadAndSubmit, e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,8 +188,8 @@ async function findDependencyGraphFiles(dir: string): Promise<string[]> {
|
|||
return graphFiles
|
||||
}
|
||||
|
||||
function warnOrFail(option: String, error: unknown): void {
|
||||
if (!getDependencyGraphContinueOnFailure()) {
|
||||
function warnOrFail(config: DependencyGraphConfig, option: String, error: unknown): void {
|
||||
if (!config.getDependencyGraphContinueOnFailure()) {
|
||||
throw new PostActionJobFailure(error)
|
||||
}
|
||||
|
||||
|
@ -228,32 +224,6 @@ function getShaFromContext(): string {
|
|||
}
|
||||
}
|
||||
|
||||
function getJobCorrelator(): string {
|
||||
return constructJobCorrelator(github.context.workflow, github.context.job, getJobMatrix())
|
||||
}
|
||||
|
||||
export function constructJobCorrelator(workflow: string, jobId: string, matrixJson: string): string {
|
||||
const matrixString = describeMatrix(matrixJson)
|
||||
const label = matrixString ? `${workflow}-${jobId}-${matrixString}` : `${workflow}-${jobId}`
|
||||
return sanitize(label)
|
||||
}
|
||||
|
||||
function describeMatrix(matrixJson: string): string {
|
||||
core.debug(`Got matrix json: ${matrixJson}`)
|
||||
const matrix = JSON.parse(matrixJson)
|
||||
if (matrix) {
|
||||
return Object.values(matrix).join('-')
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
function sanitize(value: string): string {
|
||||
return value
|
||||
.replace(/[^a-zA-Z0-9_-\s]/g, '')
|
||||
.replace(/\s+/g, '_')
|
||||
.toLowerCase()
|
||||
}
|
||||
|
||||
function isRunningInActEnvironment(): boolean {
|
||||
return process.env.ACT !== undefined
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import * as layout from '../repository-layout'
|
|||
import * as dependencyGraph from '../dependency-graph'
|
||||
|
||||
import {parseArgsStringToArgv} from 'string-argv'
|
||||
import {DependencyGraphOption, getDependencyGraphOption} from '../input-params'
|
||||
import {BuildScanConfig, CacheConfig, DependencyGraphConfig, DependencyGraphOption} from '../input-params'
|
||||
|
||||
/**
|
||||
* The main entry point for the action, called by Github Actions for the step.
|
||||
|
@ -15,12 +15,13 @@ import {DependencyGraphOption, getDependencyGraphOption} from '../input-params'
|
|||
export async function run(): Promise<void> {
|
||||
try {
|
||||
// Configure Gradle environment (Gradle User Home)
|
||||
await setupGradle.setup()
|
||||
await setupGradle.setup(new CacheConfig(), new BuildScanConfig())
|
||||
|
||||
// Configure the dependency graph submission
|
||||
await dependencyGraph.setup(getDependencyGraphOption())
|
||||
const config = new DependencyGraphConfig()
|
||||
await dependencyGraph.setup(config)
|
||||
|
||||
if (getDependencyGraphOption() === DependencyGraphOption.DownloadAndSubmit) {
|
||||
if (config.getDependencyGraphOption() === DependencyGraphOption.DownloadAndSubmit) {
|
||||
// No execution to perform
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as core from '@actions/core'
|
|||
import * as setupGradle from '../setup-gradle'
|
||||
import * as dependencyGraph from '../dependency-graph'
|
||||
|
||||
import {getDependencyGraphOption} from '../input-params'
|
||||
import {CacheConfig, DependencyGraphConfig, SummaryConfig} from '../input-params'
|
||||
import {PostActionJobFailure} from '../errors'
|
||||
|
||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
||||
|
@ -15,9 +15,9 @@ process.on('uncaughtException', e => handleFailure(e))
|
|||
*/
|
||||
export async function run(): Promise<void> {
|
||||
try {
|
||||
if (await setupGradle.complete()) {
|
||||
if (await setupGradle.complete(new CacheConfig(), new SummaryConfig())) {
|
||||
// Only submit the dependency graphs once per job
|
||||
await dependencyGraph.complete(getDependencyGraphOption())
|
||||
await dependencyGraph.complete(new DependencyGraphConfig())
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof PostActionJobFailure) {
|
||||
|
|
|
@ -1,54 +1,234 @@
|
|||
import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
import * as cache from '@actions/cache'
|
||||
import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary'
|
||||
|
||||
import {parseArgsStringToArgv} from 'string-argv'
|
||||
|
||||
export function isCacheDisabled(): boolean {
|
||||
return getBooleanInput('cache-disabled')
|
||||
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 function isCacheReadOnly(): boolean {
|
||||
return getBooleanInput('cache-read-only')
|
||||
export enum DependencyGraphOption {
|
||||
Disabled = 'disabled',
|
||||
Generate = 'generate',
|
||||
GenerateAndSubmit = 'generate-and-submit',
|
||||
GenerateAndUpload = 'generate-and-upload',
|
||||
DownloadAndSubmit = 'download-and-submit',
|
||||
Clear = 'clear'
|
||||
}
|
||||
|
||||
export function isCacheWriteOnly(): boolean {
|
||||
return getBooleanInput('cache-write-only')
|
||||
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 function isCacheOverwriteExisting(): boolean {
|
||||
return getBooleanInput('cache-overwrite-existing')
|
||||
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 function isCacheStrictMatch(): boolean {
|
||||
return getBooleanInput('gradle-home-cache-strict-match')
|
||||
export enum JobSummaryOption {
|
||||
Never = 'never',
|
||||
Always = 'always',
|
||||
OnFailure = 'on-failure'
|
||||
}
|
||||
|
||||
export function isCacheDebuggingEnabled(): boolean {
|
||||
return process.env['GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED'] ? true : false
|
||||
}
|
||||
export class BuildScanConfig {
|
||||
getBuildScanPublishEnabled(): boolean {
|
||||
if (!this.verifyTermsOfUseAgreement()) {
|
||||
return false
|
||||
}
|
||||
return getBooleanInput('build-scan-publish') && this.verifyTermsOfUseAgreement()
|
||||
}
|
||||
|
||||
export function isCacheCleanupEnabled(): boolean {
|
||||
return getBooleanInput('gradle-home-cache-cleanup')
|
||||
}
|
||||
getBuildScanTermsOfUseUrl(): string {
|
||||
return this.getTermsOfUseProp('build-scan-terms-of-use-url', 'build-scan-terms-of-service-url')
|
||||
}
|
||||
|
||||
export function getCacheEncryptionKey(): string {
|
||||
return core.getInput('cache-encryption-key')
|
||||
}
|
||||
getBuildScanTermsOfUseAgree(): string {
|
||||
return this.getTermsOfUseProp('build-scan-terms-of-use-agree', 'build-scan-terms-of-service-agree')
|
||||
}
|
||||
|
||||
export function getCacheIncludes(): string[] {
|
||||
return core.getMultilineInput('gradle-home-cache-includes')
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
export function getCacheExcludes(): string[] {
|
||||
return core.getMultilineInput('gradle-home-cache-excludes')
|
||||
}
|
||||
|
||||
export function getBuildRootDirectory(): string {
|
||||
return core.getInput('build-root-directory')
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
return core.getInput(oldPropName)
|
||||
}
|
||||
}
|
||||
|
||||
export function getGradleVersion(): string {
|
||||
return core.getInput('gradle-version')
|
||||
}
|
||||
|
||||
export function getBuildRootDirectory(): string {
|
||||
return core.getInput('build-root-directory')
|
||||
}
|
||||
|
||||
export function getArguments(): string[] {
|
||||
const input = core.getInput('arguments')
|
||||
return parseArgsStringToArgv(input)
|
||||
|
@ -63,85 +243,6 @@ export function getGithubToken(): string {
|
|||
return core.getInput('github-token', {required: true})
|
||||
}
|
||||
|
||||
export function isJobSummaryEnabled(): boolean {
|
||||
return getBooleanInput('generate-job-summary', true)
|
||||
}
|
||||
|
||||
export function getJobSummaryOption(): JobSummaryOption {
|
||||
return parseJobSummaryOption('add-job-summary')
|
||||
}
|
||||
|
||||
export function getPRCommentOption(): JobSummaryOption {
|
||||
return parseJobSummaryOption('add-job-summary-as-pr-comment')
|
||||
}
|
||||
|
||||
export function getBuildScanPublishEnabled(): boolean {
|
||||
return getBooleanInput('build-scan-publish')
|
||||
}
|
||||
|
||||
export function getBuildScanTermsOfUseUrl(): string {
|
||||
return getTermsOfUseProp('build-scan-terms-of-use-url', 'build-scan-terms-of-service-url')
|
||||
}
|
||||
|
||||
export function getBuildScanTermsOfUseAgree(): string {
|
||||
return getTermsOfUseProp('build-scan-terms-of-use-agree', 'build-scan-terms-of-service-agree')
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO @bigdaz: remove the deprecated input property in the next major release of the action
|
||||
*/
|
||||
function getTermsOfUseProp(newPropName: string, oldPropName: string): string {
|
||||
const newProp = core.getInput(newPropName)
|
||||
if (newProp !== '') {
|
||||
return newProp
|
||||
}
|
||||
return core.getInput(oldPropName)
|
||||
}
|
||||
|
||||
function 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 function 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'.`
|
||||
)
|
||||
}
|
||||
|
||||
export function getDependencyGraphContinueOnFailure(): boolean {
|
||||
return getBooleanInput('dependency-graph-continue-on-failure', true)
|
||||
}
|
||||
|
||||
export function 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
|
||||
}
|
||||
|
||||
export function parseNumericInput(paramName: string, paramValue: string, paramDefault: number): number {
|
||||
if (paramValue.length === 0) {
|
||||
return paramDefault
|
||||
|
@ -165,18 +266,3 @@ function getBooleanInput(paramName: string, paramDefault = false): boolean {
|
|||
}
|
||||
throw TypeError(`The value '${paramValue} is not valid for '${paramName}. Valid values are: [true, false]`)
|
||||
}
|
||||
|
||||
export enum DependencyGraphOption {
|
||||
Disabled = 'disabled',
|
||||
Generate = 'generate',
|
||||
GenerateAndSubmit = 'generate-and-submit',
|
||||
GenerateAndUpload = 'generate-and-upload',
|
||||
DownloadAndSubmit = 'download-and-submit',
|
||||
Clear = 'clear'
|
||||
}
|
||||
|
||||
export enum JobSummaryOption {
|
||||
Never = 'never',
|
||||
Always = 'always',
|
||||
OnFailure = 'on-failure'
|
||||
}
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary'
|
||||
import {RequestError} from '@octokit/request-error'
|
||||
|
||||
import * as params from './input-params'
|
||||
import {BuildResult} from './build-results'
|
||||
import {CacheListener, generateCachingReport} from './cache-reporting'
|
||||
import {SummaryConfig, getGithubToken} from './input-params'
|
||||
|
||||
export async function generateJobSummary(buildResults: BuildResult[], cacheListener: CacheListener): Promise<void> {
|
||||
export async function generateJobSummary(
|
||||
buildResults: BuildResult[],
|
||||
cacheListener: CacheListener,
|
||||
config: SummaryConfig
|
||||
): Promise<void> {
|
||||
const summaryTable = renderSummaryTable(buildResults)
|
||||
const cachingReport = generateCachingReport(cacheListener)
|
||||
|
||||
if (shouldGenerateJobSummary(buildResults)) {
|
||||
const hasFailure = buildResults.some(result => result.buildFailed)
|
||||
if (config.shouldGenerateJobSummary(hasFailure)) {
|
||||
core.info('Generating Job Summary')
|
||||
|
||||
core.summary.addRaw(summaryTable)
|
||||
|
@ -25,7 +29,7 @@ export async function generateJobSummary(buildResults: BuildResult[], cacheListe
|
|||
core.info('============================')
|
||||
}
|
||||
|
||||
if (shouldAddPRComment(buildResults)) {
|
||||
if (config.shouldAddPRComment(hasFailure)) {
|
||||
await addPRComment(summaryTable)
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +51,7 @@ async function addPRComment(jobSummary: string): Promise<void> {
|
|||
|
||||
${jobSummary}`
|
||||
|
||||
const github_token = params.getGithubToken()
|
||||
const github_token = getGithubToken()
|
||||
const octokit = github.getOctokit(github_token)
|
||||
try {
|
||||
await octokit.rest.issues.createComment({
|
||||
|
@ -128,36 +132,6 @@ function renderBuildScanBadge(outcomeText: string, outcomeColor: string, targetU
|
|||
return `<a href="${targetUrl}" rel="nofollow" target="_blank">${badgeHtml}</a>`
|
||||
}
|
||||
|
||||
function shouldGenerateJobSummary(buildResults: BuildResult[]): 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 (!params.isJobSummaryEnabled()) {
|
||||
return false
|
||||
}
|
||||
|
||||
return shouldAddJobSummary(params.getJobSummaryOption(), buildResults)
|
||||
}
|
||||
|
||||
function shouldAddPRComment(buildResults: BuildResult[]): boolean {
|
||||
return shouldAddJobSummary(params.getPRCommentOption(), buildResults)
|
||||
}
|
||||
|
||||
function shouldAddJobSummary(option: params.JobSummaryOption, buildResults: BuildResult[]): boolean {
|
||||
switch (option) {
|
||||
case params.JobSummaryOption.Always:
|
||||
return true
|
||||
case params.JobSummaryOption.Never:
|
||||
return false
|
||||
case params.JobSummaryOption.OnFailure:
|
||||
core.info(`Got these build results: ${JSON.stringify(buildResults)}`)
|
||||
return buildResults.some(result => result.buildFailed)
|
||||
}
|
||||
}
|
||||
|
||||
function truncateString(str: string, maxLength: number): string {
|
||||
if (str.length > maxLength) {
|
||||
return `<div title='${str}'>${str.slice(0, maxLength - 1)}…</div>`
|
||||
|
|
|
@ -8,7 +8,8 @@ import * as toolCache from '@actions/tool-cache'
|
|||
|
||||
import * as gradlew from './gradlew'
|
||||
import * as params from './input-params'
|
||||
import {handleCacheFailure, isCacheDisabled, isCacheReadOnly} from './cache-utils'
|
||||
import {handleCacheFailure} from './cache-utils'
|
||||
import {CacheConfig} from './input-params'
|
||||
|
||||
const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'
|
||||
|
||||
|
@ -122,7 +123,9 @@ async function locateGradleAndDownloadIfRequired(versionInfo: GradleVersionInfo)
|
|||
async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo): Promise<string> {
|
||||
const downloadPath = path.join(os.homedir(), `gradle-installations/downloads/gradle-${versionInfo.version}-bin.zip`)
|
||||
|
||||
if (isCacheDisabled()) {
|
||||
// TODO: Convert this to a class and inject config
|
||||
const cacheConfig = new CacheConfig()
|
||||
if (cacheConfig.isCacheDisabled()) {
|
||||
await downloadGradleDistribution(versionInfo, downloadPath)
|
||||
return downloadPath
|
||||
}
|
||||
|
@ -141,7 +144,7 @@ async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo
|
|||
core.info(`Gradle distribution ${versionInfo.version} not found in cache. Will download.`)
|
||||
await downloadGradleDistribution(versionInfo, downloadPath)
|
||||
|
||||
if (!isCacheReadOnly()) {
|
||||
if (!cacheConfig.isCacheReadOnly()) {
|
||||
try {
|
||||
await cache.saveCache([downloadPath], cacheKey)
|
||||
} catch (error) {
|
||||
|
|
|
@ -10,13 +10,14 @@ import * as buildScan from './build-scan'
|
|||
import {loadBuildResults} from './build-results'
|
||||
import {CacheListener} from './cache-reporting'
|
||||
import {DaemonController} from './daemon-controller'
|
||||
import {BuildScanConfig, CacheConfig, SummaryConfig} from './input-params'
|
||||
|
||||
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
|
||||
const USER_HOME = 'USER_HOME'
|
||||
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
|
||||
const CACHE_LISTENER = 'CACHE_LISTENER'
|
||||
|
||||
export async function setup(): Promise<boolean> {
|
||||
export async function setup(cacheConfig: CacheConfig, buildScanConfig: BuildScanConfig): Promise<boolean> {
|
||||
const userHome = await determineUserHome()
|
||||
const gradleUserHome = await determineGradleUserHome()
|
||||
|
||||
|
@ -35,16 +36,16 @@ export async function setup(): Promise<boolean> {
|
|||
core.saveState(GRADLE_USER_HOME, gradleUserHome)
|
||||
|
||||
const cacheListener = new CacheListener()
|
||||
await caches.restore(userHome, gradleUserHome, cacheListener)
|
||||
await caches.restore(userHome, gradleUserHome, cacheListener, cacheConfig)
|
||||
|
||||
core.saveState(CACHE_LISTENER, cacheListener.stringify())
|
||||
|
||||
buildScan.setup()
|
||||
buildScan.setup(buildScanConfig)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
export async function complete(): Promise<boolean> {
|
||||
export async function complete(cacheConfig: CacheConfig, summaryConfig: SummaryConfig): Promise<boolean> {
|
||||
if (!core.getState(GRADLE_SETUP_VAR)) {
|
||||
core.info('Gradle setup post-action only performed for first gradle/actions step in workflow.')
|
||||
return false
|
||||
|
@ -58,9 +59,9 @@ export async function complete(): Promise<boolean> {
|
|||
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
||||
const daemonController = new DaemonController(buildResults)
|
||||
|
||||
await caches.save(userHome, gradleUserHome, cacheListener, daemonController)
|
||||
await caches.save(userHome, gradleUserHome, cacheListener, daemonController, cacheConfig)
|
||||
|
||||
await jobSummary.generateJobSummary(buildResults, cacheListener)
|
||||
await jobSummary.generateJobSummary(buildResults, cacheListener, summaryConfig)
|
||||
|
||||
core.info('Completed post-action step')
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ import * as setupGradle from '../setup-gradle'
|
|||
import * as execution from '../execution'
|
||||
import * as provisioner from '../provision'
|
||||
import * as layout from '../repository-layout'
|
||||
import * as params from '../input-params'
|
||||
import * as dependencyGraph from '../dependency-graph'
|
||||
import {BuildScanConfig, CacheConfig, DependencyGraphConfig, getArguments} from '../input-params'
|
||||
|
||||
/**
|
||||
* The main entry point for the action, called by Github Actions for the step.
|
||||
|
@ -13,16 +13,16 @@ import * as dependencyGraph from '../dependency-graph'
|
|||
export async function run(): Promise<void> {
|
||||
try {
|
||||
// Configure Gradle environment (Gradle User Home)
|
||||
await setupGradle.setup()
|
||||
await setupGradle.setup(new CacheConfig(), new BuildScanConfig())
|
||||
|
||||
// Configure the dependency graph submission
|
||||
await dependencyGraph.setup(params.getDependencyGraphOption())
|
||||
await dependencyGraph.setup(new DependencyGraphConfig())
|
||||
|
||||
// Download and install Gradle if required
|
||||
const executable = await provisioner.provisionGradle()
|
||||
|
||||
// Only execute if arguments have been provided
|
||||
const args: string[] = params.getArguments()
|
||||
const args: string[] = getArguments()
|
||||
if (args.length > 0) {
|
||||
const buildRootDirectory = layout.buildRootDirectory()
|
||||
await execution.executeGradleBuild(executable, buildRootDirectory, args)
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as core from '@actions/core'
|
|||
import * as setupGradle from '../setup-gradle'
|
||||
import * as dependencyGraph from '../dependency-graph'
|
||||
|
||||
import {getDependencyGraphOption} from '../input-params'
|
||||
import {CacheConfig, DependencyGraphConfig, SummaryConfig} from '../input-params'
|
||||
import {PostActionJobFailure} from '../errors'
|
||||
|
||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
||||
|
@ -15,9 +15,9 @@ process.on('uncaughtException', e => handleFailure(e))
|
|||
*/
|
||||
export async function run(): Promise<void> {
|
||||
try {
|
||||
if (await setupGradle.complete()) {
|
||||
if (await setupGradle.complete(new CacheConfig(), new SummaryConfig())) {
|
||||
// Only submit the dependency graphs once per job
|
||||
await dependencyGraph.complete(getDependencyGraphOption())
|
||||
await dependencyGraph.complete(new DependencyGraphConfig())
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof PostActionJobFailure) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {GradleStateCache} from "../../src/cache-base"
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
import {GradleStateCache} from "../../src/cache-base"
|
||||
import {CacheConfig} from "../../src/input-params"
|
||||
|
||||
const testTmp = 'test/jest/tmp'
|
||||
fs.rmSync(testTmp, {recursive: true, force: true})
|
||||
|
@ -11,7 +12,7 @@ describe("--info and --stacktrace", () => {
|
|||
const emptyGradleHome = `${testTmp}/empty-gradle-home`
|
||||
fs.mkdirSync(emptyGradleHome, {recursive: true})
|
||||
|
||||
const stateCache = new GradleStateCache("ignored", emptyGradleHome)
|
||||
const stateCache = new GradleStateCache("ignored", emptyGradleHome, new CacheConfig())
|
||||
stateCache.configureInfoLogLevel()
|
||||
|
||||
expect(fs.readFileSync(path.resolve(emptyGradleHome, "gradle.properties"), 'utf-8'))
|
||||
|
@ -24,7 +25,7 @@ describe("--info and --stacktrace", () => {
|
|||
fs.mkdirSync(existingGradleHome, {recursive: true})
|
||||
fs.writeFileSync(path.resolve(existingGradleHome, "gradle.properties"), "org.gradle.logging.level=debug\n")
|
||||
|
||||
const stateCache = new GradleStateCache("ignored", existingGradleHome)
|
||||
const stateCache = new GradleStateCache("ignored", existingGradleHome, new CacheConfig())
|
||||
stateCache.configureInfoLogLevel()
|
||||
|
||||
expect(fs.readFileSync(path.resolve(existingGradleHome, "gradle.properties"), 'utf-8'))
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
import * as dependencyGraph from '../../src/dependency-graph'
|
||||
import { DependencyGraphConfig } from "../../src/input-params"
|
||||
|
||||
describe('dependency-graph', () => {
|
||||
describe('constructs job correlator', () => {
|
||||
it('removes commas from workflow name', () => {
|
||||
const id = dependencyGraph.constructJobCorrelator('Workflow, with,commas', 'jobid', '{}')
|
||||
const id = DependencyGraphConfig.constructJobCorrelator('Workflow, with,commas', 'jobid', '{}')
|
||||
expect(id).toBe('workflow_withcommas-jobid')
|
||||
})
|
||||
it('removes non word characters', () => {
|
||||
const id = dependencyGraph.constructJobCorrelator('Workflow!_with()characters', 'job-*id', '{"foo": "bar!@#$%^&*("}')
|
||||
const id = DependencyGraphConfig.constructJobCorrelator('Workflow!_with()characters', 'job-*id', '{"foo": "bar!@#$%^&*("}')
|
||||
expect(id).toBe('workflow_withcharacters-job-id-bar')
|
||||
})
|
||||
it('replaces spaces', () => {
|
||||
const id = dependencyGraph.constructJobCorrelator('Workflow !_ with () characters, and spaces', 'job-*id', '{"foo": "bar!@#$%^&*("}')
|
||||
const id = DependencyGraphConfig.constructJobCorrelator('Workflow !_ with () characters, and spaces', 'job-*id', '{"foo": "bar!@#$%^&*("}')
|
||||
expect(id).toBe('workflow___with_characters_and_spaces-job-id-bar')
|
||||
})
|
||||
it('without matrix', () => {
|
||||
const id = dependencyGraph.constructJobCorrelator('workflow', 'jobid', 'null')
|
||||
const id = DependencyGraphConfig.constructJobCorrelator('workflow', 'jobid', 'null')
|
||||
expect(id).toBe('workflow-jobid')
|
||||
})
|
||||
it('with dashes in values', () => {
|
||||
const id = dependencyGraph.constructJobCorrelator('workflow-name', 'job-id', '{"os": "ubuntu-latest"}')
|
||||
const id = DependencyGraphConfig.constructJobCorrelator('workflow-name', 'job-id', '{"os": "ubuntu-latest"}')
|
||||
expect(id).toBe('workflow-name-job-id-ubuntu-latest')
|
||||
})
|
||||
it('with single matrix value', () => {
|
||||
const id = dependencyGraph.constructJobCorrelator('workflow', 'jobid', '{"os": "windows"}')
|
||||
const id = DependencyGraphConfig.constructJobCorrelator('workflow', 'jobid', '{"os": "windows"}')
|
||||
expect(id).toBe('workflow-jobid-windows')
|
||||
})
|
||||
it('with composite matrix value', () => {
|
||||
const id = dependencyGraph.constructJobCorrelator('workflow', 'jobid', '{"os": "windows", "java-version": "21.1", "other": "Value, with COMMA"}')
|
||||
const id = DependencyGraphConfig.constructJobCorrelator('workflow', 'jobid', '{"os": "windows", "java-version": "21.1", "other": "Value, with COMMA"}')
|
||||
expect(id).toBe('workflow-jobid-windows-211-value_with_comma')
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue