Skip to content

Commit 61dda50

Browse files
aaronpowellCopilot
andauthored
Add version parity checks to external plugin quality gates (#2307)
* Add external plugin version-match gate Enforce external.json version matching against remote plugin.json for source ref and/or sha in shared quality gates, and surface the new gate status/output in intake and PR workflows. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8aa3e98d-1873-4cab-8866-1b2efd0f24ad * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent 49c6c0f commit 61dda50

6 files changed

Lines changed: 215 additions & 14 deletions

.github/workflows/external-plugin-command-router.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,8 +746,9 @@ jobs:
746746
if (process.env.QUALITY_JOB_RESULT === 'failure' || process.env.QUALITY_JOB_RESULT === 'cancelled') {
747747
qualityResult = {
748748
overall_status: 'infra_error',
749-
skill_validator_status: 'infra_error',
749+
vally_lint_status: 'infra_error',
750750
smoke_status: 'infra_error',
751+
version_match_status: 'infra_error',
751752
failure_class: 'infra',
752753
summary: 'Quality-gate workflow failed unexpectedly. Re-run intake to retry.',
753754
};
@@ -756,8 +757,9 @@ jobs:
756757
} else {
757758
qualityResult = {
758759
overall_status: 'infra_error',
759-
skill_validator_status: 'infra_error',
760+
vally_lint_status: 'infra_error',
760761
smoke_status: 'infra_error',
762+
version_match_status: 'infra_error',
761763
failure_class: 'infra',
762764
summary: 'Quality-gate workflow did not return results. Re-run intake to retry.',
763765
};

.github/workflows/external-plugin-intake.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,9 @@ jobs:
113113
if (process.env.QUALITY_JOB_RESULT === 'failure' || process.env.QUALITY_JOB_RESULT === 'cancelled') {
114114
qualityResult = {
115115
overall_status: 'infra_error',
116-
skill_validator_status: 'infra_error',
116+
vally_lint_status: 'infra_error',
117117
smoke_status: 'infra_error',
118+
version_match_status: 'infra_error',
118119
failure_class: 'infra',
119120
summary: 'Quality-gate workflow failed unexpectedly. Re-run intake to retry.',
120121
};
@@ -123,8 +124,9 @@ jobs:
123124
} else {
124125
qualityResult = {
125126
overall_status: 'infra_error',
126-
skill_validator_status: 'infra_error',
127+
vally_lint_status: 'infra_error',
127128
smoke_status: 'infra_error',
129+
version_match_status: 'infra_error',
128130
failure_class: 'infra',
129131
summary: 'Quality-gate workflow did not return results. Re-run intake to retry.',
130132
};

.github/workflows/external-plugin-pr-quality-gates.yml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ jobs:
157157
overall_status: 'infra_error',
158158
failure_class: 'infra',
159159
checked_plugins: [],
160+
version_match_status: 'infra_error',
160161
summary: 'External plugin PR change detection failed unexpectedly. Re-run this workflow.',
161162
};
162163
} else if (shouldRun) {
@@ -165,6 +166,7 @@ jobs:
165166
overall_status: 'infra_error',
166167
failure_class: 'infra',
167168
checked_plugins: [],
169+
version_match_status: 'infra_error',
168170
summary: 'External plugin PR quality checks failed unexpectedly. Re-run this workflow.',
169171
};
170172
} else if (process.env.QUALITY_RESULT_JSON) {
@@ -174,6 +176,7 @@ jobs:
174176
overall_status: 'infra_error',
175177
failure_class: 'infra',
176178
checked_plugins: [],
179+
version_match_status: 'infra_error',
177180
summary: 'External plugin PR quality checks did not return a result payload.',
178181
};
179182
}
@@ -242,14 +245,15 @@ jobs:
242245
const sourceUrl = String(entry?.source_tree_url || '');
243246
const locator = String(entry?.source?.sha || entry?.source?.ref || 'repository');
244247
const sourceCell = sourceUrl ? `[${locator}](${sourceUrl})` : locator;
245-
return `| ${name} | ${quality.vally_lint_status || 'not_run'} | ${quality.smoke_status || 'not_run'} | ${quality.overall_status || 'not_run'} | ${sourceCell} |`;
248+
return `| ${name} | ${quality.vally_lint_status || 'not_run'} | ${quality.smoke_status || 'not_run'} | ${quality.version_match_status || 'not_run'} | ${quality.overall_status || 'not_run'} | ${sourceCell} |`;
246249
})
247-
: ['| _none_ | not_run | not_run | not_run | _n/a_ |'];
250+
: ['| _none_ | not_run | not_run | not_run | not_run | _n/a_ |'];
248251
const failureDetails = checkedPlugins.flatMap((entry) => {
249252
const name = String(entry?.name || 'unknown');
250253
const quality = entry?.quality || {};
251254
const shouldShowVally = quality.vally_lint_status === 'fail' || quality.vally_lint_status === 'infra_error' || String(quality.vally_lint_output || '').trim().length > 0;
252255
const shouldShowSmoke = quality.smoke_status === 'fail' || quality.smoke_status === 'infra_error' || String(quality.smoke_output || '').trim().length > 0;
256+
const shouldShowVersionMatch = quality.version_match_status === 'fail' || quality.version_match_status === 'infra_error' || String(quality.version_match_output || '').trim().length > 0;
253257
254258
const details = [];
255259
if (shouldShowVally) {
@@ -258,6 +262,9 @@ jobs:
258262
if (shouldShowSmoke) {
259263
details.push(formatGateOutput(name, 'install smoke test', quality.smoke_status, quality.smoke_output));
260264
}
265+
if (shouldShowVersionMatch) {
266+
details.push(formatGateOutput(name, 'version match', quality.version_match_status, quality.version_match_output));
267+
}
261268
return details;
262269
});
263270
@@ -270,8 +277,8 @@ jobs:
270277
'',
271278
'### Per-plugin quality summary',
272279
'',
273-
'| Plugin | vally lint | install smoke test | overall | source tree |',
274-
'|---|---|---|---|---|',
280+
'| Plugin | vally lint | install smoke test | version match | overall | source tree |',
281+
'|---|---|---|---|---|---|',
275282
...rows,
276283
'',
277284
...(failureDetails.length > 0

eng/external-plugin-intake.mjs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,10 +425,12 @@ function normalizeQualityGateResult(rawResult) {
425425
overall_status: "not_run",
426426
vally_lint_status: "not_run",
427427
smoke_status: "not_run",
428+
version_match_status: "not_run",
428429
failure_class: "none",
429430
summary: "",
430431
vally_lint_output: "",
431432
smoke_output: "",
433+
version_match_output: "",
432434
};
433435

434436
if (!rawResult || typeof rawResult !== "object" || Array.isArray(rawResult)) {
@@ -444,6 +446,7 @@ function normalizeQualityGateResult(rawResult) {
444446
function buildQualityGatesCommentSection(qualityResult) {
445447
const vallyState = qualityResult.vally_lint_status || "not_run";
446448
const smokeState = qualityResult.smoke_status || "not_run";
449+
const versionMatchState = qualityResult.version_match_status || "not_run";
447450
const summaryText = String(qualityResult.summary || "").trim() || "_No quality gate details were provided._";
448451

449452
const sections = [
@@ -453,6 +456,7 @@ function buildQualityGatesCommentSection(qualityResult) {
453456
"|---|---|",
454457
`| vally lint | ${vallyState} |`,
455458
`| install smoke test | ${smokeState} |`,
459+
`| version match | ${versionMatchState} |`,
456460
"",
457461
summaryText,
458462
];
@@ -487,6 +491,21 @@ function buildQualityGatesCommentSection(qualityResult) {
487491
);
488492
}
489493

494+
const versionMatchOutput = String(qualityResult.version_match_output || "").trim();
495+
if (versionMatchOutput) {
496+
sections.push(
497+
"",
498+
"<details>",
499+
"<summary>Version match output</summary>",
500+
"",
501+
"```text",
502+
versionMatchOutput,
503+
"```",
504+
"",
505+
"</details>",
506+
);
507+
}
508+
490509
return sections.join("\n");
491510
}
492511

eng/external-plugin-pr-quality-gates.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export async function runExternalPluginPrQualityGates(plugins) {
8686
? "No changed external plugin entries were detected in plugins/external.json."
8787
: checkedPlugins
8888
.map((entry) =>
89-
`- ${entry.name}: vally-lint=${entry.quality.vally_lint_status}, install-smoke=${entry.quality.smoke_status}, overall=${entry.quality.overall_status}`
89+
`- ${entry.name}: vally-lint=${entry.quality.vally_lint_status}, install-smoke=${entry.quality.smoke_status}, version-match=${entry.quality.version_match_status}, overall=${entry.quality.overall_status}`
9090
)
9191
.join("\n");
9292

0 commit comments

Comments
 (0)