test(plugins): extend external install contract coverage

This commit is contained in:
Vincent Koc
2026-04-29 02:48:41 -07:00
parent 3af661384c
commit 412434a450
5 changed files with 130 additions and 3 deletions

View File

@@ -213,6 +213,38 @@ function assertMarketplaceRecords() {
}
}
function assertRealPathInside(parentPath, childPath, label) {
const parentRealPath = fs.realpathSync(parentPath);
const childRealPath = fs.realpathSync(childPath);
if (
childRealPath !== parentRealPath &&
!childRealPath.startsWith(`${parentRealPath}${path.sep}`)
) {
throw new Error(`${label} resolved outside ${parentPath}: ${childRealPath}`);
}
}
function assertClawHubExternalInstallContract(installPath) {
const openclawPeerPath = path.join(installPath, "node_modules", "openclaw");
if (!fs.existsSync(openclawPeerPath)) {
throw new Error(`missing ClawHub openclaw peer symlink: ${openclawPeerPath}`);
}
if (!fs.lstatSync(openclawPeerPath).isSymbolicLink()) {
throw new Error(`ClawHub openclaw peer is not a symlink: ${openclawPeerPath}`);
}
const hostRoot = fs.realpathSync(process.cwd());
const linkedHostRoot = fs.realpathSync(openclawPeerPath);
if (linkedHostRoot !== hostRoot) {
throw new Error(`expected ClawHub openclaw peer ${linkedHostRoot} to target ${hostRoot}`);
}
const dependencyPackagePath = path.join(installPath, "node_modules", "is-number", "package.json");
if (!fs.existsSync(dependencyPackagePath)) {
throw new Error(`missing ClawHub isolated dependency: ${dependencyPackagePath}`);
}
assertRealPathInside(installPath, dependencyPackagePath, "ClawHub isolated dependency");
}
function assertMarketplaceUpdated() {
const data = readJson("/tmp/plugins-marketplace-updated.json");
const inspect = readJson("/tmp/plugins-marketplace-updated-inspect.json");
@@ -322,6 +354,7 @@ function assertClawHubInstalled() {
if (!fs.existsSync(installPath)) {
throw new Error(`ClawHub install path missing on disk: ${installPath}`);
}
assertClawHubExternalInstallContract(installPath);
fs.writeFileSync("/tmp/plugins-clawhub-install-path.txt", installPath, "utf8");
}

View File

@@ -10,6 +10,7 @@ export const PLUGIN_PRERELEASE_REQUIRED_SURFACES = Object.freeze([
"config-round-trip",
"gateway-bootstrap",
"sdk-compatibility",
"external-install-boundary",
"status-diagnostics",
"npm-registry-plugin",
"clawhub-registry-plugin",
@@ -40,13 +41,19 @@ const pluginPrereleaseDockerLanes = Object.freeze([
},
{
lane: "plugins",
surfaces: ["external-plugins", "sdk-compatibility", "status-diagnostics"],
surfaces: [
"external-plugins",
"sdk-compatibility",
"external-install-boundary",
"status-diagnostics",
],
},
{
lane: "kitchen-sink-plugin",
surfaces: [
"external-plugins",
"sdk-compatibility",
"external-install-boundary",
"status-diagnostics",
"npm-registry-plugin",
"clawhub-registry-plugin",