mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 12:00:43 +00:00
fix(update): isolate plugin sync failures
Disable and skip plugins that fail package-update plugin sync so broken plugin packages do not fail an otherwise successful OpenClaw update.
This commit is contained in:
@@ -222,6 +222,37 @@ describe("collectMissingPluginInstallPayloads", () => {
|
||||
await fs.rm(tmpDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("skips disabled tracked records when requested", async () => {
|
||||
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-update-plugin-payload-"));
|
||||
const missingDir = path.join(tmpDir, "state", "npm", "node_modules", "@openclaw", "missing");
|
||||
try {
|
||||
await expect(
|
||||
collectMissingPluginInstallPayloads({
|
||||
env: { HOME: tmpDir } as NodeJS.ProcessEnv,
|
||||
skipDisabledPlugins: true,
|
||||
config: {
|
||||
plugins: {
|
||||
entries: {
|
||||
missing: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
records: {
|
||||
missing: {
|
||||
source: "npm",
|
||||
spec: "@openclaw/missing@beta",
|
||||
installPath: missingDir,
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual([]);
|
||||
} finally {
|
||||
await fs.rm(tmpDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("shouldUseLegacyProcessRestartAfterUpdate", () => {
|
||||
|
||||
@@ -51,6 +51,7 @@ import {
|
||||
resolveGlobalInstallSpec,
|
||||
} from "../../infra/update-global.js";
|
||||
import { runGatewayUpdate, type UpdateRunResult } from "../../infra/update-runner.js";
|
||||
import { normalizePluginsConfig, resolveEffectiveEnableState } from "../../plugins/config-state.js";
|
||||
import {
|
||||
loadInstalledPluginIndexInstallRecords,
|
||||
withoutPluginInstallRecords,
|
||||
@@ -184,9 +185,15 @@ async function pathExists(filePath: string): Promise<boolean> {
|
||||
|
||||
export async function collectMissingPluginInstallPayloads(params: {
|
||||
records: Record<string, PluginInstallRecord>;
|
||||
config?: OpenClawConfig;
|
||||
skipDisabledPlugins?: boolean;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
}): Promise<MissingPluginInstallPayload[]> {
|
||||
const env = params.env ?? process.env;
|
||||
const normalizedPluginConfig =
|
||||
params.skipDisabledPlugins && params.config
|
||||
? normalizePluginsConfig(params.config.plugins)
|
||||
: undefined;
|
||||
const missing: MissingPluginInstallPayload[] = [];
|
||||
for (const [pluginId, record] of Object.entries(params.records).toSorted(([left], [right]) =>
|
||||
left.localeCompare(right),
|
||||
@@ -194,6 +201,17 @@ export async function collectMissingPluginInstallPayloads(params: {
|
||||
if (!isTrackedPackageInstallRecord(record)) {
|
||||
continue;
|
||||
}
|
||||
if (normalizedPluginConfig && params.config) {
|
||||
const enableState = resolveEffectiveEnableState({
|
||||
id: pluginId,
|
||||
origin: "global",
|
||||
config: normalizedPluginConfig,
|
||||
rootConfig: params.config,
|
||||
});
|
||||
if (!enableState.enabled) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const rawInstallPath = normalizeOptionalString(record.installPath);
|
||||
if (!rawInstallPath) {
|
||||
missing.push({ pluginId, reason: "missing-install-path" });
|
||||
@@ -1091,7 +1109,11 @@ async function updatePluginsAfterCoreUpdate(params: {
|
||||
const repairMissingPayloads = async (
|
||||
records: Record<string, PluginInstallRecord>,
|
||||
): Promise<readonly string[]> => {
|
||||
const missing = await collectMissingPluginInstallPayloads({ records });
|
||||
const missing = await collectMissingPluginInstallPayloads({
|
||||
records,
|
||||
config: pluginConfig,
|
||||
skipDisabledPlugins: true,
|
||||
});
|
||||
if (missing.length === 0) {
|
||||
return [];
|
||||
}
|
||||
@@ -1110,6 +1132,8 @@ async function updatePluginsAfterCoreUpdate(params: {
|
||||
pluginIds: missingIds,
|
||||
timeoutMs: params.timeoutMs,
|
||||
updateChannel: params.channel,
|
||||
skipDisabledPlugins: true,
|
||||
disableOnFailure: true,
|
||||
logger: pluginLogger,
|
||||
onIntegrityDrift: onPluginIntegrityDrift,
|
||||
});
|
||||
@@ -1130,6 +1154,7 @@ async function updatePluginsAfterCoreUpdate(params: {
|
||||
updateChannel: params.channel,
|
||||
skipIds: new Set([...syncResult.summary.switchedToNpm, ...repairedMissingPayloadIds]),
|
||||
skipDisabledPlugins: true,
|
||||
disableOnFailure: true,
|
||||
logger: pluginLogger,
|
||||
onIntegrityDrift: onPluginIntegrityDrift,
|
||||
});
|
||||
@@ -1140,6 +1165,8 @@ async function updatePluginsAfterCoreUpdate(params: {
|
||||
|
||||
const remainingMissingPayloads = await collectMissingPluginInstallPayloads({
|
||||
records: pluginConfig.plugins?.installs ?? {},
|
||||
config: pluginConfig,
|
||||
skipDisabledPlugins: true,
|
||||
});
|
||||
pluginUpdateOutcomes.push(
|
||||
...remainingMissingPayloads.map(
|
||||
|
||||
Reference in New Issue
Block a user