fix(update): honor update.channel for update.run

This commit is contained in:
Peter Steinberger
2026-02-03 17:57:44 -08:00
parent 61a7fc5e0e
commit bbe9cb3022
5 changed files with 98 additions and 2 deletions

View File

@@ -208,6 +208,54 @@ describe("runGatewayUpdate", () => {
expect(calls.some((call) => call === "npm i -g openclaw@latest")).toBe(true);
});
it("uses update channel for global npm installs when tag is omitted", async () => {
const nodeModules = path.join(tempDir, "node_modules");
const pkgRoot = path.join(nodeModules, "openclaw");
await fs.mkdir(pkgRoot, { recursive: true });
await fs.writeFile(
path.join(pkgRoot, "package.json"),
JSON.stringify({ name: "openclaw", version: "1.0.0" }),
"utf-8",
);
const calls: string[] = [];
const runCommand = async (argv: string[]) => {
const key = argv.join(" ");
calls.push(key);
if (key === `git -C ${pkgRoot} rev-parse --show-toplevel`) {
return { stdout: "", stderr: "not a git repository", code: 128 };
}
if (key === "npm root -g") {
return { stdout: nodeModules, stderr: "", code: 0 };
}
if (key === "npm i -g openclaw@beta") {
await fs.writeFile(
path.join(pkgRoot, "package.json"),
JSON.stringify({ name: "openclaw", version: "2.0.0" }),
"utf-8",
);
return { stdout: "ok", stderr: "", code: 0 };
}
if (key === "pnpm root -g") {
return { stdout: "", stderr: "", code: 1 };
}
return { stdout: "", stderr: "", code: 0 };
};
const result = await runGatewayUpdate({
cwd: pkgRoot,
runCommand: async (argv, _options) => runCommand(argv),
timeoutMs: 5000,
channel: "beta",
});
expect(result.status).toBe("ok");
expect(result.mode).toBe("npm");
expect(result.before?.version).toBe("1.0.0");
expect(result.after?.version).toBe("2.0.0");
expect(calls.some((call) => call === "npm i -g openclaw@beta")).toBe(true);
});
it("cleans stale npm rename dirs before global update", async () => {
const nodeModules = path.join(tempDir, "node_modules");
const pkgRoot = path.join(nodeModules, "openclaw");

View File

@@ -3,7 +3,14 @@ import os from "node:os";
import path from "node:path";
import { type CommandOptions, runCommandWithTimeout } from "../process/exec.js";
import { trimLogTail } from "./restart-sentinel.js";
import { DEV_BRANCH, isBetaTag, isStableTag, type UpdateChannel } from "./update-channels.js";
import {
channelToNpmTag,
DEFAULT_PACKAGE_CHANNEL,
DEV_BRANCH,
isBetaTag,
isStableTag,
type UpdateChannel,
} from "./update-channels.js";
import { compareSemverStrings } from "./update-check.js";
import {
cleanupGlobalRenameDirs,
@@ -800,7 +807,9 @@ export async function runGatewayUpdate(opts: UpdateRunnerOptions = {}): Promise<
globalRoot: path.dirname(pkgRoot),
packageName,
});
const spec = `${packageName}@${normalizeTag(opts.tag)}`;
const channel = opts.channel ?? DEFAULT_PACKAGE_CHANNEL;
const tag = normalizeTag(opts.tag ?? channelToNpmTag(channel));
const spec = `${packageName}@${tag}`;
const updateStep = await runStep({
runCommand,
name: "global update",