fix(config): add --dry-run support to unset (#81895)

* Add config unset dry-run

Add --dry-run support to config unset, including JSON output and allow-exec validation parity with config set/patch dry-run handling.

* Refresh checks after proof update

* fix(config): address unset dry-run review

Return structured JSON when config unset dry-run misses a path and validate broad secret provider/default unsets against affected SecretRefs.
This commit is contained in:
Gio Della-Libera
2026-05-16 11:09:42 -07:00
committed by GitHub
parent e06782d5e7
commit 489cab2738
7 changed files with 354 additions and 20 deletions

View File

@@ -149,6 +149,30 @@ describe("route-args", () => {
]),
).toEqual({
path: "update.channel",
cliOptions: {
dryRun: false,
allowExec: false,
json: false,
},
});
expect(
parseConfigUnsetRouteArgs([
"node",
"openclaw",
"config",
"unset",
"--dry-run",
"--json",
"--allow-exec",
"update.channel",
]),
).toEqual({
path: "update.channel",
cliOptions: {
dryRun: true,
allowExec: true,
json: true,
},
});
expect(parseConfigGetRouteArgs(["node", "openclaw", "config", "get", "--json"])).toBeNull();
});

View File

@@ -182,11 +182,19 @@ export function parseConfigGetRouteArgs(argv: string[]) {
export function parseConfigUnsetRouteArgs(argv: string[]) {
const path = parseSinglePositional(argv, {
commandPath: ["config", "unset"],
booleanFlags: ["--dry-run", "--allow-exec", "--json"],
});
if (!path) {
return null;
}
return { path };
return {
path,
cliOptions: {
dryRun: hasFlag(argv, "--dry-run"),
allowExec: hasFlag(argv, "--allow-exec"),
json: hasFlag(argv, "--json"),
},
};
}
export function parseModelsListRouteArgs(argv: string[]) {

View File

@@ -344,7 +344,14 @@ describe("program routes", () => {
await expect(
route.run(["node", "openclaw", "--profile", "work", "config", "unset", "update.channel"]),
).resolves.toBe(true);
expect(runConfigUnsetMock).toHaveBeenCalledWith({ path: "update.channel" });
expect(runConfigUnsetMock).toHaveBeenCalledWith({
path: "update.channel",
cliOptions: {
dryRun: false,
allowExec: false,
json: false,
},
});
});
it("passes config get path when root value options appear after subcommand", async () => {
@@ -369,7 +376,38 @@ describe("program routes", () => {
await expect(
route.run(["node", "openclaw", "config", "unset", "--profile", "work", "update.channel"]),
).resolves.toBe(true);
expect(runConfigUnsetMock).toHaveBeenCalledWith({ path: "update.channel" });
expect(runConfigUnsetMock).toHaveBeenCalledWith({
path: "update.channel",
cliOptions: {
dryRun: false,
allowExec: false,
json: false,
},
});
});
it("passes config unset dry-run options", async () => {
const route = expectRoute(["config", "unset"]);
await expect(
route.run([
"node",
"openclaw",
"config",
"unset",
"--dry-run",
"--json",
"--allow-exec",
"update.channel",
]),
).resolves.toBe(true);
expect(runConfigUnsetMock).toHaveBeenCalledWith({
path: "update.channel",
cliOptions: {
dryRun: true,
allowExec: true,
json: true,
},
});
});
it("returns false for config get route when unknown option appears", async () => {