fix(gateway): check restored runtime overlays

This commit is contained in:
Ruben Cuevas
2026-05-09 03:12:22 -04:00
committed by Peter Steinberger
parent 23eec7b0fa
commit 9ce359b370
2 changed files with 62 additions and 5 deletions

View File

@@ -342,6 +342,20 @@ const listBuiltBundledPluginEntries = (deps) => {
.toSorted((left, right) => left.id.localeCompare(right.id));
};
const listBuiltBundledPluginRuntimeOverlayDirs = (deps) => {
const distExtensionsRoot = path.join(resolveRuntimePostBuildDistRoot(deps), "extensions");
let entries = [];
try {
entries = deps.fs.readdirSync(distExtensionsRoot, { withFileTypes: true });
} catch {
return [];
}
return entries
.filter((entry) => entry.isDirectory() && entry.name !== "node_modules")
.map((entry) => entry.name)
.toSorted((left, right) => left.localeCompare(right));
};
const listRequiredBundledPluginMetadataOutputs = (pluginEntries, deps) =>
pluginEntries.flatMap(({ id, hasManifest, hasPackageJson }) => {
const builtPluginDir = path.join(resolveRuntimePostBuildDistRoot(deps), "extensions", id);
@@ -386,13 +400,13 @@ const listRuntimeOverlaySourcePaths = (sourceDir, deps) => {
return paths.toSorted((left, right) => left.localeCompare(right));
};
const listRequiredBundledPluginRuntimeOverlayOutputs = (pluginEntries, deps) => {
const listRequiredBundledPluginRuntimeOverlayOutputs = (deps) => {
const distRoot = resolveRuntimePostBuildDistRoot(deps);
const runtimeRoot = resolveRuntimePostBuildRuntimeRoot(deps);
const runtimePaths = [];
for (const pluginEntry of pluginEntries) {
const distPluginDir = path.join(distRoot, "extensions", pluginEntry.id);
const runtimePluginDir = path.join(runtimeRoot, "extensions", pluginEntry.id);
for (const pluginId of listBuiltBundledPluginRuntimeOverlayDirs(deps)) {
const distPluginDir = path.join(distRoot, "extensions", pluginId);
const runtimePluginDir = path.join(runtimeRoot, "extensions", pluginId);
for (const sourcePath of listRuntimeOverlaySourcePaths(distPluginDir, deps)) {
runtimePaths.push(path.join(runtimePluginDir, path.relative(distPluginDir, sourcePath)));
}
@@ -443,7 +457,7 @@ export const listRequiredRuntimePostBuildOutputs = (deps) => {
...listRequiredOpenClawExtensionAliasOutputs(deps),
...listRequiredStaticExtensionAssetOutputs(deps),
...listRequiredBundledPluginMetadataOutputs(builtPluginEntries, deps),
...listRequiredBundledPluginRuntimeOverlayOutputs(builtPluginEntries, deps),
...listRequiredBundledPluginRuntimeOverlayOutputs(deps),
];
};

View File

@@ -1777,6 +1777,49 @@ describe("run-node script", () => {
});
});
it("reports missing runtime overlay outputs from restored dist without plugin sources", async () => {
await withTempDir({ prefix: "openclaw-run-node-" }, async (tmp) => {
await setupTrackedProject(tmp, {
files: {
[ROOT_SRC]: "export const value = 1;\n",
[DIST_EXTENSION_INDEX]: "export default {};\n",
[DIST_EXTENSION_MANIFEST]: '{"id":"demo","configSchema":{"type":"object"}}\n',
[DIST_EXTENSION_PACKAGE]: '{"openclaw":{"extensions":["./index.js"]}}\n',
[DIST_RUNTIME_EXTENSION_INDEX]: "export default {};\n",
[DIST_RUNTIME_EXTENSION_MANIFEST]: '{"id":"demo","configSchema":{"type":"object"}}\n',
[DIST_RUNTIME_EXTENSION_PACKAGE]: '{"openclaw":{"extensions":["./index.js"]}}\n',
[RUNTIME_POSTBUILD_STAMP]: '{"head":"abc123"}\n',
},
buildPaths: [
ROOT_SRC,
DIST_ENTRY,
DIST_EXTENSION_INDEX,
DIST_EXTENSION_MANIFEST,
DIST_EXTENSION_PACKAGE,
DIST_RUNTIME_EXTENSION_INDEX,
DIST_RUNTIME_EXTENSION_MANIFEST,
DIST_RUNTIME_EXTENSION_PACKAGE,
BUILD_STAMP,
RUNTIME_POSTBUILD_STAMP,
],
});
await fs.rm(resolvePath(tmp, "extensions"), { recursive: true, force: true });
await fs.rm(resolvePath(tmp, DIST_RUNTIME_EXTENSION_INDEX));
const requirement = resolveRuntimePostBuildRequirement(
createBuildRequirementDeps(tmp, {
gitHead: "abc123\n",
gitStatus: "",
}),
);
expect(requirement).toEqual({
shouldSync: true,
reason: "missing_runtime_postbuild_output",
});
});
});
it("does not require OpenClaw SDK alias outputs when dist extensions are absent", async () => {
await withTempDir({ prefix: "openclaw-run-node-" }, async (tmp) => {
await setupTrackedProject(tmp, {