Refine caching report layout and copy

- Render the heading as <h4> so it displays as a heading (markdown
  ATX headings were rendered literally in the Job Summary).
- Heading reads "Gradle Caching — <Enhanced|Basic> Provider"; drop the
  status suffix since status now lives inside the details expando.
- Provider note: lead with a linked "Enhanced Caching" / "Basic Caching"
  to the docs; the proprietary provider name is now inline code.
- Move the status and cache-cleanup messages inside the details expando.
  The clickable summary now reads "Entries: N restored, M saved
  (expand for more details)".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Daz DeBoer
2026-06-11 22:47:32 -06:00
parent cbc6f4a545
commit f5cb57ae79
2 changed files with 41 additions and 28 deletions
+21 -13
View File
@@ -34,13 +34,16 @@ const CLEANUP_COPY: Record<CacheCleanupStatus, string> = {
* provider note, and (when there are entries) an expandable details section.
*/
export function renderCachingReport(report: CacheReport, providerNote?: ProviderNote): string {
const active = isActive(report.status)
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),
STATUS_COPY[report.status],
report.status === 'enabled' ? renderCleanupLine(report.cleanup) : undefined,
active ? renderProviderNote(providerNote) : undefined,
report.entries.length > 0 ? renderDetails(report) : undefined
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`
}
@@ -53,14 +56,17 @@ function renderHeading(status: CacheStatus, providerNote?: ProviderNote): string
if (!isActive(status)) {
const label =
status === 'disabled-existing-home' ? 'Skipped' : status === 'not-available' ? 'Unavailable' : 'Disabled'
return `#### Gradle Caching — ${label}`
return `<h4>Gradle Caching — ${label}</h4>`
}
const icon = providerNote?.kind === 'basic' ? '🛡️ ' : providerNote?.kind === 'enhanced' ? '⚡ ' : ''
const provider =
providerNote?.kind === 'basic' ? ' — Basic' : providerNote?.kind === 'enhanced' ? ' — Enhanced' : ''
const suffix = status === 'read-only' ? ' (read-only)' : status === 'write-only' ? ' (write-only)' : ''
return `#### ${icon}Gradle Caching${provider}${suffix}`
providerNote?.kind === 'basic'
? ' — Basic Provider'
: providerNote?.kind === 'enhanced'
? ' — Enhanced Provider'
: ''
return `<h4>${icon}Gradle Caching${provider}</h4>`
}
function renderCleanupLine(cleanup?: CacheCleanupStatus): string | undefined {
@@ -72,18 +78,20 @@ function renderProviderNote(providerNote?: ProviderNote): string | undefined {
return undefined
}
if (providerNote.kind === 'enhanced') {
return `Optimized caching is provided by the proprietary **[gradle-actions-caching](${DOCS}#enhanced-caching)** provider. See [DISTRIBUTION.md](${DISTRIBUTION}) for terms of use and opt-out instructions.`
return `**[Enhanced Caching](${DOCS}#enhanced-caching)** is provided by the proprietary \`gradle-actions-caching\` provider. See [DISTRIBUTION.md](${DISTRIBUTION}) for terms of use and opt-out instructions.`
}
return `This build uses the basic open-source caching provider. For faster builds and advanced features, consider the **[Enhanced Caching](${DOCS}#enhanced-caching)** provider. See [DISTRIBUTION.md](${DISTRIBUTION}) for details.`
return `**[Basic Caching](${DOCS}#basic-caching)** uses the basic open-source provider. For faster builds and advanced features, consider the **[Enhanced Caching](${DOCS}#enhanced-caching)** provider. See [DISTRIBUTION.md](${DISTRIBUTION}) for details.`
}
function renderDetails(report: CacheReport): string {
const restored = report.entries.filter(entry => entry.restoredKey).length
const saved = report.entries.filter(entry => entry.savedKey).length
const summary = `Cache entry details — ${restored} restored, ${saved} saved`
const summary = `Entries: ${restored} restored, ${saved} saved (expand for more details)`
const cleanup = report.status === 'enabled' ? renderCleanupLine(report.cleanup) : undefined
const table = renderEntryTable(report.entries)
const body = [table, `<pre>\n${renderEntryDetails(report.entries)}</pre>`].filter(Boolean).join('\n')
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>
+20 -15
View File
@@ -23,27 +23,31 @@ function entry(overrides: Partial<CacheReport['entries'][number]> = {}): CacheRe
}
describe('renderCachingReport', () => {
it('renders an enhanced read-only report with heading, status, note and details', () => {
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('#### ⚡ Gradle Caching — Enhanced (read-only)')
expect(md).toContain('Cache was read-only')
expect(md).toContain('gradle-actions-caching')
expect(md).toContain('<h4>⚡ Gradle Caching — Enhanced Provider</h4>')
expect(md).toContain('[Enhanced Caching]')
expect(md).toContain('`gradle-actions-caching`')
expect(md).toContain('DISTRIBUTION.md')
expect(md).toContain('<details>')
expect(md).toContain('Cache entry details — 1 restored, 1 saved')
expect(md).toContain('<summary>Entries: 1 restored, 1 saved (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 a cleanup line and metrics table', () => {
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('#### ⚡ Gradle Caching — Enhanced')
expect(md).not.toContain('(read-only)')
expect(md).toContain('Cache cleanup')
expect(md).toContain('<h4>⚡ Gradle Caching — Enhanced Provider</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')
})
@@ -64,20 +68,21 @@ describe('renderCachingReport', () => {
}
const md = renderCachingReport(report, BASIC)
expect(md).toContain('#### 🛡️ Gradle Caching — Basic (read-only)')
expect(md).toContain('Enhanced Caching')
expect(md).toContain('<h4>🛡️ Gradle Caching — Basic Provider</h4>')
expect(md).toContain('[Basic Caching]')
expect(md).toContain('[Enhanced Caching]')
expect(md).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('Cache entry details — 1 restored, 0 saved')
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('#### Gradle Caching — Disabled')
expect(md).toContain('<h4>Gradle Caching — Disabled</h4>')
expect(md).toContain('Caching was disabled')
expect(md).not.toContain('<details>')
expect(md).not.toContain('DISTRIBUTION.md')
@@ -87,7 +92,7 @@ describe('renderCachingReport', () => {
const report: CacheReport = {status: 'disabled-existing-home', entries: []}
const md = renderCachingReport(report, ENHANCED)
expect(md).toContain('#### Gradle Caching — Skipped')
expect(md).toContain('<h4>Gradle Caching — Skipped</h4>')
expect(md).toContain('pre-existing Gradle User Home')
expect(md).not.toContain('<details>')
// no provider note for non-active states
@@ -98,7 +103,7 @@ describe('renderCachingReport', () => {
const report: CacheReport = {status: 'not-available', entries: []}
const md = renderCachingReport(report, ENHANCED)
expect(md).toContain('#### Gradle Caching — Unavailable')
expect(md).toContain('<h4>Gradle Caching — Unavailable</h4>')
expect(md).not.toContain('<details>')
})
})