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:
Daz DeBoer
2026-06-12 15:21:52 +00:00
committed by GitHub
co-authored by Bot Githubaction Claude Opus 4.8
parent 8b6cdb5f58
commit 97715a29bc
13 changed files with 502 additions and 92 deletions
+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'})
})
})
})