feat(FN-3470): prefer source aliases for runtime plugins and add test artif
Merges FN-3470 in two steps: first, runtime plugins now prefer source path aliases over build artifacts, with hardening tests for vitest alias resolution and plugin view registry updates; second, a new `ensure-test-artifacts.mjs` bootstrap script guarantees required test files exist before test runs Fusion-Task-Id: FN-3470
This commit is contained in:
33
scripts/__tests__/ensure-test-artifacts.test.mjs
Normal file
33
scripts/__tests__/ensure-test-artifacts.test.mjs
Normal file
@@ -0,0 +1,33 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { detectMissingArtifacts, ensureTestArtifacts } from "../ensure-test-artifacts.mjs";
|
||||
|
||||
test("detectMissingArtifacts returns missing package list", () => {
|
||||
const missing = detectMissingArtifacts("/repo", () => false);
|
||||
assert.ok(missing.length >= 5);
|
||||
assert.equal(missing[0].name, "@fusion/core");
|
||||
});
|
||||
|
||||
test("ensureTestArtifacts skips build when nothing is missing", () => {
|
||||
let called = false;
|
||||
const built = ensureTestArtifacts("/repo", () => {
|
||||
called = true;
|
||||
}, () => true);
|
||||
|
||||
assert.equal(called, false);
|
||||
assert.deepEqual(built, []);
|
||||
});
|
||||
|
||||
test("ensureTestArtifacts builds only missing packages", () => {
|
||||
const calls = [];
|
||||
const built = ensureTestArtifacts(
|
||||
"/repo",
|
||||
(cmd, args, cwd) => calls.push({ cmd, args, cwd }),
|
||||
(fullPath) => !fullPath.includes("fusion-plugin-openclaw-runtime"),
|
||||
);
|
||||
|
||||
assert.deepEqual(built, ["@fusion-plugin-examples/openclaw-runtime"]);
|
||||
assert.equal(calls.length, 1);
|
||||
assert.equal(calls[0].cmd, "pnpm");
|
||||
assert.deepEqual(calls[0].args, ["--filter", "@fusion-plugin-examples/openclaw-runtime", "build"]);
|
||||
});
|
||||
41
scripts/__tests__/vitest-source-aliases.test.mjs
Normal file
41
scripts/__tests__/vitest-source-aliases.test.mjs
Normal file
@@ -0,0 +1,41 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { URL } from "node:url";
|
||||
|
||||
function read(path) {
|
||||
return readFileSync(new URL(`../../${path}`, import.meta.url), "utf8");
|
||||
}
|
||||
|
||||
test("dashboard vitest config aliases runtime plugins to src", () => {
|
||||
const content = read("packages/dashboard/vitest.config.ts");
|
||||
assert.match(content, /@fusion-plugin-examples\/hermes-runtime/);
|
||||
assert.match(content, /@fusion-plugin-examples\/openclaw-runtime/);
|
||||
assert.match(content, /@fusion-plugin-examples\/paperclip-runtime/);
|
||||
assert.match(content, /plugins\/fusion-plugin-hermes-runtime\/src\/index\.ts/);
|
||||
assert.match(content, /plugins\/fusion-plugin-openclaw-runtime\/src\/index\.ts/);
|
||||
assert.match(content, /plugins\/fusion-plugin-paperclip-runtime\/src\/index\.ts/);
|
||||
});
|
||||
|
||||
test("cli vitest config aliases runtime plugins to src", () => {
|
||||
const content = read("packages/cli/vitest.config.ts");
|
||||
assert.ok(content.includes("@fusion-plugin-examples\\/droid-runtime"));
|
||||
assert.ok(content.includes("@fusion-plugin-examples\\/hermes-runtime"));
|
||||
assert.ok(content.includes("@fusion-plugin-examples\\/openclaw-runtime"));
|
||||
assert.ok(content.includes("@fusion-plugin-examples\\/paperclip-runtime"));
|
||||
assert.match(content, /plugins\/fusion-plugin-hermes-runtime\/src\/index\.ts/);
|
||||
assert.match(content, /plugins\/fusion-plugin-openclaw-runtime\/src\/index\.ts/);
|
||||
assert.match(content, /plugins\/fusion-plugin-paperclip-runtime\/src\/index\.ts/);
|
||||
});
|
||||
|
||||
test("engine and plugin-sdk vitest configs keep source aliases", () => {
|
||||
const engine = read("packages/engine/vitest.config.ts");
|
||||
const sdk = read("packages/plugin-sdk/vitest.config.ts");
|
||||
|
||||
assert.match(engine, /@fusion\/core/);
|
||||
assert.match(engine, /\.\.\/core\/src\/index\.ts/);
|
||||
assert.match(engine, /@fusion\/plugin-sdk/);
|
||||
|
||||
assert.match(sdk, /@fusion\/core/);
|
||||
assert.match(sdk, /\.\.\/core\/src\/index\.ts/);
|
||||
});
|
||||
@@ -3,6 +3,7 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { ensureTestArtifacts } from "./ensure-test-artifacts.mjs";
|
||||
|
||||
const DEFAULT_TEST_PACKAGES = [
|
||||
"@fusion/core",
|
||||
@@ -74,6 +75,7 @@ export function main(argv = process.argv.slice(2), env = process.env) {
|
||||
};
|
||||
|
||||
run("pnpm", ["sync:fusion-skill:check"], { env: shardEnv });
|
||||
ensureTestArtifacts(process.cwd());
|
||||
const filters = shardPackages.flatMap((pkg) => ["--filter", pkg]);
|
||||
run("pnpm", [...filters, "test"], { env: shardEnv });
|
||||
}
|
||||
|
||||
38
scripts/ensure-test-artifacts.mjs
Normal file
38
scripts/ensure-test-artifacts.mjs
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { existsSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { spawnSync } from "node:child_process";
|
||||
|
||||
export const REQUIRED_BUILD_PACKAGES = [
|
||||
{ name: "@fusion/core", distEntry: "packages/core/dist/index.js" },
|
||||
{ name: "@fusion/plugin-sdk", distEntry: "packages/plugin-sdk/dist/index.js" },
|
||||
{ name: "@fusion-plugin-examples/hermes-runtime", distEntry: "plugins/fusion-plugin-hermes-runtime/dist/index.js" },
|
||||
{ name: "@fusion-plugin-examples/openclaw-runtime", distEntry: "plugins/fusion-plugin-openclaw-runtime/dist/index.js" },
|
||||
{ name: "@fusion-plugin-examples/paperclip-runtime", distEntry: "plugins/fusion-plugin-paperclip-runtime/dist/index.js" },
|
||||
];
|
||||
|
||||
export function detectMissingArtifacts(rootDir = process.cwd(), existsFn = existsSync) {
|
||||
return REQUIRED_BUILD_PACKAGES.filter((pkg) => !existsFn(path.join(rootDir, pkg.distEntry)));
|
||||
}
|
||||
|
||||
function run(command, args, cwd) {
|
||||
const result = spawnSync(command, args, { cwd, stdio: "inherit" });
|
||||
if (result.status !== 0) {
|
||||
process.exit(result.status ?? 1);
|
||||
}
|
||||
}
|
||||
|
||||
export function ensureTestArtifacts(rootDir = process.cwd(), runFn = run, existsFn = existsSync) {
|
||||
const missing = detectMissingArtifacts(rootDir, existsFn);
|
||||
if (missing.length === 0) return [];
|
||||
|
||||
const names = missing.map((pkg) => pkg.name);
|
||||
console.log(`[test-bootstrap] building missing dist artifacts: ${names.join(", ")}`);
|
||||
runFn("pnpm", [...names.flatMap((name) => ["--filter", name]), "build"], rootDir);
|
||||
return names;
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
ensureTestArtifacts();
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import path from "node:path";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { createHash } from "node:crypto";
|
||||
import { ensureTestArtifacts } from "./ensure-test-artifacts.mjs";
|
||||
|
||||
const rootDir = process.env.FUSION_PROJECT_DIR
|
||||
? path.resolve(process.env.FUSION_PROJECT_DIR)
|
||||
@@ -447,6 +448,7 @@ export function main(argv = process.argv.slice(2)) {
|
||||
const forwardedArgs = argv.filter((arg) => arg !== "--full" && arg !== "--no-cache");
|
||||
|
||||
run("pnpm", ["sync:fusion-skill:check"]);
|
||||
ensureTestArtifacts(rootDir);
|
||||
|
||||
const baseBranch = getBaseBranch();
|
||||
const comparisonBase = detectComparisonBase(baseBranch);
|
||||
|
||||
Reference in New Issue
Block a user