mirror of
https://hub.gitmirror.com/https://github.com/gradle/actions.git
synced 2025-10-28 16:40:02 +08: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
@ -1,30 +1,18 @@
|
|||||||
import * as core from '@actions/core'
|
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_INJECTION_INIT_SCRIPT_NAME', 'gradle-actions.inject-develocity.init.gradle')
|
||||||
maybeExportVariable('DEVELOCITY_AUTO_INJECTION_CUSTOM_VALUE', 'gradle-actions')
|
maybeExportVariable('DEVELOCITY_AUTO_INJECTION_CUSTOM_VALUE', 'gradle-actions')
|
||||||
if (getBuildScanPublishEnabled() && verifyTermsOfUseAgreement()) {
|
if (config.getBuildScanPublishEnabled()) {
|
||||||
maybeExportVariable('DEVELOCITY_INJECTION_ENABLED', 'true')
|
maybeExportVariable('DEVELOCITY_INJECTION_ENABLED', 'true')
|
||||||
maybeExportVariable('DEVELOCITY_PLUGIN_VERSION', '3.17')
|
maybeExportVariable('DEVELOCITY_PLUGIN_VERSION', '3.17')
|
||||||
maybeExportVariable('DEVELOCITY_CCUD_PLUGIN_VERSION', '1.13')
|
maybeExportVariable('DEVELOCITY_CCUD_PLUGIN_VERSION', '1.13')
|
||||||
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_URL', getBuildScanTermsOfUseUrl())
|
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_URL', config.getBuildScanTermsOfUseUrl())
|
||||||
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_AGREE', getBuildScanTermsOfUseAgree())
|
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 {
|
function maybeExportVariable(variableName: string, value: unknown): void {
|
||||||
if (!process.env[variableName]) {
|
if (!process.env[variableName]) {
|
||||||
core.exportVariable(variableName, value)
|
core.exportVariable(variableName, value)
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import * as glob from '@actions/glob'
|
|||||||
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import * as params from './input-params'
|
import {CacheConfig} from './input-params'
|
||||||
import {CacheListener} from './cache-reporting'
|
import {CacheListener} from './cache-reporting'
|
||||||
import {saveCache, restoreCache, cacheDebug, isCacheDebuggingEnabled, tryDelete, generateCacheKey} from './cache-utils'
|
import {saveCache, restoreCache, cacheDebug, isCacheDebuggingEnabled, tryDelete, generateCacheKey} from './cache-utils'
|
||||||
import {GradleHomeEntryExtractor, ConfigurationCacheEntryExtractor} from './cache-extract-entries'
|
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 const META_FILE_DIR = '.setup-gradle'
|
||||||
|
|
||||||
export class GradleStateCache {
|
export class GradleStateCache {
|
||||||
|
private cacheConfig: CacheConfig
|
||||||
private cacheName: string
|
private cacheName: string
|
||||||
private cacheDescription: string
|
private cacheDescription: string
|
||||||
|
|
||||||
protected readonly userHome: string
|
protected readonly userHome: string
|
||||||
protected readonly gradleUserHome: string
|
protected readonly gradleUserHome: string
|
||||||
|
|
||||||
constructor(userHome: string, gradleUserHome: string) {
|
constructor(userHome: string, gradleUserHome: string, cacheConfig: CacheConfig) {
|
||||||
this.userHome = userHome
|
this.userHome = userHome
|
||||||
this.gradleUserHome = gradleUserHome
|
this.gradleUserHome = gradleUserHome
|
||||||
|
this.cacheConfig = cacheConfig
|
||||||
this.cacheName = 'gradle'
|
this.cacheName = 'gradle'
|
||||||
this.cacheDescription = 'Gradle User Home'
|
this.cacheDescription = 'Gradle User Home'
|
||||||
}
|
}
|
||||||
@ -31,7 +33,7 @@ export class GradleStateCache {
|
|||||||
this.initializeGradleUserHome()
|
this.initializeGradleUserHome()
|
||||||
|
|
||||||
// Export the GRADLE_ENCRYPTION_KEY variable if provided
|
// Export the GRADLE_ENCRYPTION_KEY variable if provided
|
||||||
const encryptionKey = params.getCacheEncryptionKey()
|
const encryptionKey = this.cacheConfig.getCacheEncryptionKey()
|
||||||
if (encryptionKey) {
|
if (encryptionKey) {
|
||||||
core.exportVariable('GRADLE_ENCRYPTION_KEY', encryptionKey)
|
core.exportVariable('GRADLE_ENCRYPTION_KEY', encryptionKey)
|
||||||
}
|
}
|
||||||
@ -52,7 +54,7 @@ export class GradleStateCache {
|
|||||||
async restore(listener: CacheListener): Promise<void> {
|
async restore(listener: CacheListener): Promise<void> {
|
||||||
const entryListener = listener.entry(this.cacheDescription)
|
const entryListener = listener.entry(this.cacheDescription)
|
||||||
|
|
||||||
const cacheKey = generateCacheKey(this.cacheName)
|
const cacheKey = generateCacheKey(this.cacheName, this.cacheConfig)
|
||||||
|
|
||||||
cacheDebug(
|
cacheDebug(
|
||||||
`Requesting ${this.cacheDescription} with
|
`Requesting ${this.cacheDescription} with
|
||||||
@ -82,8 +84,8 @@ export class GradleStateCache {
|
|||||||
*/
|
*/
|
||||||
async afterRestore(listener: CacheListener): Promise<void> {
|
async afterRestore(listener: CacheListener): Promise<void> {
|
||||||
await this.debugReportGradleUserHomeSize('as restored from cache')
|
await this.debugReportGradleUserHomeSize('as restored from cache')
|
||||||
await new GradleHomeEntryExtractor(this.gradleUserHome).restore(listener)
|
await new GradleHomeEntryExtractor(this.gradleUserHome, this.cacheConfig).restore(listener)
|
||||||
await new ConfigurationCacheEntryExtractor(this.gradleUserHome).restore(listener)
|
await new ConfigurationCacheEntryExtractor(this.gradleUserHome, this.cacheConfig).restore(listener)
|
||||||
await this.debugReportGradleUserHomeSize('after restoring common artifacts')
|
await this.debugReportGradleUserHomeSize('after restoring common artifacts')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +97,7 @@ export class GradleStateCache {
|
|||||||
* it is saved with the exact key.
|
* it is saved with the exact key.
|
||||||
*/
|
*/
|
||||||
async save(listener: CacheListener): Promise<void> {
|
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 restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY)
|
||||||
const gradleHomeEntryListener = listener.entry(this.cacheDescription)
|
const gradleHomeEntryListener = listener.entry(this.cacheDescription)
|
||||||
|
|
||||||
@ -133,8 +135,8 @@ export class GradleStateCache {
|
|||||||
await this.debugReportGradleUserHomeSize('before saving common artifacts')
|
await this.debugReportGradleUserHomeSize('before saving common artifacts')
|
||||||
await this.deleteExcludedPaths()
|
await this.deleteExcludedPaths()
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
new GradleHomeEntryExtractor(this.gradleUserHome).extract(listener),
|
new GradleHomeEntryExtractor(this.gradleUserHome, this.cacheConfig).extract(listener),
|
||||||
new ConfigurationCacheEntryExtractor(this.gradleUserHome).extract(listener)
|
new ConfigurationCacheEntryExtractor(this.gradleUserHome, this.cacheConfig).extract(listener)
|
||||||
])
|
])
|
||||||
await this.debugReportGradleUserHomeSize(
|
await this.debugReportGradleUserHomeSize(
|
||||||
"after extracting common artifacts (only 'caches' and 'notifications' will be stored)"
|
"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.
|
* Delete any file paths that are excluded by the `gradle-home-cache-excludes` parameter.
|
||||||
*/
|
*/
|
||||||
private async deleteExcludedPaths(): Promise<void> {
|
private async deleteExcludedPaths(): Promise<void> {
|
||||||
const rawPaths: string[] = params.getCacheExcludes()
|
const rawPaths: string[] = this.cacheConfig.getCacheExcludes()
|
||||||
rawPaths.push('caches/*/cc-keystore')
|
rawPaths.push('caches/*/cc-keystore')
|
||||||
const resolvedPaths = rawPaths.map(x => path.resolve(this.gradleUserHome, x))
|
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.
|
* but this can be overridden by the `gradle-home-cache-includes` parameter.
|
||||||
*/
|
*/
|
||||||
protected getCachePath(): string[] {
|
protected getCachePath(): string[] {
|
||||||
const rawPaths: string[] = params.getCacheIncludes()
|
const rawPaths: string[] = this.cacheConfig.getCacheIncludes()
|
||||||
rawPaths.push(META_FILE_DIR)
|
rawPaths.push(META_FILE_DIR)
|
||||||
const resolvedPaths = rawPaths.map(x => this.resolveCachePath(x))
|
const resolvedPaths = rawPaths.map(x => this.resolveCachePath(x))
|
||||||
cacheDebug(`Using cache paths: ${resolvedPaths}`)
|
cacheDebug(`Using cache paths: ${resolvedPaths}`)
|
||||||
|
|||||||
@ -4,12 +4,19 @@ import * as core from '@actions/core'
|
|||||||
import * as glob from '@actions/glob'
|
import * as glob from '@actions/glob'
|
||||||
import * as semver from 'semver'
|
import * as semver from 'semver'
|
||||||
|
|
||||||
import * as params from './input-params'
|
|
||||||
|
|
||||||
import {META_FILE_DIR} from './cache-base'
|
import {META_FILE_DIR} from './cache-base'
|
||||||
import {CacheEntryListener, CacheListener} from './cache-reporting'
|
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 {BuildResult, loadBuildResults} from './build-results'
|
||||||
|
import {CacheConfig} from './input-params'
|
||||||
|
|
||||||
const SKIP_RESTORE_VAR = 'GRADLE_BUILD_ACTION_SKIP_RESTORE'
|
const SKIP_RESTORE_VAR = 'GRADLE_BUILD_ACTION_SKIP_RESTORE'
|
||||||
|
|
||||||
@ -80,12 +87,14 @@ class ExtractedCacheEntryDefinition {
|
|||||||
* for more efficient storage.
|
* for more efficient storage.
|
||||||
*/
|
*/
|
||||||
abstract class AbstractEntryExtractor {
|
abstract class AbstractEntryExtractor {
|
||||||
|
protected readonly cacheConfig: CacheConfig
|
||||||
protected readonly gradleUserHome: string
|
protected readonly gradleUserHome: string
|
||||||
private extractorName: string
|
private extractorName: string
|
||||||
|
|
||||||
constructor(gradleUserHome: string, extractorName: string) {
|
constructor(gradleUserHome: string, extractorName: string, cacheConfig: CacheConfig) {
|
||||||
this.gradleUserHome = gradleUserHome
|
this.gradleUserHome = gradleUserHome
|
||||||
this.extractorName = extractorName
|
this.extractorName = extractorName
|
||||||
|
this.cacheConfig = cacheConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -261,7 +270,7 @@ abstract class AbstractEntryExtractor {
|
|||||||
|
|
||||||
// Run actions sequentially if debugging is enabled
|
// Run actions sequentially if debugging is enabled
|
||||||
private async awaitForDebugging(p: Promise<ExtractedCacheEntry>): Promise<ExtractedCacheEntry> {
|
private async awaitForDebugging(p: Promise<ExtractedCacheEntry>): Promise<ExtractedCacheEntry> {
|
||||||
if (params.isCacheDebuggingEnabled()) {
|
if (isCacheDebuggingEnabled()) {
|
||||||
await p
|
await p
|
||||||
}
|
}
|
||||||
return p
|
return p
|
||||||
@ -306,8 +315,8 @@ abstract class AbstractEntryExtractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class GradleHomeEntryExtractor extends AbstractEntryExtractor {
|
export class GradleHomeEntryExtractor extends AbstractEntryExtractor {
|
||||||
constructor(gradleUserHome: string) {
|
constructor(gradleUserHome: string, cacheConfig: CacheConfig) {
|
||||||
super(gradleUserHome, 'gradle-home')
|
super(gradleUserHome, 'gradle-home', cacheConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
async extract(listener: CacheListener): Promise<void> {
|
async extract(listener: CacheListener): Promise<void> {
|
||||||
@ -363,8 +372,8 @@ export class GradleHomeEntryExtractor extends AbstractEntryExtractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
export class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
||||||
constructor(gradleUserHome: string) {
|
constructor(gradleUserHome: string, cacheConfig: CacheConfig) {
|
||||||
super(gradleUserHome, 'configuration-cache')
|
super(gradleUserHome, 'configuration-cache', cacheConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -377,7 +386,7 @@ export class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!params.getCacheEncryptionKey()) {
|
if (!this.cacheConfig.getCacheEncryptionKey()) {
|
||||||
this.markNotRestored(listener, 'Encryption Key was not provided')
|
this.markNotRestored(listener, 'Encryption Key was not provided')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -399,7 +408,7 @@ export class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async extract(listener: CacheListener): Promise<void> {
|
async extract(listener: CacheListener): Promise<void> {
|
||||||
if (!params.getCacheEncryptionKey()) {
|
if (!this.cacheConfig.getCacheEncryptionKey()) {
|
||||||
const cacheEntryDefinitions = this.getExtractedCacheEntryDefinitions()
|
const cacheEntryDefinitions = this.getExtractedCacheEntryDefinitions()
|
||||||
if (cacheEntryDefinitions.length > 0) {
|
if (cacheEntryDefinitions.length > 0) {
|
||||||
core.info('Not saving configuration-cache state, as no encryption key was provided')
|
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 path from 'path'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
|
|
||||||
import * as params from './input-params'
|
|
||||||
|
|
||||||
import {CacheEntryListener} from './cache-reporting'
|
import {CacheEntryListener} from './cache-reporting'
|
||||||
|
import {CacheConfig, getJobMatrix} from './input-params'
|
||||||
|
|
||||||
const CACHE_PROTOCOL_VERSION = 'v9-'
|
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_VAR = 'SEGMENT_DOWNLOAD_TIMEOUT_MINS'
|
||||||
const SEGMENT_DOWNLOAD_TIMEOUT_DEFAULT = 10 * 60 * 1000 // 10 minutes
|
const SEGMENT_DOWNLOAD_TIMEOUT_DEFAULT = 10 * 60 * 1000 // 10 minutes
|
||||||
|
|
||||||
export function isCacheDisabled(): boolean {
|
export function isCacheDebuggingEnabled(): boolean {
|
||||||
if (!cache.isFeatureAvailable()) {
|
if (core.isDebug()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return params.isCacheDisabled()
|
return process.env['GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED'] ? true : false
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,7 +59,7 @@ export class CacheKey {
|
|||||||
* - Any previous key for this Job (any matrix)
|
* - Any previous key for this Job (any matrix)
|
||||||
* - Any previous key for this cache on the current OS
|
* - 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}`
|
const cacheKeyBase = `${getCacheKeyPrefix()}${CACHE_PROTOCOL_VERSION}${cacheName}`
|
||||||
|
|
||||||
// At the most general level, share caches for all executions on the same OS
|
// 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
|
// Exact match on Git SHA
|
||||||
const cacheKey = `${cacheKeyForJobContext}-${getCacheKeyJobExecution()}`
|
const cacheKey = `${cacheKeyForJobContext}-${getCacheKeyJobExecution()}`
|
||||||
|
|
||||||
if (params.isCacheStrictMatch()) {
|
if (config.isCacheStrictMatch()) {
|
||||||
return new CacheKey(cacheKey, [cacheKeyForJobContext])
|
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
|
// 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.
|
// 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 workflowName = github.context.workflow
|
||||||
const workflowJobContext = params.getJobMatrix()
|
const workflowJobContext = getJobMatrix()
|
||||||
return hashStrings([workflowName, workflowJobContext])
|
return hashStrings([workflowName, workflowJobContext])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,19 +1,18 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import {
|
|
||||||
isCacheCleanupEnabled,
|
|
||||||
isCacheDisabled,
|
|
||||||
isCacheReadOnly,
|
|
||||||
isCacheWriteOnly,
|
|
||||||
isCacheOverwriteExisting
|
|
||||||
} from './cache-utils'
|
|
||||||
import {CacheListener} from './cache-reporting'
|
import {CacheListener} from './cache-reporting'
|
||||||
import {DaemonController} from './daemon-controller'
|
import {DaemonController} from './daemon-controller'
|
||||||
import {GradleStateCache} from './cache-base'
|
import {GradleStateCache} from './cache-base'
|
||||||
import {CacheCleaner} from './cache-cleaner'
|
import {CacheCleaner} from './cache-cleaner'
|
||||||
|
import {CacheConfig} from './input-params'
|
||||||
|
|
||||||
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'
|
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.
|
// Bypass restore cache on all but first action step in workflow.
|
||||||
if (process.env[CACHE_RESTORED_VAR]) {
|
if (process.env[CACHE_RESTORED_VAR]) {
|
||||||
core.info('Cache only restored on first action step.')
|
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)
|
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.')
|
core.info('Cache is disabled: will not restore state from previous builds.')
|
||||||
// Initialize the Gradle User Home even when caching is disabled.
|
// Initialize the Gradle User Home even when caching is disabled.
|
||||||
gradleStateCache.init()
|
gradleStateCache.init()
|
||||||
@ -32,7 +31,7 @@ export async function restore(userHome: string, gradleUserHome: string, cacheLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gradleStateCache.cacheOutputExists()) {
|
if (gradleStateCache.cacheOutputExists()) {
|
||||||
if (!isCacheOverwriteExisting()) {
|
if (!cacheConfig.isCacheOverwriteExisting()) {
|
||||||
core.info('Gradle User Home already exists: will not restore from cache.')
|
core.info('Gradle User Home already exists: will not restore from cache.')
|
||||||
// Initialize pre-existing Gradle User Home.
|
// Initialize pre-existing Gradle User Home.
|
||||||
gradleStateCache.init()
|
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.
|
// Mark the state as restored so that post-action will perform save.
|
||||||
core.saveState(CACHE_RESTORED_VAR, true)
|
core.saveState(CACHE_RESTORED_VAR, true)
|
||||||
|
|
||||||
if (isCacheWriteOnly()) {
|
if (cacheConfig.isCacheWriteOnly()) {
|
||||||
core.info('Cache is write-only: will not restore from cache.')
|
core.info('Cache is write-only: will not restore from cache.')
|
||||||
cacheListener.cacheWriteOnly = true
|
cacheListener.cacheWriteOnly = true
|
||||||
return
|
return
|
||||||
@ -57,7 +56,7 @@ export async function restore(userHome: string, gradleUserHome: string, cacheLis
|
|||||||
await gradleStateCache.restore(cacheListener)
|
await gradleStateCache.restore(cacheListener)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isCacheCleanupEnabled() && !isCacheReadOnly()) {
|
if (cacheConfig.isCacheCleanupEnabled()) {
|
||||||
core.info('Preparing cache for cleanup.')
|
core.info('Preparing cache for cleanup.')
|
||||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||||
await cacheCleaner.prepare()
|
await cacheCleaner.prepare()
|
||||||
@ -68,9 +67,10 @@ export async function save(
|
|||||||
userHome: string,
|
userHome: string,
|
||||||
gradleUserHome: string,
|
gradleUserHome: string,
|
||||||
cacheListener: CacheListener,
|
cacheListener: CacheListener,
|
||||||
daemonController: DaemonController
|
daemonController: DaemonController,
|
||||||
|
cacheConfig: CacheConfig
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (isCacheDisabled()) {
|
if (cacheConfig.isCacheDisabled()) {
|
||||||
core.info('Cache is disabled: will not save state for later builds.')
|
core.info('Cache is disabled: will not save state for later builds.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ export async function save(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCacheReadOnly()) {
|
if (cacheConfig.isCacheReadOnly()) {
|
||||||
core.info('Cache is read-only: will not save state for use in subsequent builds.')
|
core.info('Cache is read-only: will not save state for use in subsequent builds.')
|
||||||
cacheListener.cacheReadOnly = true
|
cacheListener.cacheReadOnly = true
|
||||||
return
|
return
|
||||||
@ -88,7 +88,7 @@ export async function save(
|
|||||||
|
|
||||||
await daemonController.stopAllDaemons()
|
await daemonController.stopAllDaemons()
|
||||||
|
|
||||||
if (isCacheCleanupEnabled()) {
|
if (cacheConfig.isCacheCleanupEnabled()) {
|
||||||
core.info('Forcing cache cleanup.')
|
core.info('Forcing cache cleanup.')
|
||||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||||
try {
|
try {
|
||||||
@ -99,6 +99,6 @@ export async function save(
|
|||||||
}
|
}
|
||||||
|
|
||||||
await core.group('Caching Gradle state', async () => {
|
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 * as layout from './repository-layout'
|
||||||
import {PostActionJobFailure} from './errors'
|
import {PostActionJobFailure} from './errors'
|
||||||
import {
|
import {DependencyGraphConfig, DependencyGraphOption, getGithubToken} from './input-params'
|
||||||
DependencyGraphOption,
|
|
||||||
getDependencyGraphContinueOnFailure,
|
|
||||||
getGithubToken,
|
|
||||||
getJobMatrix,
|
|
||||||
getArtifactRetentionDays
|
|
||||||
} from './input-params'
|
|
||||||
|
|
||||||
const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_'
|
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) {
|
if (option === DependencyGraphOption.Disabled) {
|
||||||
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'false')
|
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'false')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Download and submit early, for compatability with dependency review.
|
// Download and submit early, for compatability with dependency review.
|
||||||
if (option === DependencyGraphOption.DownloadAndSubmit) {
|
if (option === DependencyGraphOption.DownloadAndSubmit) {
|
||||||
await downloadAndSubmitDependencyGraphs()
|
await downloadAndSubmitDependencyGraphs(config)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
core.info('Enabling dependency graph generation')
|
core.info('Enabling dependency graph generation')
|
||||||
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true')
|
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true')
|
||||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', getDependencyGraphContinueOnFailure())
|
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', config.getDependencyGraphContinueOnFailure())
|
||||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator())
|
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', config.getJobCorrelator())
|
||||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId)
|
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId)
|
||||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref)
|
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref)
|
||||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext())
|
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()) {
|
if (isRunningInActEnvironment()) {
|
||||||
core.info('Dependency graph upload and submit not supported in the ACT environment.')
|
core.info('Dependency graph upload and submit not supported in the ACT environment.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const option = config.getDependencyGraphOption()
|
||||||
try {
|
try {
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case DependencyGraphOption.Disabled:
|
case DependencyGraphOption.Disabled:
|
||||||
@ -75,10 +71,10 @@ export async function complete(option: DependencyGraphOption): Promise<void> {
|
|||||||
await submitDependencyGraphs(await findGeneratedDependencyGraphFiles())
|
await submitDependencyGraphs(await findGeneratedDependencyGraphFiles())
|
||||||
return
|
return
|
||||||
case DependencyGraphOption.GenerateAndUpload:
|
case DependencyGraphOption.GenerateAndUpload:
|
||||||
await uploadDependencyGraphs(await findGeneratedDependencyGraphFiles())
|
await uploadDependencyGraphs(await findGeneratedDependencyGraphFiles(), config)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
warnOrFail(option, e)
|
warnOrFail(config, option, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +83,7 @@ async function findGeneratedDependencyGraphFiles(): Promise<string[]> {
|
|||||||
return await findDependencyGraphFiles(workspaceDirectory)
|
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 workspaceDirectory = layout.workspaceDirectory()
|
||||||
|
|
||||||
const artifactClient = new DefaultArtifactClient()
|
const artifactClient = new DefaultArtifactClient()
|
||||||
@ -96,12 +92,12 @@ async function uploadDependencyGraphs(dependencyGraphFiles: string[]): Promise<v
|
|||||||
core.info(`Uploading dependency graph file: ${relativePath}`)
|
core.info(`Uploading dependency graph file: ${relativePath}`)
|
||||||
const artifactName = `${DEPENDENCY_GRAPH_PREFIX}${path.basename(dependencyGraphFile)}`
|
const artifactName = `${DEPENDENCY_GRAPH_PREFIX}${path.basename(dependencyGraphFile)}`
|
||||||
await artifactClient.uploadArtifact(artifactName, [dependencyGraphFile], workspaceDirectory, {
|
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()) {
|
if (isRunningInActEnvironment()) {
|
||||||
core.info('Dependency graph download and submit not supported in the ACT environment.')
|
core.info('Dependency graph download and submit not supported in the ACT environment.')
|
||||||
return
|
return
|
||||||
@ -110,7 +106,7 @@ async function downloadAndSubmitDependencyGraphs(): Promise<void> {
|
|||||||
try {
|
try {
|
||||||
await submitDependencyGraphs(await downloadDependencyGraphs())
|
await submitDependencyGraphs(await downloadDependencyGraphs())
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
warnOrFail(DependencyGraphOption.DownloadAndSubmit, e)
|
warnOrFail(config, DependencyGraphOption.DownloadAndSubmit, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,8 +188,8 @@ async function findDependencyGraphFiles(dir: string): Promise<string[]> {
|
|||||||
return graphFiles
|
return graphFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
function warnOrFail(option: String, error: unknown): void {
|
function warnOrFail(config: DependencyGraphConfig, option: String, error: unknown): void {
|
||||||
if (!getDependencyGraphContinueOnFailure()) {
|
if (!config.getDependencyGraphContinueOnFailure()) {
|
||||||
throw new PostActionJobFailure(error)
|
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 {
|
function isRunningInActEnvironment(): boolean {
|
||||||
return process.env.ACT !== undefined
|
return process.env.ACT !== undefined
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import * as layout from '../repository-layout'
|
|||||||
import * as dependencyGraph from '../dependency-graph'
|
import * as dependencyGraph from '../dependency-graph'
|
||||||
|
|
||||||
import {parseArgsStringToArgv} from 'string-argv'
|
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.
|
* 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> {
|
export async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// Configure Gradle environment (Gradle User Home)
|
// Configure Gradle environment (Gradle User Home)
|
||||||
await setupGradle.setup()
|
await setupGradle.setup(new CacheConfig(), new BuildScanConfig())
|
||||||
|
|
||||||
// Configure the dependency graph submission
|
// 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
|
// No execution to perform
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import * as core from '@actions/core'
|
|||||||
import * as setupGradle from '../setup-gradle'
|
import * as setupGradle from '../setup-gradle'
|
||||||
import * as dependencyGraph from '../dependency-graph'
|
import * as dependencyGraph from '../dependency-graph'
|
||||||
|
|
||||||
import {getDependencyGraphOption} from '../input-params'
|
import {CacheConfig, DependencyGraphConfig, SummaryConfig} from '../input-params'
|
||||||
import {PostActionJobFailure} from '../errors'
|
import {PostActionJobFailure} from '../errors'
|
||||||
|
|
||||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
// 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> {
|
export async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
if (await setupGradle.complete()) {
|
if (await setupGradle.complete(new CacheConfig(), new SummaryConfig())) {
|
||||||
// Only submit the dependency graphs once per job
|
// Only submit the dependency graphs once per job
|
||||||
await dependencyGraph.complete(getDependencyGraphOption())
|
await dependencyGraph.complete(new DependencyGraphConfig())
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof PostActionJobFailure) {
|
if (error instanceof PostActionJobFailure) {
|
||||||
|
|||||||
@ -1,117 +1,12 @@
|
|||||||
import * as core from '@actions/core'
|
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'
|
import {parseArgsStringToArgv} from 'string-argv'
|
||||||
|
|
||||||
export function isCacheDisabled(): boolean {
|
export class DependencyGraphConfig {
|
||||||
return getBooleanInput('cache-disabled')
|
getDependencyGraphOption(): DependencyGraphOption {
|
||||||
}
|
|
||||||
|
|
||||||
export function isCacheReadOnly(): boolean {
|
|
||||||
return getBooleanInput('cache-read-only')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isCacheWriteOnly(): boolean {
|
|
||||||
return getBooleanInput('cache-write-only')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isCacheOverwriteExisting(): boolean {
|
|
||||||
return getBooleanInput('cache-overwrite-existing')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isCacheStrictMatch(): boolean {
|
|
||||||
return getBooleanInput('gradle-home-cache-strict-match')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isCacheDebuggingEnabled(): boolean {
|
|
||||||
return process.env['GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED'] ? true : false
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isCacheCleanupEnabled(): boolean {
|
|
||||||
return getBooleanInput('gradle-home-cache-cleanup')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCacheEncryptionKey(): string {
|
|
||||||
return core.getInput('cache-encryption-key')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCacheIncludes(): string[] {
|
|
||||||
return core.getMultilineInput('gradle-home-cache-includes')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCacheExcludes(): string[] {
|
|
||||||
return core.getMultilineInput('gradle-home-cache-excludes')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getBuildRootDirectory(): string {
|
|
||||||
return core.getInput('build-root-directory')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getGradleVersion(): string {
|
|
||||||
return core.getInput('gradle-version')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getArguments(): string[] {
|
|
||||||
const input = core.getInput('arguments')
|
|
||||||
return parseArgsStringToArgv(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 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')
|
const val = core.getInput('dependency-graph')
|
||||||
switch (val.toLowerCase().trim()) {
|
switch (val.toLowerCase().trim()) {
|
||||||
case 'disabled':
|
case 'disabled':
|
||||||
@ -130,16 +25,222 @@ export function getDependencyGraphOption(): DependencyGraphOption {
|
|||||||
throw TypeError(
|
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'.`
|
`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 {
|
getDependencyGraphContinueOnFailure(): boolean {
|
||||||
return getBooleanInput('dependency-graph-continue-on-failure', true)
|
return getBooleanInput('dependency-graph-continue-on-failure', true)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getArtifactRetentionDays(): number {
|
getArtifactRetentionDays(): number {
|
||||||
const val = core.getInput('artifact-retention-days')
|
const val = core.getInput('artifact-retention-days')
|
||||||
return parseNumericInput('artifact-retention-days', val, 0)
|
return parseNumericInput('artifact-retention-days', val, 0)
|
||||||
// Zero indicates that the default repository settings should be used
|
// 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 {
|
||||||
|
if (!this.verifyTermsOfUseAgreement()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 parseNumericInput(paramName: string, paramValue: string, paramDefault: number): number {
|
export function parseNumericInput(paramName: string, paramValue: string, paramDefault: number): number {
|
||||||
@ -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]`)
|
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 core from '@actions/core'
|
||||||
import * as github from '@actions/github'
|
import * as github from '@actions/github'
|
||||||
import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary'
|
|
||||||
import {RequestError} from '@octokit/request-error'
|
import {RequestError} from '@octokit/request-error'
|
||||||
|
|
||||||
import * as params from './input-params'
|
|
||||||
import {BuildResult} from './build-results'
|
import {BuildResult} from './build-results'
|
||||||
import {CacheListener, generateCachingReport} from './cache-reporting'
|
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 summaryTable = renderSummaryTable(buildResults)
|
||||||
const cachingReport = generateCachingReport(cacheListener)
|
const cachingReport = generateCachingReport(cacheListener)
|
||||||
|
|
||||||
if (shouldGenerateJobSummary(buildResults)) {
|
const hasFailure = buildResults.some(result => result.buildFailed)
|
||||||
|
if (config.shouldGenerateJobSummary(hasFailure)) {
|
||||||
core.info('Generating Job Summary')
|
core.info('Generating Job Summary')
|
||||||
|
|
||||||
core.summary.addRaw(summaryTable)
|
core.summary.addRaw(summaryTable)
|
||||||
@ -25,7 +29,7 @@ export async function generateJobSummary(buildResults: BuildResult[], cacheListe
|
|||||||
core.info('============================')
|
core.info('============================')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldAddPRComment(buildResults)) {
|
if (config.shouldAddPRComment(hasFailure)) {
|
||||||
await addPRComment(summaryTable)
|
await addPRComment(summaryTable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,7 +51,7 @@ async function addPRComment(jobSummary: string): Promise<void> {
|
|||||||
|
|
||||||
${jobSummary}`
|
${jobSummary}`
|
||||||
|
|
||||||
const github_token = params.getGithubToken()
|
const github_token = getGithubToken()
|
||||||
const octokit = github.getOctokit(github_token)
|
const octokit = github.getOctokit(github_token)
|
||||||
try {
|
try {
|
||||||
await octokit.rest.issues.createComment({
|
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>`
|
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 {
|
function truncateString(str: string, maxLength: number): string {
|
||||||
if (str.length > maxLength) {
|
if (str.length > maxLength) {
|
||||||
return `<div title='${str}'>${str.slice(0, maxLength - 1)}…</div>`
|
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 gradlew from './gradlew'
|
||||||
import * as params from './input-params'
|
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'
|
const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'
|
||||||
|
|
||||||
@ -122,7 +123,9 @@ async function locateGradleAndDownloadIfRequired(versionInfo: GradleVersionInfo)
|
|||||||
async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo): Promise<string> {
|
async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo): Promise<string> {
|
||||||
const downloadPath = path.join(os.homedir(), `gradle-installations/downloads/gradle-${versionInfo.version}-bin.zip`)
|
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)
|
await downloadGradleDistribution(versionInfo, downloadPath)
|
||||||
return downloadPath
|
return downloadPath
|
||||||
}
|
}
|
||||||
@ -141,7 +144,7 @@ async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo
|
|||||||
core.info(`Gradle distribution ${versionInfo.version} not found in cache. Will download.`)
|
core.info(`Gradle distribution ${versionInfo.version} not found in cache. Will download.`)
|
||||||
await downloadGradleDistribution(versionInfo, downloadPath)
|
await downloadGradleDistribution(versionInfo, downloadPath)
|
||||||
|
|
||||||
if (!isCacheReadOnly()) {
|
if (!cacheConfig.isCacheReadOnly()) {
|
||||||
try {
|
try {
|
||||||
await cache.saveCache([downloadPath], cacheKey)
|
await cache.saveCache([downloadPath], cacheKey)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -10,13 +10,14 @@ import * as buildScan from './build-scan'
|
|||||||
import {loadBuildResults} from './build-results'
|
import {loadBuildResults} from './build-results'
|
||||||
import {CacheListener} from './cache-reporting'
|
import {CacheListener} from './cache-reporting'
|
||||||
import {DaemonController} from './daemon-controller'
|
import {DaemonController} from './daemon-controller'
|
||||||
|
import {BuildScanConfig, CacheConfig, SummaryConfig} from './input-params'
|
||||||
|
|
||||||
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
|
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
|
||||||
const USER_HOME = 'USER_HOME'
|
const USER_HOME = 'USER_HOME'
|
||||||
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
|
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
|
||||||
const CACHE_LISTENER = 'CACHE_LISTENER'
|
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 userHome = await determineUserHome()
|
||||||
const gradleUserHome = await determineGradleUserHome()
|
const gradleUserHome = await determineGradleUserHome()
|
||||||
|
|
||||||
@ -35,16 +36,16 @@ export async function setup(): Promise<boolean> {
|
|||||||
core.saveState(GRADLE_USER_HOME, gradleUserHome)
|
core.saveState(GRADLE_USER_HOME, gradleUserHome)
|
||||||
|
|
||||||
const cacheListener = new CacheListener()
|
const cacheListener = new CacheListener()
|
||||||
await caches.restore(userHome, gradleUserHome, cacheListener)
|
await caches.restore(userHome, gradleUserHome, cacheListener, cacheConfig)
|
||||||
|
|
||||||
core.saveState(CACHE_LISTENER, cacheListener.stringify())
|
core.saveState(CACHE_LISTENER, cacheListener.stringify())
|
||||||
|
|
||||||
buildScan.setup()
|
buildScan.setup(buildScanConfig)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function complete(): Promise<boolean> {
|
export async function complete(cacheConfig: CacheConfig, summaryConfig: SummaryConfig): Promise<boolean> {
|
||||||
if (!core.getState(GRADLE_SETUP_VAR)) {
|
if (!core.getState(GRADLE_SETUP_VAR)) {
|
||||||
core.info('Gradle setup post-action only performed for first gradle/actions step in workflow.')
|
core.info('Gradle setup post-action only performed for first gradle/actions step in workflow.')
|
||||||
return false
|
return false
|
||||||
@ -58,9 +59,9 @@ export async function complete(): Promise<boolean> {
|
|||||||
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
||||||
const daemonController = new DaemonController(buildResults)
|
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')
|
core.info('Completed post-action step')
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,8 @@ import * as setupGradle from '../setup-gradle'
|
|||||||
import * as execution from '../execution'
|
import * as execution from '../execution'
|
||||||
import * as provisioner from '../provision'
|
import * as provisioner from '../provision'
|
||||||
import * as layout from '../repository-layout'
|
import * as layout from '../repository-layout'
|
||||||
import * as params from '../input-params'
|
|
||||||
import * as dependencyGraph from '../dependency-graph'
|
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.
|
* 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> {
|
export async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// Configure Gradle environment (Gradle User Home)
|
// Configure Gradle environment (Gradle User Home)
|
||||||
await setupGradle.setup()
|
await setupGradle.setup(new CacheConfig(), new BuildScanConfig())
|
||||||
|
|
||||||
// Configure the dependency graph submission
|
// Configure the dependency graph submission
|
||||||
await dependencyGraph.setup(params.getDependencyGraphOption())
|
await dependencyGraph.setup(new DependencyGraphConfig())
|
||||||
|
|
||||||
// Download and install Gradle if required
|
// Download and install Gradle if required
|
||||||
const executable = await provisioner.provisionGradle()
|
const executable = await provisioner.provisionGradle()
|
||||||
|
|
||||||
// Only execute if arguments have been provided
|
// Only execute if arguments have been provided
|
||||||
const args: string[] = params.getArguments()
|
const args: string[] = getArguments()
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
const buildRootDirectory = layout.buildRootDirectory()
|
const buildRootDirectory = layout.buildRootDirectory()
|
||||||
await execution.executeGradleBuild(executable, buildRootDirectory, args)
|
await execution.executeGradleBuild(executable, buildRootDirectory, args)
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import * as core from '@actions/core'
|
|||||||
import * as setupGradle from '../setup-gradle'
|
import * as setupGradle from '../setup-gradle'
|
||||||
import * as dependencyGraph from '../dependency-graph'
|
import * as dependencyGraph from '../dependency-graph'
|
||||||
|
|
||||||
import {getDependencyGraphOption} from '../input-params'
|
import {CacheConfig, DependencyGraphConfig, SummaryConfig} from '../input-params'
|
||||||
import {PostActionJobFailure} from '../errors'
|
import {PostActionJobFailure} from '../errors'
|
||||||
|
|
||||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
// 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> {
|
export async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
if (await setupGradle.complete()) {
|
if (await setupGradle.complete(new CacheConfig(), new SummaryConfig())) {
|
||||||
// Only submit the dependency graphs once per job
|
// Only submit the dependency graphs once per job
|
||||||
await dependencyGraph.complete(getDependencyGraphOption())
|
await dependencyGraph.complete(new DependencyGraphConfig())
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof PostActionJobFailure) {
|
if (error instanceof PostActionJobFailure) {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import {GradleStateCache} from "../../src/cache-base"
|
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
|
import {GradleStateCache} from "../../src/cache-base"
|
||||||
|
import {CacheConfig} from "../../src/input-params"
|
||||||
|
|
||||||
const testTmp = 'test/jest/tmp'
|
const testTmp = 'test/jest/tmp'
|
||||||
fs.rmSync(testTmp, {recursive: true, force: true})
|
fs.rmSync(testTmp, {recursive: true, force: true})
|
||||||
@ -11,7 +12,7 @@ describe("--info and --stacktrace", () => {
|
|||||||
const emptyGradleHome = `${testTmp}/empty-gradle-home`
|
const emptyGradleHome = `${testTmp}/empty-gradle-home`
|
||||||
fs.mkdirSync(emptyGradleHome, {recursive: true})
|
fs.mkdirSync(emptyGradleHome, {recursive: true})
|
||||||
|
|
||||||
const stateCache = new GradleStateCache("ignored", emptyGradleHome)
|
const stateCache = new GradleStateCache("ignored", emptyGradleHome, new CacheConfig())
|
||||||
stateCache.configureInfoLogLevel()
|
stateCache.configureInfoLogLevel()
|
||||||
|
|
||||||
expect(fs.readFileSync(path.resolve(emptyGradleHome, "gradle.properties"), 'utf-8'))
|
expect(fs.readFileSync(path.resolve(emptyGradleHome, "gradle.properties"), 'utf-8'))
|
||||||
@ -24,7 +25,7 @@ describe("--info and --stacktrace", () => {
|
|||||||
fs.mkdirSync(existingGradleHome, {recursive: true})
|
fs.mkdirSync(existingGradleHome, {recursive: true})
|
||||||
fs.writeFileSync(path.resolve(existingGradleHome, "gradle.properties"), "org.gradle.logging.level=debug\n")
|
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()
|
stateCache.configureInfoLogLevel()
|
||||||
|
|
||||||
expect(fs.readFileSync(path.resolve(existingGradleHome, "gradle.properties"), 'utf-8'))
|
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('dependency-graph', () => {
|
||||||
describe('constructs job correlator', () => {
|
describe('constructs job correlator', () => {
|
||||||
it('removes commas from workflow name', () => {
|
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')
|
expect(id).toBe('workflow_withcommas-jobid')
|
||||||
})
|
})
|
||||||
it('removes non word characters', () => {
|
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')
|
expect(id).toBe('workflow_withcharacters-job-id-bar')
|
||||||
})
|
})
|
||||||
it('replaces spaces', () => {
|
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')
|
expect(id).toBe('workflow___with_characters_and_spaces-job-id-bar')
|
||||||
})
|
})
|
||||||
it('without matrix', () => {
|
it('without matrix', () => {
|
||||||
const id = dependencyGraph.constructJobCorrelator('workflow', 'jobid', 'null')
|
const id = DependencyGraphConfig.constructJobCorrelator('workflow', 'jobid', 'null')
|
||||||
expect(id).toBe('workflow-jobid')
|
expect(id).toBe('workflow-jobid')
|
||||||
})
|
})
|
||||||
it('with dashes in values', () => {
|
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')
|
expect(id).toBe('workflow-name-job-id-ubuntu-latest')
|
||||||
})
|
})
|
||||||
it('with single matrix value', () => {
|
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')
|
expect(id).toBe('workflow-jobid-windows')
|
||||||
})
|
})
|
||||||
it('with composite matrix value', () => {
|
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')
|
expect(id).toBe('workflow-jobid-windows-211-value_with_comma')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user