mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 15:30:47 +00:00
fix(update): preserve legacy downgrade verify
This commit is contained in:
@@ -81,16 +81,24 @@ export async function readPackageDistInventory(packageRoot: string): Promise<str
|
||||
);
|
||||
}
|
||||
|
||||
export async function collectPackageDistInventoryErrors(packageRoot: string): Promise<string[]> {
|
||||
let expectedFiles: string[];
|
||||
export async function readPackageDistInventoryIfPresent(
|
||||
packageRoot: string,
|
||||
): Promise<string[] | null> {
|
||||
try {
|
||||
expectedFiles = await readPackageDistInventory(packageRoot);
|
||||
return await readPackageDistInventory(packageRoot);
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
||||
return [`missing package dist inventory ${PACKAGE_DIST_INVENTORY_RELATIVE_PATH}`];
|
||||
return null;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function collectPackageDistInventoryErrors(packageRoot: string): Promise<string[]> {
|
||||
const expectedFiles = await readPackageDistInventoryIfPresent(packageRoot);
|
||||
if (expectedFiles === null) {
|
||||
return [`missing package dist inventory ${PACKAGE_DIST_INVENTORY_RELATIVE_PATH}`];
|
||||
}
|
||||
|
||||
const actualFiles = await collectPackageDistInventory(packageRoot);
|
||||
const expectedSet = new Set(expectedFiles);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { NPM_UPDATE_COMPAT_SIDECAR_PATHS } from "../../scripts/lib/npm-update-compat-sidecars.mjs";
|
||||
import { bundledDistPluginFile } from "../../test/helpers/bundled-plugin-paths.js";
|
||||
import { BUNDLED_RUNTIME_SIDECAR_PATHS } from "../plugins/runtime-sidecar-paths.js";
|
||||
import { withTempDir } from "../test-helpers/temp-dir.js";
|
||||
@@ -27,6 +28,7 @@ import {
|
||||
} from "./update-global.js";
|
||||
|
||||
const MATRIX_HELPER_API = bundledDistPluginFile("matrix", "helper-api.js");
|
||||
const QA_CHANNEL_RUNTIME_API = bundledDistPluginFile("qa-channel", "runtime-api.js");
|
||||
|
||||
describe("update global helpers", () => {
|
||||
let envSnapshot: ReturnType<typeof captureEnv> | undefined;
|
||||
@@ -405,7 +407,7 @@ describe("update global helpers", () => {
|
||||
JSON.stringify({ name: "openclaw", version: "1.0.0" }),
|
||||
"utf-8",
|
||||
);
|
||||
for (const relativePath of BUNDLED_RUNTIME_SIDECAR_PATHS) {
|
||||
for (const relativePath of NPM_UPDATE_COMPAT_SIDECAR_PATHS) {
|
||||
const absolutePath = path.join(packageRoot, relativePath);
|
||||
await fs.mkdir(path.dirname(absolutePath), { recursive: true });
|
||||
await fs.writeFile(absolutePath, "export {};\n", "utf-8");
|
||||
@@ -413,9 +415,9 @@ describe("update global helpers", () => {
|
||||
|
||||
await expect(collectInstalledGlobalPackageErrors({ packageRoot })).resolves.toEqual([]);
|
||||
|
||||
await fs.rm(path.join(packageRoot, MATRIX_HELPER_API));
|
||||
await fs.rm(path.join(packageRoot, QA_CHANNEL_RUNTIME_API));
|
||||
await expect(collectInstalledGlobalPackageErrors({ packageRoot })).resolves.toContain(
|
||||
`missing bundled runtime sidecar ${MATRIX_HELPER_API}`,
|
||||
`missing bundled runtime sidecar ${QA_CHANNEL_RUNTIME_API}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,12 +2,12 @@ import fsSync from "node:fs";
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { BUNDLED_RUNTIME_SIDECAR_PATHS } from "../plugins/runtime-sidecar-paths.js";
|
||||
import { NPM_UPDATE_COMPAT_SIDECAR_PATHS } from "../../scripts/lib/npm-update-compat-sidecars.mjs";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { pathExists } from "../utils.js";
|
||||
import {
|
||||
PACKAGE_DIST_INVENTORY_RELATIVE_PATH,
|
||||
collectPackageDistInventoryErrors,
|
||||
collectPackageDistInventory,
|
||||
readPackageDistInventoryIfPresent,
|
||||
} from "./package-dist-inventory.js";
|
||||
import { readPackageVersion } from "./package-json.js";
|
||||
import { applyPathPrepend } from "./path-prepend.js";
|
||||
@@ -39,7 +39,6 @@ const NPM_GLOBAL_INSTALL_OMIT_OPTIONAL_FLAGS = [
|
||||
"--omit=optional",
|
||||
...NPM_GLOBAL_INSTALL_QUIET_FLAGS,
|
||||
] as const;
|
||||
const MISSING_PACKAGE_DIST_INVENTORY_ERROR = `missing package dist inventory ${PACKAGE_DIST_INVENTORY_RELATIVE_PATH}`;
|
||||
|
||||
function normalizePackageTarget(value: string): string {
|
||||
return value.trim();
|
||||
@@ -94,20 +93,53 @@ export async function collectInstalledGlobalPackageErrors(params: {
|
||||
`expected installed version ${params.expectedVersion}, found ${installedVersion ?? "<missing>"}`,
|
||||
);
|
||||
}
|
||||
const distErrors = await collectPackageDistInventoryErrors(params.packageRoot);
|
||||
if (distErrors.length === 1 && distErrors[0] === MISSING_PACKAGE_DIST_INVENTORY_ERROR) {
|
||||
errors.push(...(await collectLegacyInstalledGlobalPackageErrors(params.packageRoot)));
|
||||
return errors;
|
||||
}
|
||||
errors.push(...distErrors);
|
||||
errors.push(...(await collectInstalledPackageDistErrors(params.packageRoot)));
|
||||
return errors;
|
||||
}
|
||||
|
||||
async function collectLegacyInstalledGlobalPackageErrors(packageRoot: string): Promise<string[]> {
|
||||
async function collectInstalledPackageDistErrors(packageRoot: string): Promise<string[]> {
|
||||
const inventoryFiles = await readPackageDistInventoryIfPresent(packageRoot);
|
||||
if (inventoryFiles !== null) {
|
||||
return await collectInstalledPathErrors({
|
||||
packageRoot,
|
||||
expectedFiles: inventoryFiles,
|
||||
actualFiles: await collectPackageDistInventory(packageRoot),
|
||||
missingMessage: (relativePath) => `missing packaged dist file ${relativePath}`,
|
||||
unexpectedMessage: (relativePath) => `unexpected packaged dist file ${relativePath}`,
|
||||
});
|
||||
}
|
||||
return await collectInstalledPathErrors({
|
||||
packageRoot,
|
||||
expectedFiles: [...NPM_UPDATE_COMPAT_SIDECAR_PATHS],
|
||||
actualFiles: null,
|
||||
missingMessage: (relativePath) => `missing bundled runtime sidecar ${relativePath}`,
|
||||
});
|
||||
}
|
||||
|
||||
async function collectInstalledPathErrors(params: {
|
||||
packageRoot: string;
|
||||
expectedFiles: string[];
|
||||
actualFiles: string[] | null;
|
||||
missingMessage: (relativePath: string) => string;
|
||||
unexpectedMessage?: ((relativePath: string) => string) | undefined;
|
||||
}): Promise<string[]> {
|
||||
const errors: string[] = [];
|
||||
for (const relativePath of BUNDLED_RUNTIME_SIDECAR_PATHS) {
|
||||
if (!(await pathExists(path.join(packageRoot, relativePath)))) {
|
||||
errors.push(`missing bundled runtime sidecar ${relativePath}`);
|
||||
const actualSet = params.actualFiles ? new Set(params.actualFiles) : null;
|
||||
for (const relativePath of params.expectedFiles) {
|
||||
const exists =
|
||||
actualSet !== null
|
||||
? actualSet.has(relativePath)
|
||||
: await pathExists(path.join(params.packageRoot, relativePath));
|
||||
if (!exists) {
|
||||
errors.push(params.missingMessage(relativePath));
|
||||
}
|
||||
}
|
||||
if (actualSet !== null && params.unexpectedMessage) {
|
||||
const expectedSet = new Set(params.expectedFiles);
|
||||
for (const relativePath of params.actualFiles ?? []) {
|
||||
if (!expectedSet.has(relativePath)) {
|
||||
errors.push(params.unexpectedMessage(relativePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
|
||||
Reference in New Issue
Block a user