Skip to content

feat(host-service): project.setup endpoint for local repo path assignment#3345

Merged
Kitenite merged 6 commits intomainfrom
host-project-paths
Apr 11, 2026
Merged

feat(host-service): project.setup endpoint for local repo path assignment#3345
Kitenite merged 6 commits intomainfrom
host-project-paths

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Apr 10, 2026

Summary

  • Adds project.setup mutation to host-service that lets users import an existing local repo or clone to a chosen directory, instead of auto-cloning to ~/.superset/repos/{id}
  • Adds git remote validation utilities (SSH + HTTPS URL normalization, multi-remote matching) to verify imported repos match the cloud project's GitHub repo
  • Includes design doc covering the full phased plan (workspace.create throws + desktop UI are deferred)

Design decisions

  • Local-only storage — project path lives in host-service SQLite projects.repoPath, no new cloud table needed
  • Throw-on-create pattern (deferred) — workspace.create will throw PROJECT_NOT_SETUP instead of auto-cloning, letting the client prompt for import/clone
  • Single endpointproject.setup upserts, so re-running with import mode handles re-pointing (no separate updatePath needed)

Test plan

  • Call project.setup with mode: "import" pointing at an existing local repo — verify it validates git remotes and upserts the local project row
  • Call project.setup with mode: "import" on a repo with wrong remotes — verify it throws with mismatch details
  • Call project.setup with mode: "clone" — verify it clones and upserts
  • Call project.setup twice on same project — verify upsert overwrites cleanly
  • Typecheck passes (bun run typecheck --filter=@superset/host-service)

Summary by cubic

