Skip to content

Conversation

@LSRCT
Copy link
Contributor

@LSRCT LSRCT commented Dec 16, 2025

Summary

Refactors the branch fetching architecture to decouple branches from projects, enabling future task attempts without projects attached.

Key Changes

Backend:

  • Removed dead /api/projects/{id}/branches endpoint and related types (ProjectBranchesResponse, RepositoryBranches)
  • Branches are now fetched exclusively via /api/repos/{repoId}/branches

Frontend Hooks:

  • Created useRepoBranches(repoId) - single repo branch fetching with proper caching
  • Created useProjectRepos(projectId) - fetches repos for a project (setup phase only)
  • Consolidated useBranches into useRepoBranchSelection - eliminated intermediate hook
  • Updated git operation hooks (useRebase, useMerge, useChangeTargetBranch) to use repoBranchKeys for cache invalidation
  • Removed projectId from useGitOperations - now uses repoId only

Components:

  • GitOperations now fetches branches internally via useRepoBranches(selectedRepoId) instead of receiving as props
  • Removed projectId and branches props from GitActionsDialog and DiffsPanelContainer
  • Updated TaskFormDialog and CreateAttemptDialog to use useRepoBranchSelection

Architecture

The refactored architecture cleanly separates:

  1. Creation Phase (project-aware): useProjectRepos(projectId)useRepoBranchSelection({repos}) → create attempt
  2. Execution Phase (fully decoupled): useAttemptRepo(attemptId)useRepoBranches(repoId) → git operations

Query keys are now repo-scoped (['repoBranches', repoId]) enabling proper cache sharing across components.

Files Changed

  • 24 files modified
  • ~170 lines removed, ~136 lines added (net reduction)
  • Deleted: useBranches.ts, backend get_project_branches handler

  • tested

This PR was written using Vibe Kanban

LSRCT added 12 commits December 16, 2025 12:23
## Summary

Successfully refactored the project branches API to fetch branches using repo IDs instead of project IDs.

### Files Created
- `frontend/src/hooks/useRepoBranches.ts` - New hook that fetches branches for a single repository using `repoApi.getBranches(repoId)`

### Files Modified

1. **`frontend/src/hooks/index.ts`** - Added export for `useRepoBranches`

2. **`frontend/src/components/dialogs/tasks/GitActionsDialog.tsx`**
   - Removed `useState` for `repoBranches` and `loadingBranches`
   - Removed `useEffect` that called `projectsApi.getBranches(effectiveProjectId)`
   - Removed `useMemo` that filtered branches by `selectedRepoId`
   - Now uses `useRepoBranches(selectedRepoId)` to fetch branches directly for the selected repo from the task attempt

3. **`frontend/src/components/dialogs/tasks/CreatePRDialog.tsx`**
   - Removed `projectId` from props interface and component destructuring
   - Removed `useState` for `branches` and `branchesLoading`
   - Removed branch-fetching logic from useEffect
   - Now uses `useRepoBranches(repoId)` to fetch branches directly for the specified repo
   - Split useEffect into two: one for form initialization, one for setting default base branch

4. **`frontend/src/components/tasks/Toolbar/GitOperations.tsx`**
   - Removed `projectId` from `CreatePRDialog.show()` call

### Benefits
- More efficient - fetches only branches for the specific repo needed instead of all project repos
- Better caching - React Query caches branches per repo for efficient reuse
- Cleaner code - removed manual filtering logic from components
- Type safety - hooks return `GitBranch[]` directly instead of `RepositoryBranches[]`
## Summary

Successfully decoupled the branches API from project IDs.

### Changes Made

**1. `frontend/src/hooks/useBranches.ts`** - Refactored to accept `repos: Array<{ id: string; name: string }>` instead of `projectId`
- Now uses `useQueries` to fetch branches for multiple repos in parallel
- Reuses the same query keys as `useRepoBranches` for cache consistency

**2. `frontend/src/hooks/useRepoBranchSelection.ts`** - Refactored to accept `repos: Repo[]` instead of `projectId`
- Removed internal fetch of project repos (caller now provides them)
- Removed `projectRepos` from return value
- Uses refactored `useBranches(repos)`

**3. `frontend/src/components/dialogs/tasks/CreateAttemptDialog.tsx`**
- Added `useQuery` to fetch project repos separately
- Passes `repos` to `useRepoBranchSelection`

**4. `frontend/src/components/dialogs/tasks/TaskFormDialog.tsx`**
- Already fetched `projectRepos`
- Updated to pass `projectRepos` to refactored `useBranches`

**5. `frontend/src/components/layout/Navbar.tsx`**
- Replaced `useBranches(projectId)` with `useQuery` for `projectsApi.getRepositories`
- Only needed repo count, not branches

**6. `frontend/src/components/projects/ProjectCard.tsx`**
- Replaced `useBranches(project.id)` with `useQuery` for `projectsApi.getRepositories`
- Only needed repo count, not branches

### Benefits
- Branch hooks no longer require a project ID
- Repos can come from any source (project, attempt, or future sources without projects)
- Better separation of concerns
- Enables future task attempts without projects attached
… the loose `Array<{ id: string; name: string }>` type.

