mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 13:10:43 +00:00
ci: time-box package acceptance legacy compat
This commit is contained in:
@@ -120,6 +120,22 @@ LOGINCTL
|
||||
fi
|
||||
git_cli="$git_root/openclaw.mjs"
|
||||
|
||||
package_version="$(node -p "require(\"$npm_root/package.json\").version")"
|
||||
is_legacy_package_acceptance_compat() {
|
||||
node - "$1" <<"NODE"
|
||||
const version = process.argv[2] || "";
|
||||
const match = /^(\d{4})\.(\d{1,2})\.(\d{1,2})(?:[-+].*)?$/.exec(version);
|
||||
if (!match) process.exit(1);
|
||||
const value = [Number(match[1]), Number(match[2]), Number(match[3])];
|
||||
const max = [2026, 4, 25];
|
||||
for (let i = 0; i < value.length; i += 1) {
|
||||
if (value[i] < max[i]) process.exit(0);
|
||||
if (value[i] > max[i]) process.exit(1);
|
||||
}
|
||||
process.exit(0);
|
||||
NODE
|
||||
}
|
||||
|
||||
assert_entrypoint() {
|
||||
local unit_path="$1"
|
||||
local expected="$2"
|
||||
@@ -314,7 +330,11 @@ WRAPPER
|
||||
|
||||
if "$npm_bin" gateway install --help 2>&1 | grep -q -- "--wrapper"; then
|
||||
run_wrapper_flow
|
||||
else
|
||||
elif is_legacy_package_acceptance_compat "$package_version"; then
|
||||
# Legacy compatibility: 2026.4.25 and older did not ship gateway install --wrapper.
|
||||
echo "Skipping wrapper persistence; package gateway install does not support --wrapper."
|
||||
else
|
||||
echo "Package $package_version must support gateway install --wrapper." >&2
|
||||
exit 1
|
||||
fi
|
||||
'
|
||||
|
||||
@@ -27,6 +27,9 @@ package_tgz=\"\${OPENCLAW_CURRENT_PACKAGE_TGZ:?missing OPENCLAW_CURRENT_PACKAGE_
|
||||
npm install -g --prefix /tmp/npm-prefix \"\$package_tgz\" --no-fund --no-audit >/tmp/openclaw-install.log 2>&1
|
||||
entry=\"/tmp/npm-prefix/lib/node_modules/openclaw/dist/index.mjs\"
|
||||
[ -f \"\$entry\" ] || entry=/tmp/npm-prefix/lib/node_modules/openclaw/dist/index.js
|
||||
package_version=\$(node -p \"require('/tmp/npm-prefix/lib/node_modules/openclaw/package.json').version\")
|
||||
OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT=\$(PACKAGE_VERSION=\"\$package_version\" node -e 'const version = process.env.PACKAGE_VERSION || \"\"; const match = new RegExp(\"^(\\\\d{4})\\\\.(\\\\d{1,2})\\\\.(\\\\d{1,2})(?:[-+].*)?\").exec(version); if (!match) { console.log(\"0\"); process.exit(0); } const value = [Number(match[1]), Number(match[2]), Number(match[3])]; const max = [2026, 4, 25]; for (let i = 0; i < value.length; i += 1) { if (value[i] < max[i]) { console.log(\"1\"); process.exit(0); } if (value[i] > max[i]) { console.log(\"0\"); process.exit(0); } } console.log(\"1\");')
|
||||
export OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT
|
||||
export NPM_CONFIG_REGISTRY=http://127.0.0.1:4873
|
||||
export PATH=\"/tmp/npm-prefix/bin:\$PATH\"
|
||||
|
||||
@@ -37,7 +40,8 @@ cat > \"\$HOME/.openclaw/extensions/lossless-claw/package.json\" <<'JSON'
|
||||
\"version\": \"0.9.0\"
|
||||
}
|
||||
JSON
|
||||
cat > \"\$HOME/.openclaw/openclaw.json\" <<'JSON'
|
||||
if [ \"\$OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT\" = \"1\" ]; then
|
||||
cat > \"\$HOME/.openclaw/openclaw.json\" <<'JSON'
|
||||
{
|
||||
\"plugins\": {
|
||||
\"installs\": {
|
||||
@@ -55,6 +59,13 @@ cat > \"\$HOME/.openclaw/openclaw.json\" <<'JSON'
|
||||
}
|
||||
}
|
||||
JSON
|
||||
else
|
||||
cat > \"\$HOME/.openclaw/openclaw.json\" <<'JSON'
|
||||
{
|
||||
\"plugins\": {}
|
||||
}
|
||||
JSON
|
||||
fi
|
||||
mkdir -p \"\$HOME/.openclaw/plugins\"
|
||||
cat > \"\$HOME/.openclaw/plugins/installs.json\" <<'JSON'
|
||||
{
|
||||
@@ -141,6 +152,11 @@ if [ \"\$registry_ready\" -ne 1 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
before_config_hash=\"\"
|
||||
if [ \"\$OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT\" != \"1\" ]; then
|
||||
before_config_hash=\$(sha256sum \"\$HOME/.openclaw/openclaw.json\" | awk '{print \$1}')
|
||||
fi
|
||||
|
||||
node --input-type=module > /tmp/plugin-update-before.json <<'NODE'
|
||||
import fs from \"node:fs\";
|
||||
import os from \"node:os\";
|
||||
@@ -175,6 +191,15 @@ NODE
|
||||
|
||||
node \"\$entry\" plugins update @example/lossless-claw > /tmp/plugin-update-output.log 2>&1
|
||||
|
||||
if [ -n \"\$before_config_hash\" ]; then
|
||||
after_config_hash=\$(sha256sum \"\$HOME/.openclaw/openclaw.json\" | awk '{print \$1}')
|
||||
if [ \"\$before_config_hash\" != \"\$after_config_hash\" ]; then
|
||||
echo \"Config changed unexpectedly for modern package \$package_version\"
|
||||
cat /tmp/plugin-update-output.log
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
node --input-type=module <<'NODE'
|
||||
import fs from \"node:fs\";
|
||||
import os from \"node:os\";
|
||||
|
||||
@@ -38,6 +38,31 @@ else
|
||||
exit 1
|
||||
fi
|
||||
export OPENCLAW_ENTRY
|
||||
PACKAGE_VERSION="$(node -p 'require("./package.json").version')"
|
||||
OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT="$(
|
||||
node - "$PACKAGE_VERSION" <<'NODE'
|
||||
const version = process.argv[2] || "";
|
||||
const match = /^(\d{4})\.(\d{1,2})\.(\d{1,2})(?:[-+].*)?$/.exec(version);
|
||||
if (!match) {
|
||||
console.log("0");
|
||||
process.exit(0);
|
||||
}
|
||||
const value = [Number(match[1]), Number(match[2]), Number(match[3])];
|
||||
const max = [2026, 4, 25];
|
||||
for (let i = 0; i < value.length; i += 1) {
|
||||
if (value[i] < max[i]) {
|
||||
console.log("1");
|
||||
process.exit(0);
|
||||
}
|
||||
if (value[i] > max[i]) {
|
||||
console.log("0");
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
console.log("1");
|
||||
NODE
|
||||
)"
|
||||
export OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT
|
||||
|
||||
home_dir=$(mktemp -d "/tmp/openclaw-plugins-e2e.XXXXXX")
|
||||
export HOME="$home_dir"
|
||||
@@ -562,12 +587,21 @@ const indexPath = path.join(process.env.HOME, ".openclaw", "plugins", "installs.
|
||||
const index = JSON.parse(fs.readFileSync(indexPath, "utf8"));
|
||||
const configPath = path.join(process.env.HOME, ".openclaw", "openclaw.json");
|
||||
const config = fs.existsSync(configPath) ? JSON.parse(fs.readFileSync(configPath, "utf8")) : {};
|
||||
const installRecords = index.installRecords ?? index.records ?? config.plugins?.installs ?? {};
|
||||
const allowLegacyCompat = process.env.OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT === "1";
|
||||
if (!allowLegacyCompat && !index.installRecords) {
|
||||
throw new Error("expected modern installRecords in installed plugin index");
|
||||
}
|
||||
const installRecords = allowLegacyCompat
|
||||
? index.installRecords ?? index.records ?? config.plugins?.installs ?? {}
|
||||
: index.installRecords ?? {};
|
||||
for (const id of ["marketplace-shortcut", "marketplace-direct"]) {
|
||||
const record = installRecords[id];
|
||||
if (!record) {
|
||||
console.log(`legacy package did not persist marketplace install record for ${id}`);
|
||||
continue;
|
||||
if (allowLegacyCompat) {
|
||||
console.log(`legacy package did not persist marketplace install record for ${id}`);
|
||||
continue;
|
||||
}
|
||||
throw new Error(`missing marketplace install record for ${id}`);
|
||||
}
|
||||
if (record.source !== "marketplace") {
|
||||
throw new Error(`unexpected source for ${id}: ${record.source}`);
|
||||
@@ -853,7 +887,13 @@ const indexPath = path.join(process.env.HOME, ".openclaw", "plugins", "installs.
|
||||
const index = JSON.parse(fs.readFileSync(indexPath, "utf8"));
|
||||
const configPath = path.join(process.env.HOME, ".openclaw", "openclaw.json");
|
||||
const config = fs.existsSync(configPath) ? JSON.parse(fs.readFileSync(configPath, "utf8")) : {};
|
||||
const installRecords = index.installRecords ?? index.records ?? config.plugins?.installs ?? {};
|
||||
const allowLegacyCompat = process.env.OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT === "1";
|
||||
if (!allowLegacyCompat && !index.installRecords) {
|
||||
throw new Error("expected modern installRecords in installed plugin index");
|
||||
}
|
||||
const installRecords = allowLegacyCompat
|
||||
? index.installRecords ?? index.records ?? config.plugins?.installs ?? {}
|
||||
: index.installRecords ?? {};
|
||||
const record = installRecords[pluginId];
|
||||
if (!record) throw new Error(`missing ClawHub install record for ${pluginId}`);
|
||||
if (record.source !== "clawhub") {
|
||||
|
||||
@@ -48,6 +48,17 @@ const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const packageJsonPath = "/tmp/openclaw-git/package.json";
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
||||
const isLegacyPackageAcceptanceCompat = (version) => {
|
||||
const match = /^(\d{4})\.(\d{1,2})\.(\d{1,2})(?:[-+].*)?$/.exec(version || "");
|
||||
if (!match) return false;
|
||||
const value = [Number(match[1]), Number(match[2]), Number(match[3])];
|
||||
const max = [2026, 4, 25];
|
||||
for (let i = 0; i < value.length; i += 1) {
|
||||
if (value[i] < max[i]) return true;
|
||||
if (value[i] > max[i]) return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const fixtureUiBuildSource = `const fs=require("node:fs");fs.mkdirSync("dist/control-ui",{recursive:true});fs.writeFileSync("dist/control-ui/index.html","<!doctype html><title>fixture</title>\\n")`;
|
||||
const fixtureUiBuildCommand = `node -e ${JSON.stringify(fixtureUiBuildSource)}`;
|
||||
const nextPnpm = { ...packageJson.pnpm, allowUnusedPatches: true };
|
||||
@@ -57,14 +68,28 @@ if (
|
||||
typeof patchedDependencies === "object" &&
|
||||
!Array.isArray(patchedDependencies)
|
||||
) {
|
||||
const patchEntries = Object.entries(patchedDependencies);
|
||||
const keptPatches = Object.fromEntries(
|
||||
Object.entries(patchedDependencies).filter(([, patchFile]) => {
|
||||
patchEntries.filter(([, patchFile]) => {
|
||||
return (
|
||||
typeof patchFile === "string" &&
|
||||
fs.existsSync(path.resolve(path.dirname(packageJsonPath), patchFile))
|
||||
);
|
||||
}),
|
||||
);
|
||||
const missingPatches = patchEntries.filter(([dependency, patchFile]) => {
|
||||
return (
|
||||
typeof patchFile !== "string" ||
|
||||
!fs.existsSync(path.resolve(path.dirname(packageJsonPath), patchFile))
|
||||
);
|
||||
});
|
||||
if (missingPatches.length > 0 && !isLegacyPackageAcceptanceCompat(packageJson.version)) {
|
||||
throw new Error(
|
||||
`package ${packageJson.version} has missing pnpm.patchedDependencies in package fixture: ${missingPatches
|
||||
.map(([dependency, patchFile]) => `${dependency} -> ${patchFile}`)
|
||||
.join(", ")}`,
|
||||
);
|
||||
}
|
||||
if (Object.keys(keptPatches).length > 0) {
|
||||
nextPnpm.patchedDependencies = keptPatches;
|
||||
} else {
|
||||
@@ -105,6 +130,31 @@ fixture_sha="$(git -C "$git_root" rev-parse HEAD)"
|
||||
pkg_tgz_path="$package_tgz"
|
||||
|
||||
npm install -g --prefix /tmp/npm-prefix --omit=optional "$pkg_tgz_path"
|
||||
package_version="$(node -p "require('/tmp/npm-prefix/lib/node_modules/openclaw/package.json').version")"
|
||||
OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT="$(
|
||||
node - "$package_version" <<"NODE"
|
||||
const version = process.argv[2] || "";
|
||||
const match = /^(\d{4})\.(\d{1,2})\.(\d{1,2})(?:[-+].*)?$/.exec(version);
|
||||
if (!match) {
|
||||
console.log("0");
|
||||
process.exit(0);
|
||||
}
|
||||
const value = [Number(match[1]), Number(match[2]), Number(match[3])];
|
||||
const max = [2026, 4, 25];
|
||||
for (let i = 0; i < value.length; i += 1) {
|
||||
if (value[i] < max[i]) {
|
||||
console.log("1");
|
||||
process.exit(0);
|
||||
}
|
||||
if (value[i] > max[i]) {
|
||||
console.log("0");
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
console.log("1");
|
||||
NODE
|
||||
)"
|
||||
export OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT
|
||||
|
||||
home_dir="$(mktemp -d /tmp/openclaw-update-channel-switch-home.XXXXXX)"
|
||||
export HOME="$home_dir"
|
||||
@@ -149,7 +199,11 @@ const path = require("node:path");
|
||||
const configPath = path.join(process.env.HOME, ".openclaw", "openclaw.json");
|
||||
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
||||
if (config.update?.channel !== "dev") {
|
||||
console.log(`legacy package did not persist update.channel dev; got ${JSON.stringify(config.update?.channel)}`);
|
||||
if (process.env.OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT === "1") {
|
||||
console.log(`legacy package did not persist update.channel dev; got ${JSON.stringify(config.update?.channel)}`);
|
||||
} else {
|
||||
throw new Error(`expected persisted update.channel dev, got ${JSON.stringify(config.update?.channel)}`);
|
||||
}
|
||||
}
|
||||
NODE
|
||||
|
||||
@@ -190,7 +244,11 @@ const path = require("node:path");
|
||||
const configPath = path.join(process.env.HOME, ".openclaw", "openclaw.json");
|
||||
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
||||
if (config.update?.channel !== "stable") {
|
||||
console.log(`legacy package did not persist update.channel stable; got ${JSON.stringify(config.update?.channel)}`);
|
||||
if (process.env.OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT === "1") {
|
||||
console.log(`legacy package did not persist update.channel stable; got ${JSON.stringify(config.update?.channel)}`);
|
||||
} else {
|
||||
throw new Error(`expected persisted update.channel stable, got ${JSON.stringify(config.update?.channel)}`);
|
||||
}
|
||||
}
|
||||
NODE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user