Adds a project.setup endpoint in host-service to import an existing local repo or clone to a chosen directory, preventing duplicate checkouts. Validates GitHub remotes against the cloud project and stores the repo path locally.

  • New Features

    • project.setup mutation with mode: "import" | "clone"; returns { repoPath }.
    • GitHub remote validation with multi-remote matching via utils/git-remote.ts; uses shared parseGitHubRemote (SSH/HTTPS and ssh:// support, credential-safe URL).
    • Upserts projects.repoPath in local SQLite, allowing re-runs to re-point paths.
    • Adds design doc; workspace.create throw pattern is deferred (auto-clone remains for now).
  • Bug Fixes

    • Validate clone parent path exists and is a directory; resolve absolute paths with path.resolve.
    • Wrap simple-git clone in try/catch for clearer error messages.
    • Use git rev-parse for repo detection.
    • Replace non-null assertions with explicit guards for remote parsing and matching.
    • Clean up the target directory on any clone or post-clone validation error.

Written for commit c2b92ba. Summary will update on new commits.

Summary by CodeRabbit

  • Documentation

    • Added a design document describing host-local project path mapping and phased implementation.
  • New Features

    • Host-local project path mapping to allow reuse of local checkouts per host.
    • Project setup flow letting users import existing repos or clone into a chosen local path.
    • Git remote validation with clear match/mismatch feedback, guided setup, and automatic retry of workspace creation.

Outlines the approach for allowing users to import existing local repos
or clone to a chosen location instead of auto-cloning to a fixed path.
Covers local-only storage decision, throw-on-create pattern, and phased
implementation plan.
…repos

Adds a `project.setup` mutation that lets users either import an
existing local repo or clone to a chosen directory. Validates git
remotes against the cloud project's GitHub repo (handles SSH + HTTPS).
Upserts the local projects table so re-running handles re-pointing.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 10, 2026

📝 Walkthrough

Walkthrough

Adds a design doc and host-service implementation for per-host project path mapping: a new protected project.setup mutation (modes: import | clone), git-remote helper utilities, and upserting per-host projects.repoPath and related metadata into the host SQLite.

Changes

Cohort / File(s) Summary
Design Documentation
docs/design/v2-host-project-paths.md
New design doc describing per-host path mapping, error model (PROJECT_NOT_SETUP, PROJECT_PATH_MISSING), project.setup behavior (modes import/clone), desktop UI flow, phased checklist, and edge cases.
Project Router
packages/host-service/src/trpc/router/project/project.ts
Added protected setup mutation accepting `{ projectId, mode: "import"
Git Utilities
packages/host-service/src/trpc/router/project/utils/git-remote.ts
New helpers: getAllRemoteUrls(SimpleGit), getGitHubRemotes(SimpleGit) (parses GitHub remotes), and findMatchingRemote(remotes, expectedSlug) (case-insensitive owner/name match). Exports ParsedGitHubRemote type.

Sequence Diagram

sequenceDiagram
    participant Client
    participant HostRouter as Host Project Router
    participant Cloud as Cloud API/DB
    participant Git as Git / FileSystem
    participant HostDB as Host SQLite

    Client->>HostRouter: project.setup(projectId, mode, localPath)
    HostRouter->>Cloud: fetch project metadata (repoCloneUrl, provider, slug)
    
    alt mode == "import"
        HostRouter->>Git: assert localPath exists & is directory
        HostRouter->>Git: run git rev-parse --show-toplevel
        HostRouter->>Git: getAllRemoteUrls / getGitHubRemotes
        HostRouter->>Git: findMatchingRemote(expectedSlug)
    else mode == "clone"
        HostRouter->>Git: validate parent directory exists
        HostRouter->>Git: clone repoCloneUrl -> targetDir
        HostRouter->>Git: getAllRemoteUrls / getGitHubRemotes on clone
        HostRouter->>Git: findMatchingRemote(expectedSlug)
    end

    HostRouter->>HostDB: upsert projects row (repoPath, repoOwner, repoName, repoUrl, remoteName)
    HostRouter->>Client: return { repoPath }
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped through remotes, sniffed each name,

found a root or cloned and called it home,
repo owner, repo name — a tiny fame,
host SQLite now knows the path I roam,
whiskers twitch: setup done, I hop and roam.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main feature: adding a project.setup endpoint for local repo path assignment in host-service.
Description check ✅ Passed The PR description provides a comprehensive summary of changes, design decisions, and a detailed test plan covering the main scenarios.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch host-project-paths

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 10, 2026

Greptile Summary

This PR adds a project.setup tRPC mutation to the host-service, giving users the ability to point a cloud project at an existing local checkout (mode: "import") or have the service clone it to a chosen directory (mode: "clone"), rather than always auto-cloning to ~/.superset/repos/{id}. A companion git-remote.ts utility handles SSH/HTTPS URL normalization and multi-remote matching so that any remote pointing to the correct GitHub repo is accepted.

Key changes:

  • project.setup mutation — validates path/git-root for import mode, clones for clone mode, then upserts the local projects row with repoPath, remote metadata, and owner/name.
  • git-remote.ts — three pure utilities: getAllRemoteUrls (parses git remote -v), extractGitHubSlug (normalizes SSH + HTTPS → owner/repo), and findMatchingRemote (case-insensitive slug comparison across all remotes).
  • Design doc — captures the local-only storage decision, throw-on-create pattern (deferred to Phase 2), and phased UI rollout.

Two P1 issues in cloneRepo need attention before merging: the function only checks that parentDir exists (not that it's a directory), and clone failures from simpleGit are not wrapped in a TRPCError, leaving callers with an opaque INTERNAL_SERVER_ERROR instead of a useful message.

Confidence Score: 3/5

Safe to merge after fixing the two P1 bugs in cloneRepo — missing directory-type guard and unhandled simpleGit errors.

The core import-mode logic is sound and well-validated. Clone mode has two concrete gaps: it skips the isDirectory() check that import mode correctly applies, and any simpleGit clone failure propagates as a raw error rather than a user-friendly TRPCError. Both are straightforward 3-5 line fixes. The git-remote utilities are clean and the design is well-reasoned.

packages/host-service/src/trpc/router/project/project.ts — specifically the cloneRepo function (lines 193–216).

Important Files Changed

Filename Overview
packages/host-service/src/trpc/router/project/project.ts Adds project.setup mutation with import/clone modes; cloneRepo is missing a directory-type check on parentDir and doesn't wrap simpleGit errors in TRPCError, and the post-mode remote fetch duplicates work already done in importExistingRepo.
packages/host-service/src/trpc/router/project/utils/git-remote.ts New git remote utilities correctly handle SCP-style SSH and HTTPS URLs with case-insensitive slug matching, but the ssh:// URI scheme (also supported by GitHub) is not covered.
docs/design/v2-host-project-paths.md Well-written design doc covering local-only storage decision, throw-on-create pattern, phased rollout, and edge cases; no issues found.

Sequence Diagram

sequenceDiagram
    participant Desktop
    participant HostService as host-service (tRPC)
    participant Cloud as Cloud API
    participant LocalSQLite as Local SQLite
    participant FS as Filesystem / Git

    Desktop->>HostService: project.setup({ projectId, mode, localPath })
    HostService->>Cloud: v2Project.get({ organizationId, id })
    Cloud-->>HostService: { repoCloneUrl }
    HostService->>HostService: extractGitHubSlug(repoCloneUrl) → expectedSlug

    alt mode = import
        HostService->>FS: existsSync + statSync(localPath)
        HostService->>FS: git rev-parse --show-toplevel
        FS-->>HostService: gitRoot
        HostService->>FS: git remote -v (on gitRoot)
        FS-->>HostService: remotes map
        HostService->>HostService: findMatchingRemote(remotes, expectedSlug)
        note over HostService: throws BAD_REQUEST if no match
    else mode = clone
        HostService->>FS: existsSync(parentDir)
        HostService->>FS: simpleGit().clone(repoCloneUrl, targetPath)
        FS-->>HostService: clone complete
    end

    HostService->>FS: git remote -v (on repoPath)
    FS-->>HostService: remotes + matchingRemote
    HostService->>LocalSQLite: INSERT projects ON CONFLICT DO UPDATE
    LocalSQLite-->>HostService: ok
    HostService-->>Desktop: { repoPath }
Loading

Reviews (1): Last reviewed commit: "feat(host-service): add project.setup en..." | Re-trigger Greptile

Comment on lines +196 to +203
): Promise<string> {
if (!existsSync(parentDir)) {
throw new TRPCError({
code: "BAD_REQUEST",
message: `Parent directory does not exist: ${parentDir}`,
});
}

This comment was marked as resolved.

Comment on lines +213 to +215

await simpleGit().clone(repoCloneUrl, targetPath);

This comment was marked as resolved.

Comment on lines +31 to +45
export function extractGitHubSlug(remoteUrl: string): string | null {
// SSH format: git@github.com:owner/repo.git
const sshMatch = remoteUrl.match(
/^[\w.-]+@github\.com:([^/]+\/[^/]+?)(?:\.git)?$/,
);
if (sshMatch?.[1]) return sshMatch[1];

// HTTPS format: https://github.com/owner/repo.git
const httpsMatch = remoteUrl.match(
/^https?:\/\/github\.com\/([^/]+\/[^/]+?)(?:\.git)?$/,
);
if (httpsMatch?.[1]) return httpsMatch[1];

return null;
}

This comment was marked as resolved.

Comment on lines +60 to +70
// Extract repo metadata from the resolved path
const git = simpleGit(repoPath);
const remotes = await getAllRemoteUrls(git);
const matchingRemote = findMatchingRemote(remotes, expectedSlug);
const remoteUrl = matchingRemote
? remotes.get(matchingRemote)
: undefined;
const repoFullName = remoteUrl
? extractGitHubSlug(remoteUrl)
: expectedSlug;
const [repoOwner, repoName] = repoFullName?.split("/") ?? [];

This comment was marked as resolved.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 10, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch
  • ✅ Electric Fly.io app

Thank you for your contribution! 🎉

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/design/v2-host-project-paths.md`:
- Around line 49-56: The fenced code blocks containing the ASCII tree/flow
diagrams (e.g., the block showing "host-service local SQLite" and other similar
blocks) are missing language identifiers and trigger markdownlint MD040; edit
each fenced block (including the ones referenced later in the file) to add the
language tag "text" after the opening ``` so they read ```text and save—this
will satisfy markdownlint without changing content.
- Around line 173-177: Update the "Validation for 'Use existing directory'"
wording to not require a literal .git directory; instead state that validation
should use git rev-parse --show-toplevel (as used by the host-service import
path validation and project.setup) so linked worktrees (a .git file) and paths
inside a repo are accepted; replace the bullet "Contains a `.git` folder (is a
git repo)" with a line that explains checking repo root via git rev-parse and
matching remote URL, and add a note that either a .git folder or a .git file
(worktree) is valid.

