Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/cli/cli.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { boolean, defineConfig, string } from "@superset/cli-framework";

const VERSION = "0.2.13";
const VERSION = "0.2.14";

export default defineConfig({
name: "superset",
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@superset/cli",
"version": "0.2.13",
"version": "0.2.14",
"private": true,
"type": "module",
"scripts": {
Expand Down
74 changes: 74 additions & 0 deletions packages/cli/src/commands/projects/setup/command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { boolean, CLIError, positional, string } from "@superset/cli-framework";
import { command } from "../../../lib/command";
import { requireHostTarget, resolveHostTarget } from "../../../lib/host-target";

export default command({
description:
"Adopt an existing project on a host (clone its repo or import a folder)",
args: [positional("id").required().desc("Project UUID to adopt")],
options: {
host: string().desc("Target host machineId"),
local: boolean().desc("Target this machine"),
parentDir: string().desc(
"Parent directory to clone the project's repo into (clone mode)",
),
import: string().desc(
"Existing local repo path on the target host (import mode)",
),
allowRelocate: boolean().desc(
"Permit re-importing at a different path if the project is already set up here",
),
},
run: async ({ ctx, args, options }) => {
const projectId = args.id as string;
const organizationId = ctx.config.organizationId;
if (!organizationId) {
throw new CLIError("No active organization", "Run: superset auth login");
}

if (Boolean(options.parentDir) === Boolean(options.import)) {
throw new CLIError(
"Specify exactly one of --parent-dir or --import",
"Use --parent-dir <path> to clone, or --import <path> to register an existing folder",
);
}
Comment on lines +29 to +34

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Mutex error message fires for "neither provided" case too

Boolean(undefined) === Boolean(undefined) is true, so a user who omits both flags sees "Specify exactly one of --parent-dir or --import" — a message that reads as if they supplied both rather than neither. The same pattern exists in create/command.ts, but here the lack of a --clone analogue makes the two-flag surface smaller and the "neither" case more likely to be hit accidentally. A disambiguated check (or a separate else if branch) would make the error clearer to users in the omit-both path.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/cli/src/commands/projects/setup/command.ts
Line: 29-34

Comment:
**Mutex error message fires for "neither provided" case too**

`Boolean(undefined) === Boolean(undefined)` is `true`, so a user who omits both flags sees "Specify exactly one of --parent-dir or --import" — a message that reads as if they supplied both rather than neither. The same pattern exists in `create/command.ts`, but here the lack of a `--clone` analogue makes the two-flag surface smaller and the "neither" case more likely to be hit accidentally. A disambiguated check (or a separate `else if` branch) would make the error clearer to users in the omit-both path.

How can I resolve this? If you propose a fix, please make it concise.

if (options.allowRelocate && !options.import) {
throw new CLIError(
"--allow-relocate only applies to --import",
"Drop --allow-relocate, or switch to --import <path>",
);
}

const hostId = requireHostTarget({
host: options.host ?? undefined,
local: options.local ?? undefined,
});

const target = resolveHostTarget({
requestedHostId: hostId,
organizationId,
userJwt: ctx.bearer,
});

const mode = options.parentDir
? {
kind: "clone" as const,
parentDir: options.parentDir,
}
: {
kind: "import" as const,
repoPath: options.import as string,
allowRelocate: options.allowRelocate ?? false,
};

const result = await target.client.project.setup.mutate({
projectId,
mode,
});

return {
data: result,
message: `Set up project ${projectId} on host ${target.hostId}`,
};
},
});
Loading