mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 13:21:25 +00:00
feat: add update channel support
This commit is contained in:
@@ -30,6 +30,12 @@ export type RegistryStatus = {
|
||||
error?: string;
|
||||
};
|
||||
|
||||
export type NpmTagStatus = {
|
||||
tag: string;
|
||||
version: string | null;
|
||||
error?: string;
|
||||
};
|
||||
|
||||
export type UpdateCheckResult = {
|
||||
root: string | null;
|
||||
installKind: "git" | "package" | "unknown";
|
||||
@@ -263,17 +269,32 @@ async function fetchWithTimeout(url: string, timeoutMs: number): Promise<Respons
|
||||
export async function fetchNpmLatestVersion(params?: {
|
||||
timeoutMs?: number;
|
||||
}): Promise<RegistryStatus> {
|
||||
const res = await fetchNpmTagVersion({ tag: "latest", timeoutMs: params?.timeoutMs });
|
||||
return {
|
||||
latestVersion: res.version,
|
||||
error: res.error,
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchNpmTagVersion(params: {
|
||||
tag: string;
|
||||
timeoutMs?: number;
|
||||
}): Promise<NpmTagStatus> {
|
||||
const timeoutMs = params?.timeoutMs ?? 3500;
|
||||
const tag = params.tag;
|
||||
try {
|
||||
const res = await fetchWithTimeout("https://registry.npmjs.org/clawdbot/latest", timeoutMs);
|
||||
const res = await fetchWithTimeout(
|
||||
`https://registry.npmjs.org/clawdbot/${encodeURIComponent(tag)}`,
|
||||
timeoutMs,
|
||||
);
|
||||
if (!res.ok) {
|
||||
return { latestVersion: null, error: `HTTP ${res.status}` };
|
||||
return { tag, version: null, error: `HTTP ${res.status}` };
|
||||
}
|
||||
const json = (await res.json()) as { version?: unknown };
|
||||
const latestVersion = typeof json?.version === "string" ? json.version : null;
|
||||
return { latestVersion };
|
||||
const version = typeof json?.version === "string" ? json.version : null;
|
||||
return { tag, version };
|
||||
} catch (err) {
|
||||
return { latestVersion: null, error: String(err) };
|
||||
return { tag, version: null, error: String(err) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -159,6 +159,54 @@ describe("runGatewayUpdate", () => {
|
||||
expect(calls.some((call) => call === "npm i -g clawdbot@latest")).toBe(true);
|
||||
});
|
||||
|
||||
it("updates global npm installs with tag override", async () => {
|
||||
const nodeModules = path.join(tempDir, "node_modules");
|
||||
const pkgRoot = path.join(nodeModules, "clawdbot");
|
||||
await fs.mkdir(pkgRoot, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(pkgRoot, "package.json"),
|
||||
JSON.stringify({ name: "clawdbot", 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 clawdbot@beta") {
|
||||
await fs.writeFile(
|
||||
path.join(pkgRoot, "package.json"),
|
||||
JSON.stringify({ name: "clawdbot", 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,
|
||||
tag: "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 clawdbot@beta")).toBe(true);
|
||||
});
|
||||
|
||||
it("updates global bun installs when detected", async () => {
|
||||
const oldBunInstall = process.env.BUN_INSTALL;
|
||||
const bunInstall = path.join(tempDir, "bun-install");
|
||||
|
||||
@@ -52,6 +52,7 @@ export type UpdateStepProgress = {
|
||||
type UpdateRunnerOptions = {
|
||||
cwd?: string;
|
||||
argv1?: string;
|
||||
tag?: string;
|
||||
timeoutMs?: number;
|
||||
runCommand?: CommandRunner;
|
||||
progress?: UpdateStepProgress;
|
||||
@@ -267,10 +268,17 @@ function managerInstallArgs(manager: "pnpm" | "bun" | "npm") {
|
||||
return ["npm", "install"];
|
||||
}
|
||||
|
||||
function globalUpdateArgs(manager: "pnpm" | "npm" | "bun") {
|
||||
if (manager === "pnpm") return ["pnpm", "add", "-g", "clawdbot@latest"];
|
||||
if (manager === "bun") return ["bun", "add", "-g", "clawdbot@latest"];
|
||||
return ["npm", "i", "-g", "clawdbot@latest"];
|
||||
function normalizeTag(tag?: string) {
|
||||
const trimmed = tag?.trim();
|
||||
if (!trimmed) return "latest";
|
||||
return trimmed.startsWith("clawdbot@") ? trimmed.slice("clawdbot@".length) : trimmed;
|
||||
}
|
||||
|
||||
function globalUpdateArgs(manager: "pnpm" | "npm" | "bun", tag?: string) {
|
||||
const spec = `clawdbot@${normalizeTag(tag)}`;
|
||||
if (manager === "pnpm") return ["pnpm", "add", "-g", spec];
|
||||
if (manager === "bun") return ["bun", "add", "-g", spec];
|
||||
return ["npm", "i", "-g", spec];
|
||||
}
|
||||
|
||||
// Total number of visible steps in a successful git update flow
|
||||
@@ -472,7 +480,7 @@ export async function runGatewayUpdate(opts: UpdateRunnerOptions = {}): Promise<
|
||||
const updateStep = await runStep({
|
||||
runCommand,
|
||||
name: "global update",
|
||||
argv: globalUpdateArgs(globalManager),
|
||||
argv: globalUpdateArgs(globalManager, opts.tag),
|
||||
cwd: pkgRoot,
|
||||
timeoutMs,
|
||||
progress,
|
||||
|
||||
Reference in New Issue
Block a user