Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds automatic discovery of git worktrees during project creation: lists worktrees from the repository, filters those under the superset worktrees directory and that exist on disk, then creates corresponding worktree and workspace DB records and adjusts project tabOrder when applicable. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client
participant ProjectsRouter as Projects Router
participant GitUtil as listWorktrees
participant Filesystem as FS (existsSync)
participant Database
Client->>ProjectsRouter: request openNew(projectData)
ProjectsRouter->>GitUtil: listWorktrees(mainRepoPath)
GitUtil-->>ProjectsRouter: [ {path, branch}, ... ]
ProjectsRouter->>Filesystem: check each worktree path exists
Filesystem-->>ProjectsRouter: exists / not exists
alt worktrees under superset dir and exist
ProjectsRouter->>Database: create worktree record(s)
Database-->>ProjectsRouter: created worktree id(s)
ProjectsRouter->>Database: create workspace(s) for worktree id(s)
Database-->>ProjectsRouter: created workspace id(s)
ProjectsRouter->>Database: possibly update project.tabOrder
Database-->>ProjectsRouter: project updated
else no valid worktrees
ProjectsRouter-->>Database: no additional DB changes
end
ProjectsRouter-->>Client: return created project (with worktrees/workspaces)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/desktop/src/lib/trpc/routers/projects/projects.ts (1)
137-150: Consider moving project activation outside the loop.This block runs on every iteration but the condition ensures it only takes effect once. Moving it after the loop would avoid repeated find/filter operations.
data.workspaces.push(workspace); - - // Mark project as active since we found workspaces - // biome-ignore lint/style/noNonNullAssertion: project is assigned above - const p = data.projects.find((proj) => proj.id === project!.id); - if (p && p.tabOrder === null) { - const activeProjects = data.projects.filter( - (proj) => proj.tabOrder !== null, - ); - const maxProjectTabOrder = - activeProjects.length > 0 - ? // biome-ignore lint/style/noNonNullAssertion: filter guarantees tabOrder is not null - Math.max(...activeProjects.map((proj) => proj.tabOrder!)) - : -1; - p.tabOrder = maxProjectTabOrder + 1; - } } + + // Mark project as active since we found workspaces + // biome-ignore lint/style/noNonNullAssertion: project is assigned above + const p = data.projects.find((proj) => proj.id === project!.id); + if (p && p.tabOrder === null) { + const activeProjects = data.projects.filter( + (proj) => proj.tabOrder !== null, + ); + const maxProjectTabOrder = + activeProjects.length > 0 + ? // biome-ignore lint/style/noNonNullAssertion: filter guarantees tabOrder is not null + Math.max(...activeProjects.map((proj) => proj.tabOrder!)) + : -1; + p.tabOrder = maxProjectTabOrder + 1; + } });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/desktop/src/lib/trpc/routers/projects/projects.ts(2 hunks)apps/desktop/src/lib/trpc/routers/workspaces/utils/git.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
apps/desktop/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
For Electron interprocess communication, ALWAYS use tRPC as defined in
src/lib/trpc
Files:
apps/desktop/src/lib/trpc/routers/workspaces/utils/git.tsapps/desktop/src/lib/trpc/routers/projects/projects.ts
apps/desktop/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
apps/desktop/**/*.{ts,tsx}: Please use alias as defined intsconfig.jsonwhen possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary
Files:
apps/desktop/src/lib/trpc/routers/workspaces/utils/git.tsapps/desktop/src/lib/trpc/routers/projects/projects.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Avoid usinganytype - use explicit types instead for type safety
Use camelCase for variable and function names following existing codebase patterns
Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications
Follow existing patterns and match the codebase style when writing new code
Files:
apps/desktop/src/lib/trpc/routers/workspaces/utils/git.tsapps/desktop/src/lib/trpc/routers/projects/projects.ts
apps/desktop/src/lib/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Never import Node.js modules in shared code like
src/lib/electron-router-dom.ts- this code runs in both main and renderer processes
Files:
apps/desktop/src/lib/trpc/routers/workspaces/utils/git.tsapps/desktop/src/lib/trpc/routers/projects/projects.ts
🧠 Learnings (3)
📚 Learning: 2025-11-28T01:03:47.951Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.951Z
Learning: Applies to apps/desktop/src/lib/**/*.ts : Never import Node.js modules in shared code like `src/lib/electron-router-dom.ts` - this code runs in both main and renderer processes
Applied to files:
apps/desktop/src/lib/trpc/routers/projects/projects.ts
📚 Learning: 2025-11-28T01:03:47.951Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.951Z
Learning: Applies to apps/desktop/src/main/**/*.{ts,tsx} : Node.js modules (fs, path, os, net, etc.) can be used in main process code only
Applied to files:
apps/desktop/src/lib/trpc/routers/projects/projects.ts
📚 Learning: 2025-11-28T01:03:47.951Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.951Z
Learning: Applies to apps/desktop/src/renderer/**/*.{ts,tsx} : Never import Node.js modules (fs, path, os, net, etc.) in renderer process code - browser environment only
Applied to files:
apps/desktop/src/lib/trpc/routers/projects/projects.ts
🧬 Code graph analysis (1)
apps/desktop/src/lib/trpc/routers/projects/projects.ts (3)
apps/desktop/src/shared/constants.ts (2)
SUPERSET_DIR_NAME(21-23)WORKTREES_DIR_NAME(24-24)apps/desktop/src/lib/trpc/routers/workspaces/utils/git.ts (1)
listWorktrees(158-193)apps/desktop/src/main/lib/db/index.ts (1)
db(18-25)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Build
🔇 Additional comments (4)
apps/desktop/src/lib/trpc/routers/workspaces/utils/git.ts (2)
148-151: LGTM!The interface is well-defined with clear, appropriately-typed fields for worktree metadata.
158-193: Clean implementation for parsing porcelain worktree output.The parsing logic correctly handles the porcelain format's structure. Note that worktrees in detached HEAD state will be excluded since they lack a branch line—this appears intentional given downstream usage requires branch names.
apps/desktop/src/lib/trpc/routers/projects/projects.ts (2)
1-14: LGTM!Imports are well-organized. Node.js modules are acceptable here since tRPC routers execute in the Electron main process.
71-135: Good integration of worktree discovery into project creation.The logic correctly filters to superset-managed worktrees, avoids duplicates in the database, and properly initializes workspace records with incremental tab ordering.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/desktop/src/lib/trpc/routers/projects/projects.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
apps/desktop/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
For Electron interprocess communication, ALWAYS use tRPC as defined in
src/lib/trpc
Files:
apps/desktop/src/lib/trpc/routers/projects/projects.ts
apps/desktop/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
apps/desktop/**/*.{ts,tsx}: Please use alias as defined intsconfig.jsonwhen possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary
Files:
apps/desktop/src/lib/trpc/routers/projects/projects.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Avoid usinganytype - use explicit types instead for type safety
Use camelCase for variable and function names following existing codebase patterns
Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications
Follow existing patterns and match the codebase style when writing new code
Files:
apps/desktop/src/lib/trpc/routers/projects/projects.ts
apps/desktop/src/lib/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Never import Node.js modules in shared code like
src/lib/electron-router-dom.ts- this code runs in both main and renderer processes
Files:
apps/desktop/src/lib/trpc/routers/projects/projects.ts
🧠 Learnings (4)
📚 Learning: 2025-11-28T01:03:47.963Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.963Z
Learning: Applies to **/*.{ts,tsx} : Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications
Applied to files:
apps/desktop/src/lib/trpc/routers/projects/projects.ts
📚 Learning: 2025-11-28T01:03:47.963Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.963Z
Learning: Applies to apps/desktop/src/lib/**/*.ts : Never import Node.js modules in shared code like `src/lib/electron-router-dom.ts` - this code runs in both main and renderer processes
Applied to files:
apps/desktop/src/lib/trpc/routers/projects/projects.ts
📚 Learning: 2025-11-28T01:03:47.963Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.963Z
Learning: Applies to apps/desktop/src/main/**/*.{ts,tsx} : Node.js modules (fs, path, os, net, etc.) can be used in main process code only
Applied to files:
apps/desktop/src/lib/trpc/routers/projects/projects.ts
📚 Learning: 2025-11-28T01:03:47.963Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.963Z
Learning: Applies to apps/desktop/src/renderer/**/*.{ts,tsx} : Never import Node.js modules (fs, path, os, net, etc.) in renderer process code - browser environment only
Applied to files:
apps/desktop/src/lib/trpc/routers/projects/projects.ts
🧬 Code graph analysis (1)
apps/desktop/src/lib/trpc/routers/projects/projects.ts (2)
apps/desktop/src/shared/constants.ts (2)
SUPERSET_DIR_NAME(21-23)WORKTREES_DIR_NAME(24-24)apps/desktop/src/lib/trpc/routers/workspaces/utils/git.ts (1)
listWorktrees(158-193)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Build
🔇 Additional comments (3)
apps/desktop/src/lib/trpc/routers/projects/projects.ts (3)
1-13: LGTM!The imports are appropriate for main process code. Node.js modules (
fs,os,path) are correctly used here since tRPC routers run in the Electron main process. Based on learnings, this aligns with the guideline that Node.js modules can be used in main process code only.
71-77: LGTM!The path construction correctly uses
path.joinwith the appropriate constants.
87-153: LGTM!The DB update logic correctly:
- Checks for existing worktrees to avoid duplicates
- Creates both worktree and workspace records with proper relationships
- Calculates sequential
tabOrdervalues for workspaces- Activates the project (sets
tabOrder) only once due to thep.tabOrder === nullguardThe repeated filter operations inside the loop are slightly inefficient but acceptable given the typical small number of worktrees.
| WORKTREES_DIR_NAME, | ||
| ); | ||
|
|
||
| const existingWorktrees = await listWorktrees(mainRepoPath); |
There was a problem hiding this comment.
Wrap listWorktrees in try-catch to prevent import failures from breaking project creation.
At this point the project has already been successfully created. If listWorktrees fails (e.g., git command error, permission issues), the entire mutation throws and the user sees an error even though the project was saved. Worktree import is supplementary functionality and shouldn't cause the overall operation to fail.
- const existingWorktrees = await listWorktrees(mainRepoPath);
+ let existingWorktrees: Awaited<ReturnType<typeof listWorktrees>> = [];
+ try {
+ existingWorktrees = await listWorktrees(mainRepoPath);
+ } catch (error) {
+ console.warn("Failed to list existing worktrees:", error);
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const existingWorktrees = await listWorktrees(mainRepoPath); | |
| let existingWorktrees: Awaited<ReturnType<typeof listWorktrees>> = []; | |
| try { | |
| existingWorktrees = await listWorktrees(mainRepoPath); | |
| } catch (error) { | |
| console.warn("Failed to list existing worktrees:", error); | |
| } |
🤖 Prompt for AI Agents
In apps/desktop/src/lib/trpc/routers/projects/projects.ts around line 79, the
call to listWorktrees can throw and currently will bubble up causing the whole
mutation to fail even after the project was created; wrap the listWorktrees call
in a try-catch, handle errors by logging them (or reporting to a
diagnostic/error-tracking service) and fall back to an empty array or skip
worktree import so the mutation returns success; ensure the catch does not
rethrow and that any subsequent code that expects the worktree list handles the
empty fallback.
| const supersetWorktrees = existingWorktrees.filter( | ||
| (wt) => | ||
| wt.path.startsWith(`${supersetWorktreesDir}/`) && existsSync(wt.path), | ||
| ); |
There was a problem hiding this comment.
Cross-platform path separator mismatch.
path.join produces OS-specific separators (backslash on Windows), but the check uses a hardcoded forward slash. On Windows, supersetWorktreesDir would be something like C:\Users\...\worktrees, so startsWith(${supersetWorktreesDir}/) would never match.
+import { sep } from "node:path";
...
const supersetWorktrees = existingWorktrees.filter(
(wt) =>
- wt.path.startsWith(`${supersetWorktreesDir}/`) && existsSync(wt.path),
+ wt.path.startsWith(`${supersetWorktreesDir}${sep}`) && existsSync(wt.path),
);Alternatively, normalize both paths before comparison to handle mixed separators from git output.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const supersetWorktrees = existingWorktrees.filter( | |
| (wt) => | |
| wt.path.startsWith(`${supersetWorktreesDir}/`) && existsSync(wt.path), | |
| ); | |
| import { sep } from "node:path"; | |
| const supersetWorktrees = existingWorktrees.filter( | |
| (wt) => | |
| wt.path.startsWith(`${supersetWorktreesDir}${sep}`) && existsSync(wt.path), | |
| ); |
🤖 Prompt for AI Agents
In apps/desktop/src/lib/trpc/routers/projects/projects.ts around lines 82-85,
the startsWith check uses a hardcoded '/' which fails on Windows; normalize both
paths and use the platform separator before comparing. Fix by normalizing or
resolving supersetWorktreesDir and wt.path (e.g., with
path.resolve/path.normalize), ensure supersetWorktreesDir ends with path.sep,
then test startsWith against that normalized directory; alternatively use
path.relative(supersetWorktreesDir, wt.path) and check it does not start with
'..' to determine containment.
Summary by CodeRabbit
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.