Add plugin owner conformance consumer proof
This commit is contained in:
parent
96f1eb6927
commit
923a099d2f
5 changed files with 118 additions and 1 deletions
|
|
@ -280,6 +280,14 @@ Exit criteria:
|
|||
|
||||
Recently cut:
|
||||
|
||||
- Plugin owner conformance consumption now has a smoke runner at
|
||||
`scripts/run-plugin-owner-conformance-consumer-smoke.ps1`. The generic
|
||||
conformance consumer can assert plugin ABI operations and capabilities with
|
||||
`--expect-plugin-operation` and `--expect-plugin-capability`, and the export
|
||||
now carries plugin manifest paths, advertisement paths, split targets,
|
||||
graduation triggers, and optional plugin dependencies. Sai and Norn can prove
|
||||
the plugin contract from the conformance export without reading Eve's parity
|
||||
manifest.
|
||||
- EveUnity now has a split lifecycle smoke at
|
||||
`scripts/run-eveunity-lifecycle-smoke.ps1`. It validates the existing
|
||||
`packages/org.gamecult.eve.unity-uitoolkit/eve-runtime-capability.json`
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ Push-Location $projectRoot
|
|||
try {
|
||||
node .\tools\parity\run-parity.mjs
|
||||
& (Join-Path $PSScriptRoot "run-conformance-consumer-smoke.ps1")
|
||||
& (Join-Path $PSScriptRoot "run-plugin-owner-conformance-consumer-smoke.ps1")
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
|
|
|||
59
scripts/run-plugin-owner-conformance-consumer-smoke.ps1
Normal file
59
scripts/run-plugin-owner-conformance-consumer-smoke.ps1
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
param(
|
||||
[string] $ExportDirectory = "artifacts\conformance\latest",
|
||||
[string] $ConsumerDirectory = "artifacts\plugin-owner-conformance-consumer-smoke"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$projectRoot = Split-Path -Parent $PSScriptRoot
|
||||
$sourceExport = if ([System.IO.Path]::IsPathRooted($ExportDirectory)) {
|
||||
$ExportDirectory
|
||||
} else {
|
||||
Join-Path $projectRoot $ExportDirectory
|
||||
}
|
||||
$consumerRoot = if ([System.IO.Path]::IsPathRooted($ConsumerDirectory)) {
|
||||
$ConsumerDirectory
|
||||
} else {
|
||||
Join-Path $projectRoot $ConsumerDirectory
|
||||
}
|
||||
$consumerExport = Join-Path $consumerRoot "export"
|
||||
|
||||
if (-not (Test-Path $sourceExport)) {
|
||||
throw "Conformance export not found: $sourceExport"
|
||||
}
|
||||
|
||||
if (Test-Path $consumerExport) {
|
||||
Remove-Item -LiteralPath $consumerExport -Recurse -Force
|
||||
}
|
||||
New-Item -ItemType Directory -Force -Path $consumerRoot | Out-Null
|
||||
Copy-Item -LiteralPath $sourceExport -Destination $consumerExport -Recurse
|
||||
|
||||
$consumerScript = Join-Path $projectRoot "tools\conformance\consume-export.mjs"
|
||||
|
||||
node $consumerScript $consumerExport `
|
||||
--expect-pack plugin `
|
||||
--expect-fixture sai-vn `
|
||||
--expect-plugin sai.vn `
|
||||
--expect-plugin norn.graph `
|
||||
--expect-plugin-operation sai.vn:describe `
|
||||
--expect-plugin-operation sai.vn:validate `
|
||||
--expect-plugin-operation sai.vn:project `
|
||||
--expect-plugin-operation sai.vn:lower `
|
||||
--expect-plugin-operation sai.vn:measure `
|
||||
--expect-plugin-operation sai.vn:apply `
|
||||
--expect-plugin-operation norn.graph:describe `
|
||||
--expect-plugin-operation norn.graph:validate `
|
||||
--expect-plugin-operation norn.graph:project `
|
||||
--expect-plugin-operation norn.graph:lower `
|
||||
--expect-plugin-operation norn.graph:measure `
|
||||
--expect-plugin-operation norn.graph:apply `
|
||||
--expect-plugin-capability sai.vn:vn.stage `
|
||||
--expect-plugin-capability sai.vn:story.choose `
|
||||
--expect-plugin-capability sai.vn:story.continue `
|
||||
--expect-plugin-capability sai.vn:story.jump `
|
||||
--expect-plugin-capability norn.graph:embed.norn `
|
||||
--expect-plugin-capability norn.graph:graph.node.activate
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Plugin owner conformance consumer smoke failed with exit code $LASTEXITCODE"
|
||||
}
|
||||
|
|
@ -16,6 +16,8 @@ if (!exportDirectory) {
|
|||
" --expect-runtime <id>",
|
||||
" --expect-scenario <id>",
|
||||
" --expect-split-target <id>",
|
||||
" --expect-plugin-operation <pluginId:operation>",
|
||||
" --expect-plugin-capability <pluginId:capability>",
|
||||
].join("\n"));
|
||||
process.exit(2);
|
||||
}
|
||||
|
|
@ -95,6 +97,26 @@ function validateIndex(index, directory, expectations, errors) {
|
|||
for (const expectedPlugin of expectations.plugins) {
|
||||
if (!plugins.some(plugin => plugin.pluginId === expectedPlugin)) errors.push(`plugins:${expectedPlugin}:missing`);
|
||||
}
|
||||
for (const expectation of expectations.pluginOperations) {
|
||||
const plugin = plugins.find(candidate => candidate.pluginId === expectation.pluginId);
|
||||
if (!plugin) {
|
||||
errors.push(`plugins:${expectation.pluginId}:missing`);
|
||||
continue;
|
||||
}
|
||||
if (!Array.isArray(plugin.abiOperations) || !plugin.abiOperations.includes(expectation.operation)) {
|
||||
errors.push(`plugins:${expectation.pluginId}:operation:${expectation.operation}:missing`);
|
||||
}
|
||||
}
|
||||
for (const expectation of expectations.pluginCapabilities) {
|
||||
const plugin = plugins.find(candidate => candidate.pluginId === expectation.pluginId);
|
||||
if (!plugin) {
|
||||
errors.push(`plugins:${expectation.pluginId}:missing`);
|
||||
continue;
|
||||
}
|
||||
if (!Array.isArray(plugin.capabilities) || !plugin.capabilities.includes(expectation.capability)) {
|
||||
errors.push(`plugins:${expectation.pluginId}:capability:${expectation.capability}:missing`);
|
||||
}
|
||||
}
|
||||
for (const expectedProvider of expectations.providers) {
|
||||
if (!providers.some(provider => provider.providerId === expectedProvider)) errors.push(`providers:${expectedProvider}:missing`);
|
||||
}
|
||||
|
|
@ -132,6 +154,8 @@ function parseArguments(args) {
|
|||
packs: [],
|
||||
fixtures: [],
|
||||
plugins: [],
|
||||
pluginOperations: [],
|
||||
pluginCapabilities: [],
|
||||
providers: [],
|
||||
runtimes: [],
|
||||
scenarios: [],
|
||||
|
|
@ -145,6 +169,8 @@ function parseArguments(args) {
|
|||
["--expect-runtime", expectations.runtimes],
|
||||
["--expect-scenario", expectations.scenarios],
|
||||
["--expect-split-target", expectations.splitTargets],
|
||||
["--expect-plugin-operation", expectations.pluginOperations],
|
||||
["--expect-plugin-capability", expectations.pluginCapabilities],
|
||||
]);
|
||||
|
||||
for (let index = 1; index < args.length; index += 1) {
|
||||
|
|
@ -159,9 +185,27 @@ function parseArguments(args) {
|
|||
console.error(`Missing value for option: ${option}`);
|
||||
process.exit(2);
|
||||
}
|
||||
target.push(value);
|
||||
if (option === "--expect-plugin-operation") {
|
||||
target.push(parsePluginExpectation(value, "operation"));
|
||||
} else if (option === "--expect-plugin-capability") {
|
||||
target.push(parsePluginExpectation(value, "capability"));
|
||||
} else {
|
||||
target.push(value);
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
|
||||
return { exportDirectory: exportPath, expectations };
|
||||
}
|
||||
|
||||
function parsePluginExpectation(value, field) {
|
||||
const separator = value.indexOf(":");
|
||||
if (separator <= 0 || separator === value.length - 1) {
|
||||
console.error(`Expected plugin ${field} in <pluginId:${field}> form, got: ${value}`);
|
||||
process.exit(2);
|
||||
}
|
||||
return {
|
||||
pluginId: value.slice(0, separator),
|
||||
[field]: value.slice(separator + 1),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1341,8 +1341,13 @@ function buildConformanceExport(report) {
|
|||
pluginId: plugin.pluginId,
|
||||
status: plugin.status,
|
||||
ownerRepo: plugin.ownerRepo,
|
||||
splitTarget: plugin.splitTarget,
|
||||
graduationTrigger: plugin.graduationTrigger,
|
||||
manifestPath: plugin.manifestPath,
|
||||
advertisementPath: plugin.advertisementPath,
|
||||
abiFixturePath: plugin.abiFixturePath,
|
||||
abiOperations: plugin.abiOperations || [],
|
||||
optionalPlugins: plugin.optionalPlugins || [],
|
||||
capabilities: plugin.capabilities,
|
||||
})),
|
||||
providers: (report.providers || []).map(provider => ({
|
||||
|
|
|
|||
Loading…
Reference in a new issue