This makes it explicit that `useBranches` expects actual `Repo` objects (with `Repo.id` being the repository's UUID), not project-repo junction records.
**Summary of changes:**

1. **Created `useProjectRepos` hook** (`frontend/src/hooks/useProjectRepos.ts`) - A reusable hook that fetches project repositories with proper query key management

2. **Updated 5 files** to use the new hook instead of duplicating the `useQuery` pattern:
   - `CreateAttemptDialog.tsx`
   - `TaskFormDialog.tsx`
   - `Navbar.tsx`
   - `ProjectCard.tsx`
   - `NoServerContent.tsx`

3. **Earlier refactors** (from before the summary):
   - `useBranches.ts` - Now accepts `repos: Repo[]` instead of `projectId`
   - `useRepoBranchSelection.ts` - Now accepts `repos: Repo[]` instead of `projectId`

This enables future task attempts without projects attached, as branch fetching is now decoupled from project IDs.
…iffs panel - showing available branches for git operations when viewing an attempt's diffs.
**Summary of changes:**

`GitOperations` now fetches its own branches using `useRepoBranches(selectedRepoId)` instead of receiving them as a prop. This:

1. Removes prop drilling through `ProjectTasks` → `DiffsPanelContainer` → `DiffsPanel` → `GitOperations`
2. Removes the need for `ProjectTasks` to fetch all project repos just to get branches for the selected repo
3. Makes `GitOperations` self-contained - it already has `selectedRepoId` from `useAttemptRepo`, so it can fetch its own branches
4. Simplifies `GitActionsDialog` which no longer needs to fetch branches either
**Removed `projectId` from GitOperations flow:**

1. **`useRebase.ts`** - Changed param from `projectId` to `repoId`, updated invalidation to use `repoBranchKeys.byRepo(repoId)`

2. **`useChangeTargetBranch.ts`** - Changed param from `projectId` to `repoId`, updated invalidation to use `repoBranchKeys.byRepo(repoId)`

3. **`useMerge.ts`** - Updated invalidation to use `repoBranchKeys.all` instead of `['projectBranches']`

4. **`useGitOperations.ts`** - Changed param from `projectId` to `repoId`

5. **`GitOperations.tsx`** - Removed `projectId` prop, now passes `selectedRepoId` to `useGitOperations`

6. **`GitActionsDialog.tsx`** - Removed `projectId` from props and internal logic

7. **`DiffsPanelContainer`** (in ProjectTasks.tsx) - Removed `projectId` prop

8. **Callers of `GitActionsDialog.show`** - Removed `projectId` from `NextActionCard.tsx` and `actions-dropdown.tsx`
**Removed dead project branches code:**

1. **Backend** (`crates/server/src/routes/projects.rs`):
   - Removed `get_project_branches` handler and route
   - Removed `RepositoryBranches` and `ProjectBranchesResponse` structs
   - Fixed unused `Serialize` import warning

2. **Type Generation** (`crates/server/src/bin/generate_types.rs`):
   - Removed exports for `ProjectBranchesResponse` and `RepositoryBranches`

3. **Frontend Hooks** (`frontend/src/hooks/useBranches.ts`):
   - Defined local `RepositoryBranches` type instead of importing from shared/types

4. **Frontend API** (`frontend/src/lib/api.ts`):
   - Removed `projectsApi.getBranches` method
   - Removed `RepositoryBranches` and `ProjectBranchesResponse` imports

Both TypeScript and Rust compilation pass without errors.
…es` to return `Map<string, GitBranch[]>`. Changes:

1. **`useBranches.ts`** - Returns `Map<string, GitBranch[]>` instead of `RepositoryBranches[]`
2. **`useRepoBranchSelection.ts`** - Uses `branchMap.get(repo.id) ?? []` instead of `.find()`
3. **`TaskFormDialog.tsx`** - Uses `branchMap.get(repo.id) ?? []` instead of `.find()`

Type checks pass.
… `useRepoBranchSelection`. Summary:

1. **Deleted** `frontend/src/hooks/useBranches.ts`
2. **Updated** `useRepoBranchSelection.ts` - inlined the `useQueries` logic directly
3. **Updated** `hooks/index.ts` - removed `useBranches` export
4. **Updated** `TaskFormDialog.tsx` - now uses `useRepoBranchSelection` instead of duplicating the config-building logic

Type checks pass.
@vibe-kanban-cloud
Copy link

Vibe Kanban Review Failed

Unfortunately, the code review could not be completed.

Review ID: f538dee7-eb99-438f-b6e4-d2184247e0de

@LSRCT LSRCT changed the title Refactor project branches API (vibe-kanban) Refactor branch fetching to use repo IDs instead of project IDs (Vibe Kanban) Dec 16, 2025
@vibe-kanban-cloud
Copy link

Vibe Kanban Review Failed

Unfortunately, the code review could not be completed.

Review ID: f538dee7-eb99-438f-b6e4-d2184247e0de

1 similar comment
@vibe-kanban-cloud
Copy link

Vibe Kanban Review Failed

Unfortunately, the code review could not be completed.

Review ID: f538dee7-eb99-438f-b6e4-d2184247e0de

@vibe-kanban-cloud
Copy link

Vibe Kanban Review Failed

Unfortunately, the code review could not be completed.

Review ID: f538dee7-eb99-438f-b6e4-d2184247e0de

@LSRCT LSRCT requested a review from ggordonhall December 16, 2025 12:38
@LSRCT LSRCT merged commit f989b47 into main Dec 16, 2025
2 checks passed
@LSRCT LSRCT deleted the vk/6b5b-refactor-project branch December 16, 2025 14:21
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.

2 participants