@@ -241,6 +241,7 @@ jobs:
241241 with :
242242 script : |
243243 const fs = require('fs');
244+ const path = require('path');
244245 const prNumber = parseInt('${{ needs.gate.outputs.pr_number }}');
245246 const sha = '${{ needs.gate.outputs.pr_head_sha }}';
246247 const runId = context.runId;
@@ -282,27 +283,67 @@ jobs:
282283 console.log(`Could not read results: ${e.message}`);
283284 }
284285
285- // Check which Grafana artifacts exist
286- const hasSnapshotJson = fs.existsSync('/tmp/benchmark-grafana-snapshot.json');
287- const hasPanels = fs.existsSync('/tmp/benchmark-panels') &&
288- fs.readdirSync('/tmp/benchmark-panels').some(f => f.endsWith('.png'));
286+ // Upload panel PNGs as release assets and collect URLs for embedding
287+ let panelImages = '';
288+ const panelDir = '/tmp/benchmark-panels';
289+ const hasPanels = fs.existsSync(panelDir) &&
290+ fs.readdirSync(panelDir).some(f => f.endsWith('.png'));
291+
292+ if (hasPanels) {
293+ const pngs = fs.readdirSync(panelDir).filter(f => f.endsWith('.png')).sort();
294+ const tag = `benchmark-run-${runId}`;
295+
296+ try {
297+ // Create a lightweight release to host panel images
298+ const release = await github.rest.repos.createRelease({
299+ owner: context.repo.owner,
300+ repo: context.repo.repo,
301+ tag_name: tag,
302+ name: `Benchmark panels (PR #${prNumber}, ${sha.substring(0, 7)})`,
303+ body: `Auto-generated by benchmark CI run #${runId}`,
304+ draft: false,
305+ prerelease: true
306+ });
289307
308+ const imageUrls = [];
309+ for (const png of pngs) {
310+ const filePath = path.join(panelDir, png);
311+ const fileData = fs.readFileSync(filePath);
312+ const asset = await github.rest.repos.uploadReleaseAsset({
313+ owner: context.repo.owner,
314+ repo: context.repo.repo,
315+ release_id: release.data.id,
316+ name: png,
317+ data: fileData,
318+ headers: { 'content-type': 'image/png' }
319+ });
320+ const title = png.replace('panel-', '').replace('.png', '').replace(/-/g, ' ');
321+ imageUrls.push(`#### ${title}\n`);
322+ console.log(`Uploaded ${png}: ${asset.data.browser_download_url}`);
323+ }
324+
325+ if (imageUrls.length > 0) {
326+ panelImages = `\n\n<details>\n<summary>Dashboard Panels (${imageUrls.length})</summary>\n\n${imageUrls.join('\n\n')}\n\n</details>`;
327+ }
328+ } catch (e) {
329+ console.log(`Could not upload panel images: ${e.message}`);
330+ }
331+ }
332+
333+ // Check for Grafana snapshot
334+ const hasSnapshotJson = fs.existsSync('/tmp/benchmark-grafana-snapshot.json');
290335 let artifactsSection = '';
291336 if (hasSnapshotJson || hasPanels) {
292337 const items = [];
293338 if (hasSnapshotJson) {
294- items.push('Grafana snapshot JSON (re-import via `POST /api/snapshots`)');
295- }
296- if (hasPanels) {
297- const pngs = fs.readdirSync('/tmp/benchmark-panels').filter(f => f.endsWith('.png'));
298- items.push(`${pngs.length} dashboard panel PNGs`);
339+ items.push('Grafana snapshot JSON');
299340 }
300- artifactsSection = `\n\n📎 **[Download artifacts](${artifactUrl})** — ${ items.join(', ')}`;
341+ artifactsSection = `\n\n📎 **[Download artifacts](${artifactUrl})**${items.length ? ' — ' + items.join(', ') : '' }`;
301342 }
302343
303344 const body = `## Benchmark: scale-up-latency (Kind)
304345
305- ${resultsTable}${artifactsSection}
346+ ${resultsTable}${panelImages}${ artifactsSection}
306347
307348 <details>
308349 <summary>Environment</summary>
0 commit comments