chore: publish from main

This commit is contained in:
github-actions[bot]
2026-07-17 08:04:30 +00:00
parent 818c0f7c53
commit b1aaa69f0a
286 changed files with 51076 additions and 67 deletions
+166 -1
View File
@@ -8,6 +8,7 @@ import { spawnSync } from "child_process";
import { runLint, LintConsoleReporter } from "@microsoft/vally";
const MAX_OUTPUT_LENGTH = 12000;
const EXTERNAL_CANVAS_KEYWORD = "canvas";
const INFRA_ERROR_PATTERNS = [
/\b401\b/,
@@ -69,6 +70,12 @@ function normalizePluginPath(pluginPath) {
return normalized;
}
function hasCanvasKeyword(plugin) {
return (plugin?.keywords ?? []).some(
(keyword) => String(keyword).trim().toLowerCase() === EXTERNAL_CANVAS_KEYWORD,
);
}
function resolveFetchSpec(pluginSource) {
if (pluginSource.sha) {
return pluginSource.sha;
@@ -467,6 +474,148 @@ function runVersionMatchGate(repoDir, plugin, primaryFetchSpec) {
};
}
function checkPathExistsAtLocator(repoDir, locator, repoPath, expectedType) {
const result = runCommand("git", ["cat-file", "-e", `${locator}:${repoPath}`], { cwd: repoDir });
if (result.exitCode === 0) {
if (!expectedType) {
return { exists: true, output: "" };
}
const typeResult = runCommand("git", ["cat-file", "-t", `${locator}:${repoPath}`], { cwd: repoDir });
if (typeResult.exitCode !== 0) {
return {
exists: false,
output: `Unable to verify path "${repoPath}" type at "${locator}": ${typeResult.output}`,
};
}
const actualType = String(typeResult.stdout ?? "").trim();
if (actualType !== expectedType) {
return {
exists: false,
output: "",
kindMismatch: true,
actualType,
};
}
return { exists: true, output: "" };
}
const normalizedOutput = String(result.output ?? "").toLowerCase();
if (
normalizedOutput.includes("not a valid object name")
|| normalizedOutput.includes("path '")
|| normalizedOutput.includes("does not exist")
) {
return { exists: false, output: "" };
}
return {
exists: false,
output: `Unable to verify path "${repoPath}" at "${locator}": ${result.output}`,
};
}
export function runCanvasStructureGate(repoDir, plugin, primaryFetchSpec) {
if (!hasCanvasKeyword(plugin)) {
return {
status: "not_run",
output: "Canvas structure gate skipped because plugin is not tagged with \"canvas\".",
};
}
const normalizedPluginPath = normalizePluginPath(plugin?.source?.path || "/");
const locators = [plugin?.source?.ref, plugin?.source?.sha]
.filter((value) => typeof value === "string" && value.trim().length > 0)
.map((value) => value.trim())
.filter((value, index, values) => values.indexOf(value) === index);
if (locators.length === 0) {
return {
status: "not_run",
output: "Canvas structure gate skipped because neither source.ref nor source.sha was provided.",
};
}
const extensionsDir = toPosixPath(normalizedPluginPath, "extensions");
const extensionEntryPoint = toPosixPath(extensionsDir, "extension.mjs");
let hasFailure = false;
let hasInfraError = false;
const messages = [];
for (const locator of locators) {
if (locator !== primaryFetchSpec) {
const fetchResult = fetchLocatorIntoRepo(repoDir, locator);
if (fetchResult.status === "fail") {
hasFailure = true;
messages.push(`- ${locator}: ${fetchResult.output}`);
continue;
}
if (fetchResult.status === "infra_error") {
hasInfraError = true;
messages.push(`- ${locator}: ${fetchResult.output}`);
continue;
}
}
const extensionDirCheck = checkPathExistsAtLocator(repoDir, locator, extensionsDir, "tree");
if (extensionDirCheck.output) {
hasInfraError = true;
messages.push(`- ${locator}: ${extensionDirCheck.output}`);
continue;
}
if (!extensionDirCheck.exists) {
hasFailure = true;
if (extensionDirCheck.kindMismatch) {
messages.push(`- ${locator}: "${extensionsDir}" must be a directory.`);
} else {
messages.push(`- ${locator}: missing required canvas extension directory "${extensionsDir}".`);
}
continue;
}
const extensionEntryCheck = checkPathExistsAtLocator(repoDir, locator, extensionEntryPoint, "blob");
if (extensionEntryCheck.output) {
hasInfraError = true;
messages.push(`- ${locator}: ${extensionEntryCheck.output}`);
continue;
}
if (!extensionEntryCheck.exists) {
hasFailure = true;
if (extensionEntryCheck.kindMismatch) {
messages.push(`- ${locator}: "${extensionEntryPoint}" must be a file.`);
} else {
messages.push(`- ${locator}: missing required canvas extension entry point "${extensionEntryPoint}".`);
}
continue;
}
messages.push(`- ${locator}: found "${extensionsDir}" with entry point "${extensionEntryPoint}".`);
}
if (hasInfraError) {
return {
status: "infra_error",
output: messages.join("\n"),
};
}
if (hasFailure) {
return {
status: "fail",
output: messages.join("\n"),
};
}
return {
status: "pass",
output: messages.join("\n"),
};
}
function toOverallStatus(states) {
if (states.includes("infra_error")) {
return "infra_error";
@@ -497,11 +646,13 @@ export async function runExternalPluginQualityGates(plugin) {
vally_lint_status: "not_run",
smoke_status: "not_run",
version_match_status: "not_run",
canvas_structure_status: "not_run",
failure_class: "none",
summary: "",
vally_lint_output: "",
smoke_output: "",
version_match_output: "",
canvas_structure_output: "",
};
try {
@@ -513,10 +664,14 @@ export async function runExternalPluginQualityGates(plugin) {
result.vally_lint_status = "fail";
result.smoke_status = "fail";
result.version_match_status = "fail";
result.canvas_structure_status = hasCanvasKeyword(plugin) ? "fail" : "not_run";
result.overall_status = "fail";
result.failure_class = "submitter_fixes";
result.summary = `Plugin path "${plugin.source?.path || "/"}" was not found in the submitted repository snapshot.`;
result.version_match_output = result.summary;
if (hasCanvasKeyword(plugin)) {
result.canvas_structure_output = result.summary;
}
return result;
}
@@ -524,6 +679,10 @@ export async function runExternalPluginQualityGates(plugin) {
result.version_match_status = versionMatchResult.status;
result.version_match_output = versionMatchResult.output;
const canvasStructureResult = runCanvasStructureGate(repoDir, plugin, fetchSpec);
result.canvas_structure_status = canvasStructureResult.status;
result.canvas_structure_output = canvasStructureResult.output;
const vallyResult = await runVallyLintGate(pluginRoot);
result.vally_lint_status = vallyResult.status;
result.vally_lint_output = vallyResult.output;
@@ -532,12 +691,18 @@ export async function runExternalPluginQualityGates(plugin) {
result.smoke_status = smokeResult.status;
result.smoke_output = smokeResult.output;
result.overall_status = toOverallStatus([result.vally_lint_status, result.smoke_status, result.version_match_status]);
result.overall_status = toOverallStatus([
result.vally_lint_status,
result.smoke_status,
result.version_match_status,
result.canvas_structure_status,
]);
result.failure_class = toFailureClass(result.overall_status);
result.summary = [
`- vally lint: ${result.vally_lint_status}`,
`- install smoke test: ${result.smoke_status}`,
`- version match: ${result.version_match_status}`,
`- canvas structure: ${result.canvas_structure_status}`,
`- overall: ${result.overall_status}`,
].join("\n");