From 7a65f91307cbbc21e8f685c85b3382e7896c710f Mon Sep 17 00:00:00 2001 From: Aaron Powell Date: Fri, 10 Jul 2026 13:55:17 +1000 Subject: [PATCH] Fix external plugin gate manifest paths and diagnostics Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../external-plugin-pr-quality-gates.yml | 35 +++++++++++++++++++ eng/external-plugin-quality-gates.mjs | 2 +- eng/external-plugin-validation.mjs | 2 +- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/.github/workflows/external-plugin-pr-quality-gates.yml b/.github/workflows/external-plugin-pr-quality-gates.yml index f194e6e39..cb05e1390 100644 --- a/.github/workflows/external-plugin-pr-quality-gates.yml +++ b/.github/workflows/external-plugin-pr-quality-gates.yml @@ -200,6 +200,18 @@ jobs: : qualityResult.overall_status === 'pass' || !shouldRun ? '## ✅ External plugin PR checks passed' : '## ⚠️ External plugin PR checks need maintainer follow-up'; + const formatGateOutput = (pluginName, gateName, gateStatus, rawOutput) => { + const output = String(rawOutput || '').trim() || '_No output captured._'; + return [ + '
', + `${pluginName} — ${gateName} (${gateStatus || 'not_run'})`, + '', + '```text', + output, + '```', + '
', + ].join('\n'); + }; const rows = checkedPlugins.length > 0 ? checkedPlugins.map((entry) => { @@ -211,6 +223,21 @@ jobs: return `| ${name} | ${quality.vally_lint_status || 'not_run'} | ${quality.smoke_status || 'not_run'} | ${quality.overall_status || 'not_run'} | ${sourceCell} |`; }) : ['| _none_ | not_run | not_run | not_run | _n/a_ |']; + const failureDetails = checkedPlugins.flatMap((entry) => { + const name = String(entry?.name || 'unknown'); + const quality = entry?.quality || {}; + const shouldShowVally = quality.vally_lint_status === 'fail' || quality.vally_lint_status === 'infra_error' || String(quality.vally_lint_output || '').trim().length > 0; + const shouldShowSmoke = quality.smoke_status === 'fail' || quality.smoke_status === 'infra_error' || String(quality.smoke_output || '').trim().length > 0; + + const details = []; + if (shouldShowVally) { + details.push(formatGateOutput(name, 'vally lint', quality.vally_lint_status, quality.vally_lint_output)); + } + if (shouldShowSmoke) { + details.push(formatGateOutput(name, 'install smoke test', quality.smoke_status, quality.smoke_output)); + } + return details; + }); const body = [ marker, @@ -225,6 +252,14 @@ jobs: '|---|---|---|---|---|', ...rows, '', + ...(failureDetails.length > 0 + ? [ + '### Gate output details', + '', + ...failureDetails, + '', + ] + : []), String(qualityResult.summary || '').trim() || '_No summary provided._', ].join('\n'); diff --git a/eng/external-plugin-quality-gates.mjs b/eng/external-plugin-quality-gates.mjs index ce866331b..6b857be09 100644 --- a/eng/external-plugin-quality-gates.mjs +++ b/eng/external-plugin-quality-gates.mjs @@ -140,7 +140,7 @@ function cloneSubmissionRepository(workDir, plugin) { // NOTE: Keep in sync with EXTERNAL_PLUGIN_ROOT_MANIFEST_PATHS in external-plugin-validation.mjs const PLUGIN_JSON_CANDIDATES = [ [".github", "plugin", "plugin.json"], - [".plugins", "plugin.json"], + [".plugin", "plugin.json"], ["plugin.json"], ]; diff --git a/eng/external-plugin-validation.mjs b/eng/external-plugin-validation.mjs index 87bc271ee..846458832 100644 --- a/eng/external-plugin-validation.mjs +++ b/eng/external-plugin-validation.mjs @@ -27,7 +27,7 @@ export const EXTERNAL_PLUGIN_POLICIES = Object.freeze({ const EXTERNAL_PLUGIN_ROOT_MANIFEST_PATHS = Object.freeze([ "plugin.json", ".github/plugin/plugin.json", - ".plugins/plugin.json", + ".plugin/plugin.json", ]); function resolvePolicy(policy) {