fix(migrate): use resolved provider for options (#83323)

* fix(migrate): use resolved provider for options

* test(migrate): cover resolved provider apply options
This commit is contained in:
Gio Della-Libera
2026-05-18 18:54:26 -07:00
committed by GitHub
parent f526d96c98
commit 8eb0a1777f
4 changed files with 112 additions and 4 deletions

View File

@@ -0,0 +1,75 @@
import { mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { describe, expect, it, vi } from "vitest";
import type { MigrationPlan, MigrationProviderPlugin } from "../../plugins/types.js";
import { createNonExitingRuntime } from "../../runtime.js";
import { runMigrationApply } from "./apply.js";
const stateDir = mkdtempSync(path.join(tmpdir(), "openclaw-migrate-apply-"));
vi.mock("../../config/paths.js", () => ({
resolveStateDir: () => stateDir,
}));
function buildEmptyPlan(): MigrationPlan {
return {
providerId: "codex",
source: "/tmp/codex",
summary: {
total: 0,
planned: 0,
migrated: 0,
skipped: 0,
conflicts: 0,
errors: 0,
sensitive: 0,
},
items: [],
};
}
describe("runMigrationApply", () => {
it("uses the resolved provider id when forwarding Codex options", async () => {
const plan = vi.fn(async () => buildEmptyPlan());
const apply = vi.fn(async () => buildEmptyPlan());
const provider: MigrationProviderPlugin = {
id: "codex",
label: "Codex",
plan,
apply,
};
await runMigrationApply({
runtime: createNonExitingRuntime(),
opts: {
yes: true,
json: true,
noBackup: true,
configOverride: {},
configPatchMode: "return",
verifyPluginApps: true,
},
providerId: "codex",
provider,
});
expect(plan).toHaveBeenCalledWith(
expect.objectContaining({
providerOptions: {
configPatchMode: "return",
verifyPluginApps: true,
},
}),
);
expect(apply).toHaveBeenCalledWith(
expect.objectContaining({
providerOptions: {
configPatchMode: "return",
verifyPluginApps: true,
},
}),
expect.anything(),
);
});
});

View File

@@ -69,7 +69,7 @@ export async function runMigrationApply(params: {
includeSecrets: params.opts.includeSecrets,
overwrite: params.opts.overwrite,
configOverride: params.opts.configOverride,
providerOptions: buildMigrationProviderOptions(params.opts),
providerOptions: buildMigrationProviderOptions(params.opts, params.providerId),
runtime: params.runtime,
json: params.opts.json,
}),
@@ -99,7 +99,7 @@ export async function runMigrationApply(params: {
includeSecrets: params.opts.includeSecrets,
overwrite: params.opts.overwrite,
configOverride: params.opts.configOverride,
providerOptions: buildMigrationProviderOptions(params.opts),
providerOptions: buildMigrationProviderOptions(params.opts, params.providerId),
runtime: params.runtime,
backupPath,
reportDir,

View File

@@ -0,0 +1,32 @@
import { describe, expect, it } from "vitest";
import { buildMigrationProviderOptions } from "./providers.js";
describe("buildMigrationProviderOptions", () => {
it("uses the resolved provider id for Codex options", () => {
expect(
buildMigrationProviderOptions(
{
configPatchMode: "return",
verifyPluginApps: true,
},
"codex",
),
).toEqual({
configPatchMode: "return",
verifyPluginApps: true,
});
});
it("omits Codex-only options for other providers", () => {
expect(
buildMigrationProviderOptions(
{
configPatchMode: "return",
provider: "other",
verifyPluginApps: true,
},
"other",
),
).toBeUndefined();
});
});

View File

@@ -28,12 +28,13 @@ export function resolveMigrationProvider(
export function buildMigrationProviderOptions(
opts: MigrateCommonOptions,
providerId = opts.provider,
): Record<string, unknown> | undefined {
const options: Record<string, unknown> = {};
if (opts.provider === "codex" && opts.verifyPluginApps === true) {
if (providerId === "codex" && opts.verifyPluginApps === true) {
options.verifyPluginApps = true;
}
if (opts.provider === "codex" && opts.configPatchMode) {
if (providerId === "codex" && opts.configPatchMode) {
options.configPatchMode = opts.configPatchMode;
}
return Object.keys(options).length > 0 ? options : undefined;