In `@packages/host-service/src/trpc/router/project/project.ts`:
- Line 2: importExistingRepo() already stores an absolute gitRoot but
cloneRepo() persists the client's raw localPath, making projects.repoPath
cwd-dependent and fragile; change cloneRepo() to resolve and persist an absolute
path (use path.resolve/localPath -> absolute) and before cloning validate that
the parent directory is an actual directory (use
fs.statSync(parentDir).isDirectory() or fs.lstatSync(...).isDirectory()) rather
than existsSync(parentDir). Also update any code that constructs parentDir
(references to basename/join) to compute parent = path.dirname(resolvedPath) so
validation and persisted repoPath are consistent; ensure projects.repoPath is
always the resolved absolute path.
- Around line 64-81: The code currently persists and returns raw git remotes
(repoUrl) which may contain embedded credentials; update the logic around
repoFullName/remoteUrl (the remotes Map, matchingRemote variable,
extractGitHubSlug usage, and the ctx.db.insert into projects where repoUrl is
set) to sanitize remoteUrl before any use: strip userinfo/credentials from the
URL (or replace with a credentialless form like only scheme+host+path) and store
only the sanitized version in projects.repoUrl, and update any error/mismatch
messages (the mismatch handling around lines referenced also) to use the
sanitizedRemote instead of the raw remote; ensure extractGitHubSlug still
receives a safe value (or derive slug from sanitized URL) so no raw credentials
are logged or returned.

