From 80a0a198dd1882f91c6f99fc5e84ba4dc2487813 Mon Sep 17 00:00:00 2001 From: ethernet Date: Tue, 11 Aug 2026 23:06:42 -0400 Subject: [PATCH] ci(install-e2e): plan chart on the run summary - combination x tag markdown table generate-e2e-matrix.mjs grows --format markdown: one row per {os, install -> update} combination, one column per starting tag, appended to GITHUB_STEP_SUMMARY by the expand job. Cells mark dispatched legs; run-vs-grey stays the run workflows' call, so the only special cell is pre-desktop (the one annotation the plan owns). JSON mode unchanged. --- .github/workflows/install-e2e.yml | 5 +++ scripts/sandbox/generate-e2e-matrix.mjs | 53 ++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/.github/workflows/install-e2e.yml b/.github/workflows/install-e2e.yml index 8f5fb3aa9e..ad7d901b91 100644 --- a/.github/workflows/install-e2e.yml +++ b/.github/workflows/install-e2e.yml @@ -134,6 +134,11 @@ jobs: for key in linux windows macos; do echo "$key=$(echo "$matrices" | node -e 'let d="";process.stdin.on("data",c=>d+=c).on("end",()=>console.log(JSON.stringify(JSON.parse(d)[process.argv[1]])))' "$key")" >> "$GITHUB_OUTPUT" done + # The plan, human-readable: a combination x starting-tag chart on + # the run's summary page. + node scripts/sandbox/generate-e2e-matrix.mjs \ + --tags '${{ needs.pick-releases.outputs.tags }}' \ + --format markdown >> "$GITHUB_STEP_SUMMARY" linux: name: ${{ matrix.name }} diff --git a/scripts/sandbox/generate-e2e-matrix.mjs b/scripts/sandbox/generate-e2e-matrix.mjs index 6abbdabb38..05301f22e1 100644 --- a/scripts/sandbox/generate-e2e-matrix.mjs +++ b/scripts/sandbox/generate-e2e-matrix.mjs @@ -165,14 +165,65 @@ export function buildMatrices(envs, tags) { return byOs; } +/** + * Render the plan as a markdown cross-table for $GITHUB_STEP_SUMMARY: + * one row per {os, install -> update} combination, one column per + * starting tag. Every cell is dispatched; whether it RUNS or greys out + * is the run workflow's call (capability lives there, not here), so the + * chart only distinguishes the one thing the plan itself knows: windows + * desktop-surface legs from tags that predate the desktop app. + * + * @param {{os: Os, install: string, update: string}[]} envs + * @param {TagAnnotation[]} tags + * @returns {string} + */ +export function renderMarkdownPlan(envs, tags) { + const needsDesktop = (/** @type {string} */ m) => + m.startsWith('desktop-installer') || m === 'app-update'; + const lines = [ + '### Install & Update E2E plan', + '', + `${envs.length} combinations x ${tags.length} starting tags = ${envs.length * tags.length} legs`, + '', + `| combination | ${tags.map((t) => t.ref).join(' | ')} |`, + `|---|${tags.map(() => '---').join('|')}|`, + ]; + for (const env of envs) { + const cells = tags.map((tag) => { + if ( + env.os === 'windows' && !tag.desktop && + (needsDesktop(env.install) || needsDesktop(env.update)) + ) { + return 'pre-desktop'; + } + return '✅'; + }); + lines.push(`| \`${env.os}: ${env.install} -> ${env.update}\` | ${cells.join(' | ')} |`); + } + lines.push( + '', + '✅ dispatched -- the OS run workflow decides run vs native skip', + '(unimplemented method pairs grey out there). `pre-desktop`: the tag', + "ships no desktop app, so desktop-surface legs grey out regardless.", + '', + ); + return lines.join('\n'); +} + function main() { const { values } = parseArgs({ options: { tags: { type: 'string', default: '[]' }, + format: { type: 'string', default: 'json' }, }, }); const tags = /** @type {TagAnnotation[]} */ (JSON.parse(values.tags)); - const matrices = buildMatrices(generateEnvironments(SPEC), tags); + const envs = generateEnvironments(SPEC); + if (values.format === 'markdown') { + process.stdout.write(renderMarkdownPlan(envs, tags)); + return; + } + const matrices = buildMatrices(envs, tags); process.stdout.write(`${JSON.stringify(matrices, null, 2)}\n`); }