Redesign the caching Job Summary (#985)

Redesigns the caching section of the Job Summary into a single,
consistent layout across every cache provider and state, and integrates
the provider message into the report rather than appending it
disconnected at the bottom.

## Motivation

The caching report was produced by three divergent code paths (NoOp /
basic / enhanced), each rendering its own markdown:

- **Explicitly disabled** → a one-line message, no expand, no provider
note.
- **Enhanced** (incl. skipped-due-to-existing-home) → a full `<details>`
block.
- **Basic** → a one-line message with **no** expandable details at all.

The Enhanced/Basic provider note floated at the very bottom,
disconnected from the report.

## What changed

`save()` now returns structured `CacheReport` data instead of
pre-rendered HTML, and a single renderer (`caching-report.ts`) produces
one unified layout for all variants:

- **Section heading**: `#### <icon> Gradle Caching — <Provider>
(<status>)`
- **Status line** explaining what the cache did
- **Integrated provider note** woven in under the heading — now shown
**unconditionally** (no longer gated on license acceptance)
- **Expandable cache-entry details** when there are entries — basic
caching now gets this too

The two disabled variants (explicitly disabled, and skipped due to a
pre-existing Gradle User Home) render as **compact callouts with no
expandable section**.

### Main repo
- `caching-report.ts` (new): central renderer + all framing copy + entry
table/`<pre>` helpers.
- `cache-service.ts`: `CacheReport` / `CacheEntryReport` / status types;
`save()` returns `CacheReport`.
- `cache-service-loader.ts`: `NoOp` returns a report;
`LicenseWarningCacheService` removed; new `getProviderNote()`.
- `cache-service-basic.ts`: builds a `CacheReport`.
- `job-summary.ts` / `setup-gradle.ts`: thread `CacheReport` +
`ProviderNote`.
- `configuration.ts`: remove now-unused `isCacheLicenseAccepted()`.

### Vendored library
The structured contract requires **gradle-actions-caching v0.7.0**
(gradle/actions-caching#74). This PR updates the vendored library to
that release — the official `Update gradle-actions-caching library to
v0.7.0` vendor commit is included here, so merging this PR ships the
redesign together with the library it depends on.

## Testing

- Both repos build; prettier + eslint clean.
- `gradle/actions`: 363/363 Jest tests pass, including new
`caching-report.test.ts` covering every variant.
- `gradle-actions-caching`: 74/74 pass under JDK 17.
- Rendered markdown verified for all five variants (enhanced/basic
enabled & read-only, disabled, skipped).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Bot Githubaction <bot-githubaction@gradle.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
authored and GitHub committed 2026-06-12 15:21:52 +00:00
1 parent 8b6cdb5f58
commit 97715a29bc
13 files changed
+502 -92

No files matched your search

+75 -13
View File
@@ -4,7 +4,9 @@ import * as glob from '@actions/glob'
import * as path from 'path'
import {BuildResult} from './build-results'
import {CacheOptions, CacheService} from './cache-service'
import {CacheEntryReport, CacheOptions, CacheReport, CacheService} from './cache-service'
const ENTRY_NAME = 'Gradle User Home'
const PRIMARY_KEY_STATE = 'BASIC_CACHE_PRIMARY_KEY'
const RESTORED_KEY_STATE = 'BASIC_CACHE_RESTORED_KEY'
@@ -40,21 +42,39 @@ export class BasicCacheService implements CacheService {
}
}
async save(gradleUserHome: string, _buildResults: BuildResult[], cacheOptions: CacheOptions): Promise<string> {
if (cacheOptions.readOnly) {
const restoredKey = core.getState(RESTORED_KEY_STATE)
if (restoredKey) {
return `Basic caching was read-only. Restored from cache key \`${restoredKey}\`.`
}
return 'Basic caching was read-only. No cache entry was found to restore.'
}
async save(gradleUserHome: string, _buildResults: BuildResult[], cacheOptions: CacheOptions): Promise<CacheReport> {
const primaryKey = core.getState(PRIMARY_KEY_STATE)
const restoredKey = core.getState(RESTORED_KEY_STATE)
if (cacheOptions.readOnly) {
return {
status: 'read-only',
entries: [
entryReport({
primaryKey,
restoredKey,
restoredOutcome: restoredKey
? '(Entry restored: exact match found)'
: '(Entry not restored: no match found)',
savedOutcome: '(Entry not saved: cache is read-only)'
})
]
}
}
if (restoredKey === primaryKey) {
core.info(`Basic caching restored entry with key \`${primaryKey}\`. Save was skipped.`)
return `Basic caching restored entry with key \`${primaryKey}\`. Save was skipped.`
return {
status: 'enabled',
entries: [
entryReport({
primaryKey,
restoredKey,
restoredOutcome: '(Entry restored: exact match found)',
savedOutcome: '(Entry not saved: entry with key already exists)'
})
]
}
}
const cachePaths = getCachePaths(gradleUserHome)
@@ -62,12 +82,54 @@ export class BasicCacheService implements CacheService {
try {
await cache.saveCache(cachePaths, primaryKey)
core.info(`Basic caching saved entry with key: ${primaryKey}`)
return `Basic caching saved entry with key \`${primaryKey}\`.`
return {
status: 'enabled',
entries: [
entryReport({
primaryKey,
restoredKey,
savedKey: primaryKey,
restoredOutcome: restoredKey
? '(Entry restored: exact match found)'
: '(Entry not restored: no match found)',
savedOutcome: '(Entry saved)'
})
]
}
} catch (error) {
core.warning(`Basic caching failed to save entry with key \`${primaryKey}\`: ${error}`)
return `Basic caching save failed: ${error}`
return {
status: 'enabled',
entries: [
entryReport({
primaryKey,
restoredKey,
restoredOutcome: restoredKey
? '(Entry restored: exact match found)'
: '(Entry not restored: no match found)',
savedOutcome: `(Entry not saved: ${error})`
})
]
}
}
}
}
function entryReport(opts: {
primaryKey: string
restoredKey?: string
savedKey?: string
restoredOutcome: string
savedOutcome: string
}): CacheEntryReport {
return {
entryName: ENTRY_NAME,
requestedKey: opts.primaryKey || undefined,
restoredKey: opts.restoredKey || undefined,
restoredOutcome: opts.restoredOutcome,
savedKey: opts.savedKey || undefined,
savedOutcome: opts.savedOutcome
}
}
function getCachePaths(gradleUserHome: string): string[] {
+21 -48
View File
@@ -5,57 +5,24 @@ import {pathToFileURL} from 'url'
import {CacheConfig, CacheProvider} from './configuration'
import {BasicCacheService} from './cache-service-basic'
import {BuildResult} from './build-results'
import {CacheOptions, CacheService} from './cache-service'
const NOOP_CACHING_REPORT = `
[Cache was disabled](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#disabling-caching). Gradle User Home was not restored from or saved to the cache.
`
import {CacheOptions, CacheReport, CacheService} from './cache-service'
import {ProviderNote} from './caching-report'
const ENHANCED_CACHE_MESSAGE = `Enhanced Caching: This build is using the proprietary 'gradle-actions-caching' provider for optimized caching support. See https://github.com/gradle/actions/blob/main/DISTRIBUTION.md for terms of use and opt-out instructions.`
const ENHANCED_CACHE_SUMMARY = `
> [!NOTE]
> ### ⚡️ Enhanced Caching enabled
> This build provides optimized caching support via the proprietary **gradle-actions-caching** provider.
> See [DISTRIBUTION.md](https://github.com/gradle/actions/blob/main/DISTRIBUTION.md) for terms of use and opt-out instructions.
`
const BASIC_CACHE_MESSAGE = `Basic Caching: This build uses the open-source caching provider for reliable, path-based caching of Gradle dependencies. Upgrade available: for faster builds and advanced features, consider switching to the Enhanced Caching provider. See https://github.com/gradle/actions/blob/main/DISTRIBUTION.md for details.`
const BASIC_CACHE_SUMMARY = `
> [!NOTE]
> ### 🛡️ Basic Caching enabled
> This build uses the open-source caching provider for reliable, path-based caching of Gradle dependencies.
>
> **Upgrade Available:** For faster builds and advanced features, consider switching to the **Enhanced Caching** provider.
> See [DISTRIBUTION.md](https://github.com/gradle/actions/blob/main/DISTRIBUTION.md) for details.`
const BASIC_CACHE_MESSAGE = `Basic Caching: This build uses the basic open-source caching provider. For faster builds and advanced features, consider switching to the Enhanced Caching provider. See https://github.com/gradle/actions/blob/main/DISTRIBUTION.md for details.`
class NoOpCacheService implements CacheService {
async restore(_gradleUserHome: string, _cacheOptions: CacheOptions): Promise<void> {
return
}
async save(_gradleUserHome: string, _buildResults: BuildResult[], _cacheOptions: CacheOptions): Promise<string> {
return NOOP_CACHING_REPORT
}
}
class LicenseWarningCacheService implements CacheService {
private delegate: CacheService
private summary: string
constructor(delegate: CacheService, summary: string) {
this.delegate = delegate
this.summary = summary
}
async restore(gradleUserHome: string, cacheOptions: CacheOptions): Promise<void> {
await this.delegate.restore(gradleUserHome, cacheOptions)
}
async save(gradleUserHome: string, buildResults: BuildResult[], cacheOptions: CacheOptions): Promise<string> {
const cachingReport = await this.delegate.save(gradleUserHome, buildResults, cacheOptions)
return `${cachingReport}\n${this.summary}`
async save(
_gradleUserHome: string,
_buildResults: BuildResult[],
_cacheOptions: CacheOptions
): Promise<CacheReport> {
return {status: 'disabled', entries: []}
}
}
@@ -67,16 +34,22 @@ export async function getCacheService(cacheConfig: CacheConfig): Promise<CacheSe
if (cacheConfig.getCacheProvider() === CacheProvider.Basic) {
logCacheMessage(BASIC_CACHE_MESSAGE)
return new LicenseWarningCacheService(new BasicCacheService(), BASIC_CACHE_SUMMARY)
return new BasicCacheService()
}
logCacheMessage(ENHANCED_CACHE_MESSAGE)
const cacheService = await loadVendoredCacheService()
if (cacheConfig.isCacheLicenseAccepted()) {
return cacheService
}
return loadVendoredCacheService()
}
return new LicenseWarningCacheService(cacheService, ENHANCED_CACHE_SUMMARY)
/**
* Identifies the caching provider for the Job Summary. Returns `undefined` when
* caching is disabled, since no provider is engaged in that case.
*/
export function getProviderNote(cacheConfig: CacheConfig): ProviderNote | undefined {
if (cacheConfig.isCacheDisabled()) {
return undefined
}
return cacheConfig.getCacheProvider() === CacheProvider.Basic ? {kind: 'basic'} : {kind: 'enhanced'}
}
export async function loadVendoredCacheService(): Promise<CacheService> {
+39 -1
View File
@@ -12,7 +12,45 @@ export interface CacheOptions {
excludes: string[]
}
export type CacheStatus =
| 'enabled'
| 'read-only'
| 'write-only'
| 'disabled'
| 'disabled-existing-home'
| 'not-available'
export type CacheCleanupStatus =
| 'enabled'
| 'disabled-param'
| 'disabled-failure'
| 'disabled-config-cache-hit'
| 'disabled-readonly'
export interface CacheEntryReport {
entryName: string
requestedKey?: string
restoredKey?: string
restoredSize?: number
restoredTime?: number
restoredOutcome: string
savedKey?: string
savedSize?: number
savedTime?: number
savedOutcome: string
}
/**
* Structured result of a cache save operation. Rendering this into a human-readable
* Job Summary is handled centrally by `caching-report.ts`.
*/
export interface CacheReport {
status: CacheStatus
cleanup?: CacheCleanupStatus
entries: CacheEntryReport[]
}
export interface CacheService {
restore(gradleUserHome: string, cacheOptions: CacheOptions): Promise<void>
save(gradleUserHome: string, buildResults: BuildResult[], cacheOptions: CacheOptions): Promise<string>
save(gradleUserHome: string, buildResults: BuildResult[], cacheOptions: CacheOptions): Promise<CacheReport>
}
+168
View File
@@ -0,0 +1,168 @@
import {CacheCleanupStatus, CacheEntryReport, CacheReport, CacheStatus} from './cache-service'
const DOCS = 'https://github.com/gradle/actions/blob/main/docs/setup-gradle.md'
const DISTRIBUTION = 'https://github.com/gradle/actions/blob/main/DISTRIBUTION.md'
/**
* Identifies the caching provider in use, so the report can attribute the cache
* and surface the relevant terms-of-use / upgrade information.
*/
export interface ProviderNote {
kind: 'enhanced' | 'basic'
}
const STATUS_COPY: Record<CacheStatus, string> = {
enabled: `[Cache was enabled](${DOCS}#caching-build-state-between-jobs) — Gradle User Home was restored from the cache and saved for use by subsequent jobs.`,
'read-only': `[Cache was read-only](${DOCS}#using-the-cache-read-only) — by default, the action only writes to the cache for jobs running on the default branch.`,
'write-only': `[Cache was write-only](${DOCS}#using-the-cache-write-only) — Gradle User Home was not restored from the cache.`,
disabled: `[Caching was disabled](${DOCS}#disabling-caching) — Gradle User Home was not restored from or saved to the cache.`,
'disabled-existing-home': `⚠️ [Caching was skipped](${DOCS}#overwriting-an-existing-gradle-user-home) — a pre-existing Gradle User Home was found, so the cache was not restored or saved.`,
'not-available': `Caching is not available — the GitHub Actions cache service could not be reached, so Gradle User Home was not restored or saved.`
}
const CLEANUP_COPY: Record<CacheCleanupStatus, string> = {
enabled: `[Cache cleanup](${DOCS}#configuring-cache-cleanup) purged stale files from Gradle User Home before saving.`,
'disabled-param': `[Cache cleanup](${DOCS}#configuring-cache-cleanup) was disabled via action parameter.`,
'disabled-failure': `[Cache cleanup](${DOCS}#configuring-cache-cleanup) was skipped due to a build failure. Use \`cache-cleanup: always\` to override.`,
'disabled-config-cache-hit': `[Cache cleanup](${DOCS}#configuring-cache-cleanup) was skipped due to configuration-cache reuse.`,
'disabled-readonly': `[Cache cleanup](${DOCS}#configuring-cache-cleanup) is always disabled when the cache is read-only.`
}
/**
* Renders a cache report into the unified Job Summary markdown, with a consistent
* skeleton across every variant: a section heading, a status line, an integrated
* provider note, and (when there are entries) an expandable details section.
*/
export function renderCachingReport(report: CacheReport, providerNote?: ProviderNote): string {
if (!isActive(report.status)) {
// Disabled / skipped / unavailable: a compact heading + status line, no expandable section.
return `${renderHeading(report.status, providerNote)}\n\n${STATUS_COPY[report.status]}\n`
}
const sections = [
renderHeading(report.status, providerNote),
renderProviderNote(providerNote),
// Status and cleanup messages live inside the details expando; if there are no entries
// to expand, fall back to showing the status line directly.
report.entries.length > 0 ? renderDetails(report) : STATUS_COPY[report.status]
]
return `${sections.filter(section => section !== undefined && section !== '').join('\n\n')}\n`
}
function isActive(status: CacheStatus): boolean {
return status === 'enabled' || status === 'read-only' || status === 'write-only'
}
function renderHeading(status: CacheStatus, providerNote?: ProviderNote): string {
if (!isActive(status)) {
const label =
status === 'disabled-existing-home' ? 'Skipped' : status === 'not-available' ? 'Unavailable' : 'Disabled'
return `<h4>Gradle State Caching - ${label}</h4>`
}
const icon = providerNote?.kind === 'basic' ? '🛡️' : '⚡'
const provider = providerNote?.kind === 'basic' ? 'Basic' : 'Enhanced'
const suffix = status === 'read-only' ? ' (read-only)' : status === 'write-only' ? ' (write-only)' : ''
return `<h4>Gradle State Caching - ${icon} ${provider}${suffix}</h4>`
}
function renderCleanupLine(cleanup?: CacheCleanupStatus): string | undefined {
return cleanup ? CLEANUP_COPY[cleanup] : undefined
}
function renderProviderNote(providerNote?: ProviderNote): string | undefined {
if (!providerNote) {
return undefined
}
if (providerNote.kind === 'enhanced') {
return `**[Enhanced Caching](${DOCS}#enhanced-caching)** uses the proprietary \`gradle-actions-caching\` provider. See [DISTRIBUTION.md](${DISTRIBUTION}) for terms of use and opt-out instructions.`
}
return `**[Basic Caching](${DOCS}#basic-caching)** uses the basic open-source caching provider. For faster builds and advanced features, consider the **[Enhanced Caching](${DOCS}#enhanced-caching)** provider.`
}
function renderDetails(report: CacheReport): string {
const entries = report.entries
const restored = entries.filter(entry => entry.restoredKey).length
const saved = entries.filter(entry => entry.savedKey).length
const summary = hasMetrics(entries)
? `Entries: ${restored} restored (${getSize(entries, e => e.restoredSize)}Mb), ${saved} saved (${getSize(entries, e => e.savedSize)}Mb) - Expand for more details`
: `Entries: ${restored} restored, ${saved} saved - Expand for more details`
const cleanup = report.status === 'enabled' ? renderCleanupLine(report.cleanup) : undefined
const table = renderEntryTable(report.entries)
const pre = `<pre>\n${renderEntryDetails(report.entries)}</pre>`
const body = [STATUS_COPY[report.status], cleanup, table, pre].filter(Boolean).join('\n\n')
return `<details>
<summary>${summary}</summary>
${body}
</details>`
}
function hasMetrics(entries: CacheEntryReport[]): boolean {
return entries.some(entry => entry.restoredSize || entry.restoredTime || entry.savedSize || entry.savedTime)
}
function renderEntryTable(entries: CacheEntryReport[]): string {
if (!hasMetrics(entries)) {
return ''
}
return `<table>
<tr><td></td><th>Count</th><th>Total Size (Mb)</th><th>Total Time (ms)</th></tr>
<tr><td>Entries Restored</td>
<td>${getCount(entries, e => e.restoredSize)}</td>
<td>${getSize(entries, e => e.restoredSize)}</td>
<td>${getTime(entries, e => e.restoredTime)}</td>
</tr>
<tr><td>Entries Saved</td>
<td>${getCount(entries, e => e.savedSize)}</td>
<td>${getSize(entries, e => e.savedSize)}</td>
<td>${getTime(entries, e => e.savedTime)}</td>
</tr>
</table>`
}
function renderEntryDetails(entries: CacheEntryReport[]): string {
return entries
.map(
entry => `Entry: ${entry.entryName}
Requested Key : ${entry.requestedKey ?? ''}
Restored Key : ${entry.restoredKey ?? ''}
Size: ${formatSize(entry.restoredSize)}
Time: ${formatTime(entry.restoredTime)}
${entry.restoredOutcome}
Saved Key : ${entry.savedKey ?? ''}
Size: ${formatSize(entry.savedSize)}
Time: ${formatTime(entry.savedTime)}
${entry.savedOutcome}
`
)
.join('---\n')
}
function getCount(entries: CacheEntryReport[], predicate: (value: CacheEntryReport) => number | undefined): number {
return entries.filter(e => predicate(e)).length
}
function getSize(entries: CacheEntryReport[], predicate: (value: CacheEntryReport) => number | undefined): number {
const bytes = entries.map(e => predicate(e) ?? 0).reduce((p, v) => p + v, 0)
return Math.round(bytes / (1024 * 1024))
}
function getTime(entries: CacheEntryReport[], predicate: (value: CacheEntryReport) => number | undefined): number {
return entries.map(e => predicate(e) ?? 0).reduce((p, v) => p + v, 0)
}
function formatSize(bytes: number | undefined): string {
if (bytes === undefined || bytes === 0) {
return ''
}
return `${Math.round(bytes / (1024 * 1024))} MB (${bytes} B)`
}
function formatTime(ms: number | undefined): string {
if (ms === undefined || ms === 0) {
return ''
}
return `${ms} ms`
}
-5
View File
@@ -167,11 +167,6 @@ export class CacheConfig {
return core.getMultilineInput('gradle-home-cache-excludes')
}
isCacheLicenseAccepted(): boolean {
const dvConfig = new DevelocityConfig()
return dvConfig.getDevelocityAccessKey() !== '' || dvConfig.hasTermsOfUseAgreement()
}
getCacheProvider(): CacheProvider {
const val = core.getInput('cache-provider')
switch (val.toLowerCase().trim()) {
+5 -1
View File
@@ -2,12 +2,15 @@ import * as core from '@actions/core'
import * as github from '@actions/github'
import {BuildResult} from './build-results'
import {CacheReport} from './cache-service'
import {ProviderNote, renderCachingReport} from './caching-report'
import {DependencyGraphConfig, getActionId, getGithubToken, getJobMatrix, SummaryConfig} from './configuration'
import {Deprecation, getDeprecations, getErrors} from './deprecation-collector'
export async function generateJobSummary(
buildResults: BuildResult[],
cachingReport: string,
cacheReport: CacheReport,
providerNote: ProviderNote | undefined,
config: SummaryConfig
): Promise<void> {
const errors = renderErrors()
@@ -18,6 +21,7 @@ export async function generateJobSummary(
}
const summaryTable = renderSummaryTable(buildResults)
const cachingReport = renderCachingReport(cacheReport, providerNote)
const hasFailure = anyFailed(buildResults)
if (config.shouldGenerateJobSummary(hasFailure)) {
core.info('Generating Job Summary')
+3 -3
View File
@@ -7,7 +7,7 @@ import * as jobSummary from './job-summary'
import * as buildScan from './develocity/build-scan'
import {loadBuildResults, markBuildResultsProcessed} from './build-results'
import {getCacheService} from './cache-service-loader'
import {getCacheService, getProviderNote} from './cache-service-loader'
import {CacheOptions} from './cache-service'
import {
DevelocityConfig,
@@ -65,8 +65,8 @@ export async function complete(cacheConfig: CacheConfig, summaryConfig: SummaryC
const gradleUserHome = core.getState(GRADLE_USER_HOME)
const cacheService = await getCacheService(cacheConfig)
const cachingReport = await cacheService.save(gradleUserHome, buildResults, cacheOptionsFrom(cacheConfig))
await jobSummary.generateJobSummary(buildResults, cachingReport, summaryConfig)
const cacheReport = await cacheService.save(gradleUserHome, buildResults, cacheOptionsFrom(cacheConfig))
await jobSummary.generateJobSummary(buildResults, cacheReport, getProviderNote(cacheConfig), summaryConfig)
markBuildResultsProcessed()
+11 -7
View File
@@ -138,8 +138,8 @@ describe('BasicCacheService', () => {
})
expect(mockSaveCache).not.toHaveBeenCalled()
expect(report).toContain('read-only')
expect(report).toContain(PRIMARY_KEY)
expect(report.status).toBe('read-only')
expect(report.entries[0].restoredKey).toBe(PRIMARY_KEY)
})
it('reports readOnly with no restore when cache was missed', async () => {
@@ -156,8 +156,9 @@ describe('BasicCacheService', () => {
})
expect(mockSaveCache).not.toHaveBeenCalled()
expect(report).toContain('read-only')
expect(report).toContain('No cache entry')
expect(report.status).toBe('read-only')
expect(report.entries[0].restoredKey).toBeUndefined()
expect(report.entries[0].restoredOutcome).toContain('not restored')
})
it('skips save when restored key equals primary key', async () => {
@@ -179,7 +180,8 @@ describe('BasicCacheService', () => {
})
expect(mockSaveCache).not.toHaveBeenCalled()
expect(report).toContain('Save was skipped')
expect(report.status).toBe('enabled')
expect(report.entries[0].savedOutcome).toContain('already exists')
})
it('saves cache and returns report on success', async () => {
@@ -204,7 +206,9 @@ describe('BasicCacheService', () => {
['/home/.gradle/caches', '/home/.gradle/wrapper'],
PRIMARY_KEY
)
expect(report).toContain('saved entry with key')
expect(report.status).toBe('enabled')
expect(report.entries[0].savedKey).toBe(PRIMARY_KEY)
expect(report.entries[0].savedOutcome).toBe('(Entry saved)')
})
it('warns on save failure instead of throwing', async () => {
@@ -228,7 +232,7 @@ describe('BasicCacheService', () => {
expect(mockWarning).toHaveBeenCalledWith(
expect.stringContaining('failed to save')
)
expect(report).toContain('failed')
expect(report.entries[0].savedOutcome).toContain('not saved')
})
})
})
+39 -10
View File
@@ -12,8 +12,7 @@ describe('getCacheService selection logic', () => {
const {getCacheService} = await import('../../src/cache-service-loader')
const mockConfig = {
isCacheDisabled: () => true,
getCacheProvider: () => CacheProvider.Enhanced,
isCacheLicenseAccepted: () => true
getCacheProvider: () => CacheProvider.Enhanced
} as unknown as CacheConfig
const service = await getCacheService(mockConfig)
@@ -28,23 +27,53 @@ describe('getCacheService selection logic', () => {
excludes: []
})
// NoOpCacheService returns a specific report mentioning cache was disabled
expect(report).toContain('Cache was disabled')
// NoOpCacheService reports a disabled cache with no entries
expect(report.status).toBe('disabled')
expect(report.entries).toHaveLength(0)
})
it('wraps BasicCacheService with LicenseWarningCacheService when cache-provider is basic', async () => {
it('returns a BasicCacheService when cache-provider is basic', async () => {
const {getCacheService} = await import('../../src/cache-service-loader')
const mockConfig = {
isCacheDisabled: () => false,
getCacheProvider: () => CacheProvider.Basic,
isCacheLicenseAccepted: () => false
getCacheProvider: () => CacheProvider.Basic
} as unknown as CacheConfig
const service = await getCacheService(mockConfig)
// The service should not be a bare BasicCacheService — it should be wrapped
// with LicenseWarningCacheService that appends the basic caching summary
const {BasicCacheService} = await import('../../src/cache-service-basic')
expect(service).not.toBeInstanceOf(BasicCacheService)
expect(service).toBeInstanceOf(BasicCacheService)
})
describe('getProviderNote', () => {
it('returns undefined when cache is disabled', async () => {
const {getProviderNote} = await import('../../src/cache-service-loader')
const mockConfig = {
isCacheDisabled: () => true,
getCacheProvider: () => CacheProvider.Enhanced
} as unknown as CacheConfig
expect(getProviderNote(mockConfig)).toBeUndefined()
})
it('returns basic note for the basic provider', async () => {
const {getProviderNote} = await import('../../src/cache-service-loader')
const mockConfig = {
isCacheDisabled: () => false,
getCacheProvider: () => CacheProvider.Basic
} as unknown as CacheConfig
expect(getProviderNote(mockConfig)).toEqual({kind: 'basic'})
})
it('returns enhanced note for the enhanced provider', async () => {
const {getProviderNote} = await import('../../src/cache-service-loader')
const mockConfig = {
isCacheDisabled: () => false,
getCacheProvider: () => CacheProvider.Enhanced
} as unknown as CacheConfig
expect(getProviderNote(mockConfig)).toEqual({kind: 'enhanced'})
})
})
})
+110
View File
@@ -0,0 +1,110 @@
import {describe, expect, it} from '@jest/globals'
import {CacheReport} from '../../src/cache-service'
import {renderCachingReport} from '../../src/caching-report'
const ENHANCED = {kind: 'enhanced'} as const
const BASIC = {kind: 'basic'} as const
function entry(overrides: Partial<CacheReport['entries'][number]> = {}): CacheReport['entries'][number] {
return {
entryName: 'Gradle User Home',
requestedKey: 'gradle-home-v1|key',
restoredKey: 'gradle-home-v1|key',
restoredSize: 535792,
restoredTime: 253,
restoredOutcome: '(Entry restored: exact match found)',
savedKey: 'gradle-home-v1|key',
savedSize: 528509,
savedTime: 257,
savedOutcome: '(Entry saved)',
...overrides
}
}
describe('renderCachingReport', () => {
it('renders an enhanced read-only report with heading, note and details', () => {
const report: CacheReport = {status: 'read-only', cleanup: 'disabled-readonly', entries: [entry()]}
const md = renderCachingReport(report, ENHANCED)
expect(md).toContain('<h4>Gradle State Caching - ⚡ Enhanced (read-only)</h4>')
expect(md).toContain('[Enhanced Caching]')
expect(md).toContain('`gradle-actions-caching`')
expect(md).toContain('DISTRIBUTION.md')
expect(md).toContain('<details>')
expect(md).toContain('<summary>Entries: 1 restored (1Mb), 1 saved (1Mb) - Expand for more details</summary>')
// status message moves inside the details expando
expect(md).toContain('Cache was read-only')
// read-only does not render the cleanup line
expect(md).not.toContain('Cache cleanup')
})
it('renders an enhanced enabled report with status and cleanup inside the details', () => {
const report: CacheReport = {status: 'enabled', cleanup: 'enabled', entries: [entry()]}
const md = renderCachingReport(report, ENHANCED)
expect(md).toContain('<h4>Gradle State Caching - ⚡ Enhanced</h4>')
// status and cleanup messages are within the expando, after the summary
const detailsBody = md.slice(md.indexOf('</summary>'))
expect(detailsBody).toContain('Cache was enabled')
expect(detailsBody).toContain('Cache cleanup')
expect(md).toContain('<table>')
expect(md).toContain('Entries Restored')
})
it('renders a basic report with the upgrade note and no metrics table', () => {
const report: CacheReport = {
status: 'read-only',
entries: [
entry({
restoredSize: undefined,
restoredTime: undefined,
savedKey: undefined,
savedSize: undefined,
savedTime: undefined,
savedOutcome: '(Entry not saved: cache is read-only)'
})
]
}
const md = renderCachingReport(report, BASIC)
expect(md).toContain('<h4>Gradle State Caching - 🛡️ Basic (read-only)</h4>')
expect(md).toContain('[Basic Caching]')
expect(md).toContain('[Enhanced Caching]')
// DISTRIBUTION.md is only referenced for the enhanced provider
expect(md).not.toContain('DISTRIBUTION.md')
// No size/time data, so the metrics table is omitted but the entry list remains
expect(md).not.toContain('<table>')
expect(md).toContain('<pre>')
expect(md).toContain('<summary>Entries: 1 restored, 0 saved - Expand for more details</summary>')
})
it('renders a compact disabled report with no note and no details', () => {
const report: CacheReport = {status: 'disabled', entries: []}
const md = renderCachingReport(report, undefined)
expect(md).toContain('<h4>Gradle State Caching - Disabled</h4>')
expect(md).toContain('Caching was disabled')
expect(md).not.toContain('<details>')
expect(md).not.toContain('DISTRIBUTION.md')
})
it('renders a compact skipped report for a pre-existing Gradle User Home', () => {
const report: CacheReport = {status: 'disabled-existing-home', entries: []}
const md = renderCachingReport(report, ENHANCED)
expect(md).toContain('<h4>Gradle State Caching - Skipped</h4>')
expect(md).toContain('pre-existing Gradle User Home')
expect(md).not.toContain('<details>')
// no provider note for non-active states
expect(md).not.toContain('DISTRIBUTION.md')
})
it('renders an unavailable report compactly', () => {
const report: CacheReport = {status: 'not-available', entries: []}
const md = renderCachingReport(report, ENHANCED)
expect(md).toContain('<h4>Gradle State Caching - Unavailable</h4>')
expect(md).not.toContain('<details>')
})
})
+28 -1
View File
@@ -11,6 +11,23 @@ export declare interface BuildResult {
get buildScanFailed(): boolean;
}
/** @public */
export declare type CacheCleanupStatus = 'enabled' | 'disabled-param' | 'disabled-failure' | 'disabled-config-cache-hit' | 'disabled-readonly';
/** @public */
export declare interface CacheEntryReport {
entryName: string;
requestedKey?: string;
restoredKey?: string;
restoredSize?: number;
restoredTime?: number;
restoredOutcome: string;
savedKey?: string;
savedSize?: number;
savedTime?: number;
savedOutcome: string;
}
/** @public */
export declare interface CacheOptions {
disabled: boolean;
@@ -24,10 +41,20 @@ export declare interface CacheOptions {
excludes: string[];
}
/** @public */
export declare interface CacheReport {
status: CacheStatus;
cleanup?: CacheCleanupStatus;
entries: CacheEntryReport[];
}
/** @public */
export declare type CacheStatus = 'enabled' | 'read-only' | 'write-only' | 'disabled' | 'disabled-existing-home' | 'not-available';
/** @public */
export declare function restore(gradleUserHome: string, cacheOptions: CacheOptions): Promise<void>;
/** @public */
export declare function save(gradleUserHome: string, buildResults: BuildResult[], cacheOptions: CacheOptions): Promise<string>;
export declare function save(gradleUserHome: string, buildResults: BuildResult[], cacheOptions: CacheOptions): Promise<CacheReport>;
export { }
+2 -2
View File
@@ -1,2 +1,2 @@
const a0_0x4f43aa=a0_0xffd8;(function(_0x302585,_0x4a274e){const _0x23c0ad=a0_0xffd8,_0x1c91eb=_0x302585();while(!![]){try{const _0x33e709=parseInt(_0x23c0ad(0x1266))/0x1+parseInt(_0x23c0ad(0xf67))/0x2+parseInt(_0x23c0ad(0x61a))/0x3*(parseInt(_0x23c0ad(0x129a))/0x4)+-parseInt(_0x23c0ad(0x59f))/0x5+-parseInt(_0x23c0ad(0xc74))/0x6*(-parseInt(_0x23c0ad(0x337))/0x7)+-parseInt(_0x23c0ad(0x114a))/0x8*(parseInt(_0x23c0ad(0xb77))/0x9)+parseInt(_0x23c0ad(0xa6d))/0xa;if(_0x33e709===_0x4a274e)break;else _0x1c91eb['push'](_0x1c91eb['shift']());}catch(_0x398153){_0x1c91eb['push'](_0x1c91eb['shift']());}}}(a0_0x2ce4,0xc297f));import*as a0_0x35f4b8 from'os';import a0_0x137676,{EOL as a0_0x114f8c}from'os';import*as a0_0x2c2bbe from'crypto';import*as a0_0x3dc31e from'fs';import a0_0x5cd30a,{promises,writeFileSync,existsSync,readFileSync}from'fs';import*as a0_0x1b7e4c from'path';import a0_0x3f7c2f from'path';import*as a0_0x2b582b from'http';import a0_0x4d3049 from'http';import*as a0_0x5b2405 from'https';import a0_0x4e0136 from'https';import a0_0x3e9e2c from'net';import a0_0x336d4d from'tls';import*as a0_0x404b8c from'events';import a0_0x16e8b6,{EventEmitter}from'events';import a0_0x228d92,{ok}from'assert';import*as a0_0x17bd1d from'util';import a0_0xc9d54b from'util';import a0_0x2642c9 from'node:assert';import a0_0xd1f879 from'node:net';import a0_0xd0f63 from'node:http';import a0_0x157f77,{Transform,Readable as a0_0x544c7c}from'node:stream';import a0_0x50d56a from'node:buffer';import a0_0x48b20c,{inspect}from'node:util';import a0_0xd4f5bd from'node:querystring';import a0_0x17bb4f from'node:events';import a0_0xa999d8 from'node:diagnostics_channel';import a0_0x2cd5b6 from'node:tls';import a0_0x47ab42 from'node:zlib';import a0_0x1c20b8 from'node:perf_hooks';import a0_0x4df183 from'node:util/types';import a0_0x2ad0e6 from'node:worker_threads';import a0_0x7adee5 from'node:url';import a0_0x1be56f from'node:async_hooks';import a0_0x4f2dc1 from'node:console';import a0_0x40b9bb from'node:dns';import a0_0x28c074,{StringDecoder}from'string_decoder';import*as a0_0x42f029 from'child_process';import{setTimeout as a0_0x59d915}from'timers';import*as a0_0x286c1a from'stream';import{Readable}from'stream';import a0_0x1c1ba8,{URL as a0_0x3480a2}from'url';import*as a0_0x23dccf from'buffer';import{Buffer as a0_0x5c25b4}from'buffer';import a0_0x514119,{EOL as a0_0x2b7a69}from'node:os';import a0_0x253953 from'node:process';import a0_0x4833fd from'node:https';import a0_0xf4e5c6 from'tty';import{createHmac}from'node:crypto';import a0_0x5a64d4 from'node:fs';function toCommandValue(_0x30faea){const _0x2d74b2=a0_0xffd8;if(_0x30faea===null||_0x30faea===undefined)return'';else{if(typeof _0x30faea===_0x2d74b2(0xcd7)||_0x30faea instanceof String)return _0x30faea;}return JSON[_0x2d74b2(0xade)](_0x30faea);}function toCommandProperties(_0x10028f){const _0x39a880=a0_0xffd8;if(!Object[_0x39a880(0x5d2)](_0x10028f)[_0x39a880(0xdb1)])return{};return{'title':_0x10028f[_0x39a880(0x217)],'file':_0x10028f[_0x39a880(0x180e)],'line':_0x10028f[_0x39a880(0x13a1)],'endLine':_0x10028f['endLine'],'col':_0x10028f[_0x39a880(0x10c7)],'endColumn':_0x10028f[_0x39a880(0xd0f)]};}function issueCommand(_0x48ea15,_0x5a67bd,_0x6e1854){const _0x4aa6aa=a0_0xffd8,_0x1c0c7b=new Command(_0x48ea15,_0x5a67bd,_0x6e1854);process[_0x4aa6aa(0x38a)][_0x4aa6aa(0x1594)](_0x1c0c7b[_0x4aa6aa(0x32a)]()+a0_0x35f4b8[_0x4aa6aa(0xc63)]);}function issue(_0x5a8e9c,_0x234f0c=''){issueCommand(_0x5a8e9c,{},_0x234f0c);}const CMD_STRING='::';class Command{constructor(_0x2d79b0,_0xfcd2a0,_0x354512){const _0x27aa86=a0_0xffd8;!_0x2d79b0&&(_0x2d79b0='missing.command'),this[_0x27aa86(0x11c2)]=_0x2d79b0,this[_0x27aa86(0xa2c)]=_0xfcd2a0,this[_0x27aa86(0xd83)]=_0x354512;}[a0_0x4f43aa(0x32a)](){const _0x334373=a0_0x4f43aa;let _0x361f2b=CMD_STRING+this['command'];if(this[_0x334373(0xa2c)]&&Object[_0x334373(0x5d2)](this[_0x334373(0xa2c)])['length']>0x0){_0x361f2b+='\x20';let _0x4dd320=!![];for(const _0x228a8b in this['properties']){if(this['properties'][_0x334373(0x973)](_0x228a8b)){const _0xeb58bf=this[_0x334373(0xa2c)][_0x228a8b];_0xeb58bf&&(_0x4dd320?_0x4dd320=![]:_0x361f2b+=',',_0x361f2b+=_0x228a8b+'='+escapeProperty(_0xeb58bf));}}}return _0x361f2b+=''+CMD_STRING+escapeData(this['message']),_0x361f2b;}}function escapeData(_0x4c027c){const _0x173814=a0_0x4f43aa;return toCommandValue(_0x4c027c)[_0x173814(0x1038)](/%/g,_0x173814(0x1164))[_0x173814(0x1038)](/\r/g,_0x173814(0x2ea))[_0x173814(0x1038)](/\n/g,'%0A');}function escapeProperty(_0x3551c7){const _0x24be59=a0_0x4f43aa;return toCommandValue(_0x3551c7)[_0x24be59(0x1038)](/%/g,_0x24be59(0x1164))[_0x24be59(0x1038)](/\r/g,_0x24be59(0x2ea))[_0x24be59(0x1038)](/\n/g,_0x24be59(0x111b))[_0x24be59(0x1038)](/:/g,_0x24be59(0x112d))[_0x24be59(0x1038)](/,/g,_0x24be59(0x1635));}function issueFileCommand(_0x4d75cd,_0x1fe047){const _0x31dbb9=a0_0x4f43aa,_0x3c4619=process.env[`GITHUB_${_0x4d75cd}`];if(!_0x3c4619)throw new Error(_0x31dbb9(0x104e)+_0x4d75cd);if(!a0_0x3dc31e['existsSync'Line truncated
()=>new ArrayBuffer(0x0));}function isJSONResponse(_0x360163){const _0x51d9e1=a0_0x4f43aa;return _0x360163[_0x51d9e1(0x1308)]==='application/json'||_0x360163[_0x51d9e1(0x1308)]===_0x51d9e1(0xcbb);}function toErrorMessage(_0x3c59a9){const _0x1a2008=a0_0x4f43aa;if(typeof _0x3c59a9===_0x1a2008(0xcd7))return _0x3c59a9;if(_0x3c59a9 instanceof ArrayBuffer)return _0x1a2008(0x64b);if('message'in _0x3c59a9){const _0xed66c='documentation_url'in _0x3c59a9?_0x1a2008(0x1773)+_0x3c59a9[_0x1a2008(0x3b3)]:'';return Array[_0x1a2008(0x807)](_0x3c59a9['errors'])?_0x3c59a9['message']+':\x20'+_0x3c59a9[_0x1a2008(0x109d)]['map'](_0x319dd5=>JSON[_0x1a2008(0xade)](_0x319dd5))['join'](',\x20')+_0xed66c:''+_0x3c59a9[_0x1a2008(0xd83)]+_0xed66c;}return _0x1a2008(0x5c9)+JSON['stringify'](_0x3c59a9);}function withDefaults$1(_0x3528eb,_0x2f35ca){const _0x4bcdc6=a0_0x4f43aa,_0x3e56a5=_0x3528eb[_0x4bcdc6(0x7a3)](_0x2f35ca),_0x574f3a=function(_0x55b23b,_0x1a8185){const _0xba224e=_0x4bcdc6,_0x36ae16=_0x3e56a5[_0xba224e(0x1c9)](_0x55b23b,_0x1a8185);if(!_0x36ae16[_0xba224e(0xbb2)]||!_0x36ae16[_0xba224e(0xbb2)][_0xba224e(0x1444)])return fetchWrapper(_0x3e56a5[_0xba224e(0xd13)](_0x36ae16));const _0x24ef3e=(_0x30c3ba,_0x30231c)=>{const _0x215c8f=_0xba224e;return fetchWrapper(_0x3e56a5[_0x215c8f(0xd13)](_0x3e56a5[_0x215c8f(0x1c9)](_0x30c3ba,_0x30231c)));};return Object[_0xba224e(0xf0f)](_0x24ef3e,{'endpoint':_0x3e56a5,'defaults':withDefaults$1[_0xba224e(0x20f)](null,_0x3e56a5)}),_0x36ae16['request'][_0xba224e(0x1444)](_0x24ef3e,_0x36ae16);};return Object[_0x4bcdc6(0xf0f)](_0x574f3a,{'endpoint':_0x3e56a5,'defaults':withDefaults$1[_0x4bcdc6(0x20f)](null,_0x3e56a5)});}var request=withDefaults$1(endpoint,defaults_default),VERSION$3='0.0.0-development';function _buildMessageForResponseErrors(_0x4a3673){const _0x27d5e1=a0_0x4f43aa;return _0x27d5e1(0xa14)+_0x4a3673[_0x27d5e1(0x109d)]['map'](_0x5575bd=>_0x27d5e1(0x1773)+_0x5575bd[_0x27d5e1(0xd83)])[_0x27d5e1(0x718)]('\x0a');}var GraphqlResponseError=class extends Error{constructor(_0x2fd366,_0x4513b4,_0x3b9e30){const _0xe1e20e=a0_0x4f43aa;super(_buildMessageForResponseErrors(_0x3b9e30)),this[_0xe1e20e(0xbb2)]=_0x2fd366,this[_0xe1e20e(0x1e6)]=_0x4513b4,this[_0xe1e20e(0xc8f)]=_0x3b9e30,this[_0xe1e20e(0x109d)]=_0x3b9e30['errors'],this[_0xe1e20e(0x1200)]=_0x3b9e30[_0xe1e20e(0x1200)],Error['captureStackTrace']&&Error['captureStackTrace'](this,this[_0xe1e20e(0x490)]);}['name']='GraphqlResponseError';[a0_0x4f43aa(0x109d)];[a0_0x4f43aa(0x1200)];},NON_VARIABLE_OPTIONS=[a0_0x4f43aa(0x3b9),'baseUrl','url',a0_0x4f43aa(0x1e6),a0_0x4f43aa(0xbb2),a0_0x4f43aa(0xee3),a0_0x4f43aa(0xf62),a0_0x4f43aa(0x11f7)],FORBIDDEN_VARIABLE_OPTIONS=['query','method','url'],GHES_V3_SUFFIX_REGEX=/\/api\/v3\/?$/;function graphql(_0xe0ed85,_0x221d39,_0x52b37d){const _0xaa8053=a0_0x4f43aa;if(_0x52b37d){if(typeof _0x221d39===_0xaa8053(0xcd7)&&_0xaa8053(0xee3)in _0x52b37d)return Promise[_0xaa8053(0xf98)](new Error(_0xaa8053(0x12f7)));for(const _0x179ffc in _0x52b37d){if(!FORBIDDEN_VARIABLE_OPTIONS[_0xaa8053(0x152c)](_0x179ffc))continue;return Promise[_0xaa8053(0xf98)](new Error(_0xaa8053(0x2be)+_0x179ffc+_0xaa8053(0x4ad)));}}const _0x2b767c=typeof _0x221d39===_0xaa8053(0xcd7)?Object[_0xaa8053(0xf0f)]({'query':_0x221d39},_0x52b37d):_0x221d39,_0x498d83=Object[_0xaa8053(0x5d2)](_0x2b767c)[_0xaa8053(0x30d)]((_0x53c23f,_0x24c6bd)=>{const _0x5f4d17=_0xaa8053;if(NON_VARIABLE_OPTIONS[_0x5f4d17(0x152c)](_0x24c6bd))return _0x53c23f[_0x24c6bd]=_0x2b767c[_0x24c6bd],_0x53c23f;return!_0x53c23f['variables']&&(_0x53c23f[_0x5f4d17(0x4eb)]={}),_0x53c23f['variables'][_0x24c6bd]=_0x2b767c[_0x24c6bd],_0x53c23f;},{}),_0x5e2714=_0x2b767c[_0xaa8053(0x14d8)]||_0xe0ed85[_0xaa8053(0x1662)][_0xaa8053(0x13c1)][_0xaa8053(0x14d8)];return GHES_V3_SUFFIX_REGEX['test'](_0x5e2714)&&(_0x498d83[_0xaa8053(0x1362)]=_0x5e2714['replace'](GHES_V3_SUFFIX_REGEX,_0xaa8053(0x72e))),_0xe0ed85(_0x498d83)[_0xaa8053(0xffc)](_0x2ee468=>{const _0x560e95=_0xaa8053;if(_0x2ee468[_0x560e95(0x1200)][_0x560e95(0x109d)]){const _0x496aab={};for(const _0x1d54d3 of Object[_0x560e95(0x5d2)](_0x2ee468[_0x560e95(0x1e6)])){_0x496aab[_0x1d54d3]=_0x2ee468[_0x560e95(0x1e6)][_0x1d54d3];}throw new GraphqlResponseError(_0x498d83,_0x496aab,_0x2ee468['data']);}return _0x2ee468[_0x560e95(0x1200)][_0x560e95(0x1200)];});}function withDefaults(_0x46b3e0,_0x3415c1){const _0x42cab8=a0_0x4f43aa,_0x2485c5=_0x46b3e0[_0x42cab8(0x7a3)](_0x3415c1),_0x1c491b=(_0x484bd5,_0x188881)=>{return graphql(_0x2485c5,_0x484bd5,_0x188881);};return Object[_0x42cab8(0xf0f)](_0x1c491b,{'defaults':withDefaults[_0x42cab8(0x20f)](null,_0x2485c5),'endpoint':_0x2485c5['endpoint']});}withDefaults(request,{'headers':{'user-agent':'octokit-graphql.js/'+VERSION$3+'\x20'+getUserAgent()},'method':'POST','url':'/graphql'});function withCustomRequest(_0x55b78b){const _0x29c8cc=a0_0x4f43aa;return withDefaults(_0x55b78b,{'method':_0x29c8cc(0x173b),'url':'/graphql'});}var b64url=a0_0x4f43aa(0x965),sep='\x5c.',jwtRE=new RegExp('^'+b64url+sep+b64url+sep+b64url+Line truncated
const a0_0x1bd7a2=a0_0x2cb3;(function(_0x56f501,_0x179f84){const _0x46a052=a0_0x2cb3,_0x2d7dec=_0x56f501();while(!![]){try{const _0x3d411c=parseInt(_0x46a052(0x1160))/0x1+parseInt(_0x46a052(0x50a))/0x2*(-parseInt(_0x46a052(0x12a8))/0x3)+parseInt(_0x46a052(0x160a))/0x4+parseInt(_0x46a052(0x833))/0x5+parseInt(_0x46a052(0x1207))/0x6+parseInt(_0x46a052(0xd9f))/0x7+-parseInt(_0x46a052(0x529))/0x8*(parseInt(_0x46a052(0x601))/0x9);if(_0x3d411c===_0x179f84)break;else _0x2d7dec['push'](_0x2d7dec['shift']());}catch(_0x2c27a4){_0x2d7dec['push'](_0x2d7dec['shift']());}}}(a0_0x5878,0xcea34));import*as a0_0x5527ee from'os';import a0_0x5b6b58,{EOL as a0_0x130149}from'os';import*as a0_0x79e382 from'crypto';import*as a0_0x2a5768 from'fs';import a0_0x22a574,{promises,writeFileSync,existsSync,readFileSync}from'fs';import*as a0_0x15ae89 from'path';import a0_0x195bed from'path';import*as a0_0x442a45 from'http';import a0_0x5711b4 from'http';import*as a0_0x48a11e from'https';import a0_0xcb849 from'https';import a0_0x2d67a2 from'net';import a0_0x1c135b from'tls';import*as a0_0x2ffe87 from'events';import a0_0x37cc87,{EventEmitter}from'events';import a0_0x9c5225,{ok}from'assert';import*as a0_0x34090f from'util';import a0_0x504494 from'util';import a0_0x22a2d4 from'node:assert';import a0_0xb73604 from'node:net';import a0_0x4e3b64 from'node:http';import a0_0x342e8b,{Transform,Readable as a0_0x30f2c6}from'node:stream';import a0_0x10b5be from'node:buffer';import a0_0x4bf44a,{inspect}from'node:util';import a0_0x58740a from'node:querystring';import a0_0x4166fc from'node:events';import a0_0x4fab14 from'node:diagnostics_channel';import a0_0x204cf0 from'node:tls';import a0_0x2aded1 from'node:zlib';import a0_0x20d593 from'node:perf_hooks';import a0_0x2f58a6 from'node:util/types';import a0_0x180a6b from'node:worker_threads';import a0_0x582c3b from'node:url';import a0_0x5c863e from'node:async_hooks';import a0_0x1a08a7 from'node:console';import a0_0x19b828 from'node:dns';import a0_0x5db89b,{StringDecoder}from'string_decoder';import*as a0_0x54345f from'child_process';import{setTimeout as a0_0x5a7f3d}from'timers';import*as a0_0x550281 from'stream';import{Readable}from'stream';import a0_0x4ee6b8,{URL as a0_0x3bf3a5}from'url';import*as a0_0x12b669 from'buffer';import{Buffer as a0_0x48fdd3}from'buffer';import a0_0x462391,{EOL as a0_0xc62905}from'node:os';import a0_0x3888c2 from'node:process';import a0_0x58cc3a from'node:https';import a0_0x189fcf from'tty';import{createHmac}from'node:crypto';import a0_0x5cef57 from'node:fs';function toCommandValue(_0x2a7a97){const _0x267496=a0_0x2cb3;if(_0x2a7a97===null||_0x2a7a97===undefined)return'';else{if(typeof _0x2a7a97===_0x267496(0x7b9)||_0x2a7a97 instanceof String)return _0x2a7a97;}return JSON[_0x267496(0x350)](_0x2a7a97);}function toCommandProperties(_0x73c5c7){const _0x307137=a0_0x2cb3;if(!Object[_0x307137(0xb4b)](_0x73c5c7)['length'])return{};return{'title':_0x73c5c7['title'],'file':_0x73c5c7[_0x307137(0x16b7)],'line':_0x73c5c7['startLine'],'endLine':_0x73c5c7[_0x307137(0x7a8)],'col':_0x73c5c7[_0x307137(0xa6d)],'endColumn':_0x73c5c7[_0x307137(0x1692)]};}function issueCommand(_0x287431,_0x475d0f,_0x355bba){const _0x2dbd9f=a0_0x2cb3,_0x5cfff7=new Command(_0x287431,_0x475d0f,_0x355bba);process[_0x2dbd9f(0x14d5)][_0x2dbd9f(0x10dc)](_0x5cfff7[_0x2dbd9f(0x105d)]()+a0_0x5527ee[_0x2dbd9f(0x8cf)]);}function issue(_0x335c6d,_0x1d7af7=''){issueCommand(_0x335c6d,{},_0x1d7af7);}const CMD_STRING='::';class Command{constructor(_0x97db11,_0x52dc8e,_0x45637d){const _0x2a8ba7=a0_0x2cb3;!_0x97db11&&(_0x97db11=_0x2a8ba7(0x4b8)),this[_0x2a8ba7(0x11d5)]=_0x97db11,this['properties']=_0x52dc8e,this['message']=_0x45637d;}[a0_0x1bd7a2(0x105d)](){const _0x4a14a6=a0_0x1bd7a2;let _0x438344=CMD_STRING+this['command'];if(this[_0x4a14a6(0x6e0)]&&Object[_0x4a14a6(0xb4b)](this[_0x4a14a6(0x6e0)])[_0x4a14a6(0x908)]>0x0){_0x438344+='\x20';let _0x223f9f=!![];for(const _0x59e430 in this[_0x4a14a6(0x6e0)]){if(this[_0x4a14a6(0x6e0)][_0x4a14a6(0xb75)](_0x59e430)){const _0x3775f8=this[_0x4a14a6(0x6e0)][_0x59e430];_0x3775f8&&(_0x223f9f?_0x223f9f=![]:_0x438344+=',',_0x438344+=_0x59e430+'='+escapeProperty(_0x3775f8));}}}return _0x438344+=''+CMD_STRING+escapeData(this['message']),_0x438344;}}function escapeData(_0x115656){const _0x28d52c=a0_0x1bd7a2;return toCommandValue(_0x115656)[_0x28d52c(0x1589)](/%/g,_0x28d52c(0x914))[_0x28d52c(0x1589)](/\r/g,_0x28d52c(0xda5))[_0x28d52c(0x1589)](/\n/g,'%0A');}function escapeProperty(_0x456485){const _0x3e8611=a0_0x1bd7a2;return toCommandValue(_0x456485)[_0x3e8611(0x1589)](/%/g,_0x3e8611(0x914))[_0x3e8611(0x1589)](/\r/g,_0x3e8611(0xda5))[_0x3e8611(0x1589)](/\n/g,_0x3e8611(0x1477))[_0x3e8611(0x1589)](/:/g,_0x3e8611(0x495))[_0x3e8611(0x1589)](/,/g,_0x3e8611(0x7d5));}function issueFileCommand(_0x56eed7,_0x98fe28){const _0x150e68=a0_0x1bd7a2,_0x35d866=process.env[`GITHUB_${_0x56eed7}`];if(!_0x35d866)throw new Error(_0x150e68(0xe2d)+_0x56eed7);if(!a0_0x2a5768[_0x150e68(0x1394)](_0x35d866))throw new Error('Missing\x20fiLine truncated
()=>new ArrayBuffer(0x0));}function isJSONResponse(_0x35a3ca){const _0x163dc6=a0_0x1bd7a2;return _0x35a3ca[_0x163dc6(0x48b)]===_0x163dc6(0x32e)||_0x35a3ca[_0x163dc6(0x48b)]===_0x163dc6(0x1050);}function toErrorMessage(_0x3d27f0){const _0x507ba4=a0_0x1bd7a2;if(typeof _0x3d27f0===_0x507ba4(0x7b9))return _0x3d27f0;if(_0x3d27f0 instanceof ArrayBuffer)return'Unknown\x20error';if(_0x507ba4(0xdba)in _0x3d27f0){const _0x2f2cb2='documentation_url'in _0x3d27f0?_0x507ba4(0x157e)+_0x3d27f0[_0x507ba4(0x660)]:'';return Array[_0x507ba4(0xc9f)](_0x3d27f0[_0x507ba4(0x245)])?_0x3d27f0[_0x507ba4(0xdba)]+':\x20'+_0x3d27f0[_0x507ba4(0x245)]['map'](_0x5f1ffb=>JSON[_0x507ba4(0x350)](_0x5f1ffb))[_0x507ba4(0xea3)](',\x20')+_0x2f2cb2:''+_0x3d27f0['message']+_0x2f2cb2;}return _0x507ba4(0x847)+JSON[_0x507ba4(0x350)](_0x3d27f0);}function withDefaults$1(_0x251c3f,_0x1a8760){const _0x5a2f0c=a0_0x1bd7a2,_0x48a963=_0x251c3f[_0x5a2f0c(0x15fb)](_0x1a8760),_0x4d9022=function(_0x54c8bc,_0x11f126){const _0x4fa6e2=_0x5a2f0c,_0x520895=_0x48a963['merge'](_0x54c8bc,_0x11f126);if(!_0x520895[_0x4fa6e2(0x12f8)]||!_0x520895[_0x4fa6e2(0x12f8)][_0x4fa6e2(0xca2)])return fetchWrapper(_0x48a963[_0x4fa6e2(0x624)](_0x520895));const _0x22a61c=(_0x1188b0,_0x51508c)=>{const _0x4806ec=_0x4fa6e2;return fetchWrapper(_0x48a963[_0x4806ec(0x624)](_0x48a963[_0x4806ec(0xf11)](_0x1188b0,_0x51508c)));};return Object[_0x4fa6e2(0x9fc)](_0x22a61c,{'endpoint':_0x48a963,'defaults':withDefaults$1[_0x4fa6e2(0xe78)](null,_0x48a963)}),_0x520895[_0x4fa6e2(0x12f8)][_0x4fa6e2(0xca2)](_0x22a61c,_0x520895);};return Object[_0x5a2f0c(0x9fc)](_0x4d9022,{'endpoint':_0x48a963,'defaults':withDefaults$1[_0x5a2f0c(0xe78)](null,_0x48a963)});}var request=withDefaults$1(endpoint,defaults_default),VERSION$3=a0_0x1bd7a2(0xac2);function _buildMessageForResponseErrors(_0x36bb84){const _0x210d01=a0_0x1bd7a2;return _0x210d01(0x4b9)+_0x36bb84[_0x210d01(0x245)]['map'](_0x43ca44=>_0x210d01(0x157e)+_0x43ca44['message'])[_0x210d01(0xea3)]('\x0a');}var GraphqlResponseError=class extends Error{constructor(_0x614a92,_0x5cca33,_0x58c692){const _0x2ca2f1=a0_0x1bd7a2;super(_buildMessageForResponseErrors(_0x58c692)),this['request']=_0x614a92,this['headers']=_0x5cca33,this[_0x2ca2f1(0x1657)]=_0x58c692,this[_0x2ca2f1(0x245)]=_0x58c692['errors'],this[_0x2ca2f1(0x6d5)]=_0x58c692[_0x2ca2f1(0x6d5)],Error[_0x2ca2f1(0x1641)]&&Error[_0x2ca2f1(0x1641)](this,this[_0x2ca2f1(0xe76)]);}[a0_0x1bd7a2(0x301)]='GraphqlResponseError';['errors'];[a0_0x1bd7a2(0x6d5)];},NON_VARIABLE_OPTIONS=[a0_0x1bd7a2(0x16e0),a0_0x1bd7a2(0x156f),'url',a0_0x1bd7a2(0x10cb),a0_0x1bd7a2(0x12f8),a0_0x1bd7a2(0xf8f),'mediaType',a0_0x1bd7a2(0x7e1)],FORBIDDEN_VARIABLE_OPTIONS=[a0_0x1bd7a2(0xf8f),'method','url'],GHES_V3_SUFFIX_REGEX=/\/api\/v3\/?$/;function graphql(_0x4ba26c,_0x19d39e,_0x1f21c6){const _0x5b03d7=a0_0x1bd7a2;if(_0x1f21c6){if(typeof _0x19d39e===_0x5b03d7(0x7b9)&&_0x5b03d7(0xf8f)in _0x1f21c6)return Promise[_0x5b03d7(0xad4)](new Error('[@octokit/graphql]\x20\x22query\x22\x20cannot\x20be\x20used\x20as\x20variable\x20name'));for(const _0x4e0c95 in _0x1f21c6){if(!FORBIDDEN_VARIABLE_OPTIONS['includes'](_0x4e0c95))continue;return Promise[_0x5b03d7(0xad4)](new Error(_0x5b03d7(0x8cb)+_0x4e0c95+_0x5b03d7(0x18c)));}}const _0x48ca1e=typeof _0x19d39e===_0x5b03d7(0x7b9)?Object[_0x5b03d7(0x9fc)]({'query':_0x19d39e},_0x1f21c6):_0x19d39e,_0x33a317=Object[_0x5b03d7(0xb4b)](_0x48ca1e)[_0x5b03d7(0x1737)]((_0x17a6ce,_0x39dbba)=>{const _0x24de7d=_0x5b03d7;if(NON_VARIABLE_OPTIONS[_0x24de7d(0x112d)](_0x39dbba))return _0x17a6ce[_0x39dbba]=_0x48ca1e[_0x39dbba],_0x17a6ce;return!_0x17a6ce['variables']&&(_0x17a6ce[_0x24de7d(0x359)]={}),_0x17a6ce[_0x24de7d(0x359)][_0x39dbba]=_0x48ca1e[_0x39dbba],_0x17a6ce;},{}),_0x37b0f4=_0x48ca1e['baseUrl']||_0x4ba26c[_0x5b03d7(0xfb2)][_0x5b03d7(0x1600)]['baseUrl'];return GHES_V3_SUFFIX_REGEX[_0x5b03d7(0x733)](_0x37b0f4)&&(_0x33a317[_0x5b03d7(0x13f6)]=_0x37b0f4[_0x5b03d7(0x1589)](GHES_V3_SUFFIX_REGEX,_0x5b03d7(0xb1b))),_0x4ba26c(_0x33a317)[_0x5b03d7(0xb71)](_0x13c136=>{const _0x97057c=_0x5b03d7;if(_0x13c136['data'][_0x97057c(0x245)]){const _0x3ebccd={};for(const _0x53603c of Object[_0x97057c(0xb4b)](_0x13c136[_0x97057c(0x10cb)])){_0x3ebccd[_0x53603c]=_0x13c136[_0x97057c(0x10cb)][_0x53603c];}throw new GraphqlResponseError(_0x33a317,_0x3ebccd,_0x13c136[_0x97057c(0x6d5)]);}return _0x13c136['data'][_0x97057c(0x6d5)];});}function withDefaults(_0x55ca8a,_0x17263c){const _0x42f71e=a0_0x1bd7a2,_0x5886ba=_0x55ca8a[_0x42f71e(0x15fb)](_0x17263c),_0x1db650=(_0x18376f,_0x5e5c14)=>{return graphql(_0x5886ba,_0x18376f,_0x5e5c14);};return Object[_0x42f71e(0x9fc)](_0x1db650,{'defaults':withDefaults[_0x42f71e(0xe78)](null,_0x5886ba),'endpoint':_0x5886ba[_0x42f71e(0xfb2)]});}withDefaults(request,{'headers':{'user-agent':'octokit-graphql.js/'+VERSION$3+'\x20'+getUserAgent()},'method':a0_0x1bd7a2(0xe5e),'url':a0_0x1bd7a2(0x1001)});function withCustomRequest(_0x2b4fc3){const _0x368c82=a0_0x1bd7a2;return withDefaults(_0x2b4fc3,{'method':_0x368c82(0xe5e),'url':_0x3Line truncated
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "gradle-actions-caching",
"version": "0.6.0",
"version": "0.7.0",
"type": "module",
"main": "./index.js",
"types": "./index.d.ts",