In `@packages/host-service/src/trpc/router/project/utils/git-remote.ts`:
- Around line 14-18: The current loop that splits output and uses
/^(\S+)\s+(\S+)\s+\(fetch\)$/ is too narrow and brittle; update the parsing in
the block that iterates over output (the variable named output, iterating with
for (const line of ...), populating remotes) to split lines with a CRLF-safe
split (e.g. split by /\r?\n/) and accept additional remote URL forms (ssh://...,
https://..., optional trailing slash, optional .git) by broadening the regex or,
better, reuse the existing parseGitHubRemote logic: call or import
parseGitHubRemote (from parse-github-remote) to normalize match[2] values before
inserting into remotes, ensuring both fetch and push lines are handled and
normalized so project.setup has all valid GitHub remote forms.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 84d44628-5072-464a-9f9e-7a4c729b26df

📥 Commits

Reviewing files that changed from the base of the PR and between 1bdd700 and 3cc23af.

📒 Files selected for processing (3)
  • docs/design/v2-host-project-paths.md
  • packages/host-service/src/trpc/router/project/project.ts
  • packages/host-service/src/trpc/router/project/utils/git-remote.ts

Comment on lines +49 to +56
```
host-service local SQLite
└── projects
├── id text PK (matches cloud v2_projects.id)
├── repoPath text NOT NULL ← this is the path mapping
├── repoProvider, repoOwner, repoName, repoUrl, remoteName
└── createdAt
```

This comment was marked as resolved.

Comment thread docs/design/v2-host-project-paths.md
Comment thread packages/host-service/src/trpc/router/project/project.ts Outdated
Comment thread packages/host-service/src/trpc/router/project/project.ts Outdated
Comment thread packages/host-service/src/trpc/router/project/utils/git-remote.ts Outdated
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

3 issues found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/host-service/src/trpc/router/project/utils/git-remote.ts">

<violation number="1" location="packages/host-service/src/trpc/router/project/utils/git-remote.ts:44">
P2: `ssh://` URI-format remotes are not handled. GitHub supports both SCP-style (`git@github.com:org/repo.git`) and full SSH URI (`ssh://git@github.com/org/repo.git`). The latter won't match either regex, causing valid repos to fail import validation with a misleading "no remote matches" error.

Add a third pattern between the SSH and HTTPS checks:
```typescript
const sshUriMatch = remoteUrl.match(
  /^ssh:\/\/[\w.-]+@github\.com\/([^/]+\/[^/]+?)(?:\.git)?$/,
);
if (sshUriMatch?.[1]) return sshUriMatch[1];
```</violation>
</file>

<file name="packages/host-service/src/trpc/router/project/project.ts">

<violation number="1" location="packages/host-service/src/trpc/router/project/project.ts:197">
P2: Validate that `parentDir` is a directory (not just existing) before cloning, so invalid file paths return a controlled `BAD_REQUEST` error.</violation>

<violation number="2" location="packages/host-service/src/trpc/router/project/project.ts:214">
P2: Wrap the `clone()` call in a try/catch to throw a `TRPCError` with `BAD_REQUEST`. Currently a network timeout, auth failure, or disk-full error propagates as a raw `GitError`, which tRPC surfaces as a generic `INTERNAL_SERVER_ERROR` with no actionable message for the client.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread packages/host-service/src/trpc/router/project/utils/git-remote.ts Outdated
Comment thread packages/host-service/src/trpc/router/project/project.ts Outdated
Comment thread packages/host-service/src/trpc/router/project/project.ts Outdated
- Reuse existing parseGitHubRemote helper instead of custom regex,
  adds ssh:// URI support and credential-safe URL storage
- Validate parentDir is a directory in cloneRepo, not just exists
- Wrap simpleGit().clone() in try/catch for actionable error messages
- Return remotes from importExistingRepo to avoid double git remote -v
- Use path.resolve for absolute clone paths
- Fix design doc: git rev-parse instead of .git folder check
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/host-service/src/trpc/router/project/project.ts (1)

238-243: Consider cleanup on post-clone verification failure.

If the cloned repository doesn't match the expected GitHub remote (which would indicate a bug or misconfiguration), the cloned directory at targetPath remains on disk. This is a rare edge case, but could leave orphaned directories.

💡 Optional: Clean up on failure
 	if (!matchingRemote) {
+		// Clean up the mismatched clone
+		try {
+			rmSync(targetPath, { recursive: true, force: true });
+		} catch {
+			// Best-effort cleanup
+		}
 		throw new TRPCError({
 			code: "INTERNAL_SERVER_ERROR",
 			message: "Cloned repo does not match expected GitHub remote",
 		});
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/host-service/src/trpc/router/project/project.ts` around lines 238 -
243, When the post-clone verification fails (the existing check using
matchingRemote) ensure the cloned directory at targetPath is cleaned up before
throwing the TRPCError: call the appropriate async remove/rm method (e.g.,
fs.promises.rm or a project-level util) to delete targetPath (recursively) and
handle/log any removal errors, then throw the TRPCError as before; update the
block around matchingRemote to perform cleanup first and only throw after
attempted removal to avoid leaving orphaned clone directories.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/host-service/src/trpc/router/project/project.ts`:
- Around line 238-243: When the post-clone verification fails (the existing
check using matchingRemote) ensure the cloned directory at targetPath is cleaned
up before throwing the TRPCError: call the appropriate async remove/rm method
(e.g., fs.promises.rm or a project-level util) to delete targetPath
(recursively) and handle/log any removal errors, then throw the TRPCError as
before; update the block around matchingRemote to perform cleanup first and only
throw after attempted removal to avoid leaving orphaned clone directories.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f21e442b-084e-43ee-b34d-9de235101173

📥 Commits

Reviewing files that changed from the base of the PR and between 3cc23af and fa04f7a.

📒 Files selected for processing (3)
  • docs/design/v2-host-project-paths.md
  • packages/host-service/src/trpc/router/project/project.ts
  • packages/host-service/src/trpc/router/project/utils/git-remote.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/host-service/src/trpc/router/project/utils/git-remote.ts

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/host-service/src/trpc/router/project/project.ts">

<violation number="1" location="packages/host-service/src/trpc/router/project/project.ts:238">
P2: When clone validation fails, the newly cloned directory is left behind, causing retries to fail with "Directory already exists".</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread packages/host-service/src/trpc/router/project/project.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/host-service/src/trpc/router/project/project.ts`:
- Around line 255-261: The code throws a TRPCError when
remotes.get(matchingRemote) returns undefined but does not remove the previously
created targetPath directory; update the error path to mirror the cleanup at
line 248 by deleting the targetPath before throwing. Locate the block around
remotes.get(matchingRemote) and the variables matchingRemote, parsed, targetPath
and ensure you call the same cleanup routine (or fs.rm/fs.rmdir used elsewhere)
to remove targetPath (and handle any errors silently) immediately prior to
throwing the TRPCError so no orphaned directories remain if
findMatchingRemote/parsed logic fails.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 87e68cef-0a09-4b40-8387-6b405d109a99

📥 Commits

Reviewing files that changed from the base of the PR and between fa04f7a and 9eb7dc7.

📒 Files selected for processing (1)
  • packages/host-service/src/trpc/router/project/project.ts

Comment thread packages/host-service/src/trpc/router/project/project.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/host-service/src/trpc/router/project/project.ts (1)

26-26: Consider adding UUID validation for projectId.

The cloud API (ctx.api.v2Project.get.query) expects a UUID format for the project ID (per context snippet 4: id: z.string().uuid()). Adding .uuid() here would provide earlier, clearer validation errors.

-			projectId: z.string(),
+			projectId: z.string().uuid(),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/host-service/src/trpc/router/project/project.ts` at line 26, The
projectId schema currently uses z.string() but the downstream API expects a
UUID; update the validation where projectId is defined (the Zod input schema
that contains projectId) to use z.string().uuid() so invalid IDs are rejected
earlier and match ctx.api.v2Project.get.query's id: z.string().uuid()
expectation; ensure any related types or usages (e.g., the router/method that
consumes this schema) still compile after the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/host-service/src/trpc/router/project/project.ts`:
- Line 26: The projectId schema currently uses z.string() but the downstream API
expects a UUID; update the validation where projectId is defined (the Zod input
schema that contains projectId) to use z.string().uuid() so invalid IDs are
rejected earlier and match ctx.api.v2Project.get.query's id: z.string().uuid()
expectation; ensure any related types or usages (e.g., the router/method that
consumes this schema) still compile after the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a25f9eca-c0e2-4998-b7a9-b71e48c118c8

📥 Commits

Reviewing files that changed from the base of the PR and between 9eb7dc7 and c2b92ba.

📒 Files selected for processing (1)
  • packages/host-service/src/trpc/router/project/project.ts

@Kitenite Kitenite merged commit bf07410 into main Apr 11, 2026
15 checks passed
@Kitenite Kitenite deleted the host-project-paths branch April 11, 2026 00:06
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 11, 2026
…ment (superset-sh#3345)

* docs: add design doc for v2 host project paths

Outlines the approach for allowing users to import existing local repos
or clone to a chosen location instead of auto-cloning to a fixed path.
Covers local-only storage decision, throw-on-create pattern, and phased
implementation plan.

* feat(host-service): add project.setup endpoint for importing/cloning repos

Adds a `project.setup` mutation that lets users either import an
existing local repo or clone to a chosen directory. Validates git
remotes against the cloud project's GitHub repo (handles SSH + HTTPS).
Upserts the local projects table so re-running handles re-pointing.

* fix(host-service): address PR review feedback on project.setup

- Reuse existing parseGitHubRemote helper instead of custom regex,
  adds ssh:// URI support and credential-safe URL storage
- Validate parentDir is a directory in cloneRepo, not just exists
- Wrap simpleGit().clone() in try/catch for actionable error messages
- Return remotes from importExistingRepo to avoid double git remote -v
- Use path.resolve for absolute clone paths
- Fix design doc: git rev-parse instead of .git folder check

* fix(host-service): replace non-null assertions with explicit guards

* fix(host-service): clean up cloned directory on post-clone validation failure

* fix(host-service): add cleanup on all cloneRepo error paths
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant