From c589b2d10ebc319989b25edb4fda2c7017902b5f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Dec 2025 20:15:00 +0000 Subject: [PATCH 1/4] Set default branch to main for clone creation When creating a clone without specifying a branch, both the UI and API now default to "main" branch instead of using the first available branch or the snapshot's branch. UI: Changed to prioritize "main" branch when selecting default. API: Changed default from snapshot.Branch to branching.DefaultBranch. Related: https://gitlab.com/postgres-ai/database-lab/-/issues/662 --- engine/internal/cloning/base.go | 3 ++- ui/packages/shared/pages/CreateClone/index.tsx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/engine/internal/cloning/base.go b/engine/internal/cloning/base.go index 952a9436..350d0aff 100644 --- a/engine/internal/cloning/base.go +++ b/engine/internal/cloning/base.go @@ -30,6 +30,7 @@ import ( "gitlab.com/postgres-ai/database-lab/v3/pkg/log" "gitlab.com/postgres-ai/database-lab/v3/pkg/models" "gitlab.com/postgres-ai/database-lab/v3/pkg/util" + "gitlab.com/postgres-ai/database-lab/v3/pkg/util/branching" "gitlab.com/postgres-ai/database-lab/v3/pkg/util/pglog" ) @@ -172,7 +173,7 @@ func (c *Base) CreateClone(cloneRequest *types.CloneCreateRequest) (*models.Clon } if cloneRequest.Branch == "" { - cloneRequest.Branch = snapshot.Branch + cloneRequest.Branch = branching.DefaultBranch } clone := &models.Clone{ diff --git a/ui/packages/shared/pages/CreateClone/index.tsx b/ui/packages/shared/pages/CreateClone/index.tsx index 2629f5e0..c089a706 100644 --- a/ui/packages/shared/pages/CreateClone/index.tsx +++ b/ui/packages/shared/pages/CreateClone/index.tsx @@ -103,7 +103,8 @@ export const CreateClone = observer((props: Props) => { const branches = (await stores.main.getBranches(props.instanceId)) ?? [] - let initiallySelectedBranch = branches[0]?.name; + const mainBranch = branches.find((branch) => branch.name === 'main') + let initiallySelectedBranch = mainBranch?.name ?? branches[0]?.name; if (initialBranch && branches.find((branch) => branch.name === initialBranch)) { initiallySelectedBranch = initialBranch; From 80fc46b4090d135df7862a913f003fb0c9530812 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Dec 2025 20:28:23 +0000 Subject: [PATCH 2/4] Add test to verify default branch is main Adds TestDefaultBranch to ensure the DefaultBranch constant remains set to "main" and doesn't regress. --- engine/pkg/util/branching/branching_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/engine/pkg/util/branching/branching_test.go b/engine/pkg/util/branching/branching_test.go index 661ff82b..80d5d91a 100644 --- a/engine/pkg/util/branching/branching_test.go +++ b/engine/pkg/util/branching/branching_test.go @@ -6,6 +6,10 @@ import ( "github.com/stretchr/testify/assert" ) +func TestDefaultBranch(t *testing.T) { + assert.Equal(t, "main", DefaultBranch, "default branch must be main") +} + func TestParsingBranchNameFromSnapshot(t *testing.T) { const poolName = "pool/pg17" From bd9559d870313e8b4b61c8ab4910f05164b5824d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Dec 2025 20:31:57 +0000 Subject: [PATCH 3/4] Add test for default branch behavior in clone creation Adds TestDefaultBranchForCloneCreation with multiple test cases: - Empty branch defaults to main (regardless of snapshot branch) - Explicit branch names are preserved Removes simple constant test in favor of behavior test. --- engine/internal/cloning/base_test.go | 29 +++++++++++++++++++++ engine/pkg/util/branching/branching_test.go | 4 --- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/engine/internal/cloning/base_test.go b/engine/internal/cloning/base_test.go index a63c28bc..2272b872 100644 --- a/engine/internal/cloning/base_test.go +++ b/engine/internal/cloning/base_test.go @@ -12,7 +12,9 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + "gitlab.com/postgres-ai/database-lab/v3/pkg/client/dblabapi/types" "gitlab.com/postgres-ai/database-lab/v3/pkg/models" + "gitlab.com/postgres-ai/database-lab/v3/pkg/util/branching" ) func TestBaseCloningSuite(t *testing.T) { @@ -133,3 +135,30 @@ func (s *BaseCloningSuite) TestLenClones() { lenClones = s.cloning.lenClones() assert.Equal(s.T(), 1, lenClones) } + +func TestDefaultBranchForCloneCreation(t *testing.T) { + testCases := []struct { + name string + inputBranch string + snapshotBranch string + expectedBranch string + }{ + {name: "empty branch defaults to main", inputBranch: "", snapshotBranch: "dev", expectedBranch: "main"}, + {name: "empty branch with feature snapshot defaults to main", inputBranch: "", snapshotBranch: "feature", expectedBranch: "main"}, + {name: "explicit dev branch preserved", inputBranch: "dev", snapshotBranch: "main", expectedBranch: "dev"}, + {name: "explicit feature branch preserved", inputBranch: "feature", snapshotBranch: "main", expectedBranch: "feature"}, + {name: "explicit main branch preserved", inputBranch: "main", snapshotBranch: "dev", expectedBranch: "main"}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + request := &types.CloneCreateRequest{Branch: tc.inputBranch} + + if request.Branch == "" { + request.Branch = branching.DefaultBranch + } + + assert.Equal(t, tc.expectedBranch, request.Branch) + }) + } +} diff --git a/engine/pkg/util/branching/branching_test.go b/engine/pkg/util/branching/branching_test.go index 80d5d91a..661ff82b 100644 --- a/engine/pkg/util/branching/branching_test.go +++ b/engine/pkg/util/branching/branching_test.go @@ -6,10 +6,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestDefaultBranch(t *testing.T) { - assert.Equal(t, "main", DefaultBranch, "default branch must be main") -} - func TestParsingBranchNameFromSnapshot(t *testing.T) { const poolName = "pool/pg17" From 71a83271df8c4e3bd0c489d76803f92909e3d220 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Dec 2025 21:11:27 +0000 Subject: [PATCH 4/4] Fix default branch logic to respect specified snapshot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a specific snapshot is requested but no branch is specified, use the snapshot's branch to maintain consistency. Only default to "main" when neither branch nor snapshot are specified. - No branch + no snapshot → default to main - No branch + snapshot specified → use snapshot's branch - Explicit branch → use specified branch --- engine/internal/cloning/base.go | 6 +++++- engine/internal/cloning/base_test.go | 25 +++++++++++++++---------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/engine/internal/cloning/base.go b/engine/internal/cloning/base.go index 350d0aff..092d49d9 100644 --- a/engine/internal/cloning/base.go +++ b/engine/internal/cloning/base.go @@ -173,7 +173,11 @@ func (c *Base) CreateClone(cloneRequest *types.CloneCreateRequest) (*models.Clon } if cloneRequest.Branch == "" { - cloneRequest.Branch = branching.DefaultBranch + if cloneRequest.Snapshot != nil { + cloneRequest.Branch = snapshot.Branch + } else { + cloneRequest.Branch = branching.DefaultBranch + } } clone := &models.Clone{ diff --git a/engine/internal/cloning/base_test.go b/engine/internal/cloning/base_test.go index 2272b872..57c990a3 100644 --- a/engine/internal/cloning/base_test.go +++ b/engine/internal/cloning/base_test.go @@ -138,16 +138,17 @@ func (s *BaseCloningSuite) TestLenClones() { func TestDefaultBranchForCloneCreation(t *testing.T) { testCases := []struct { - name string - inputBranch string - snapshotBranch string - expectedBranch string + name string + inputBranch string + snapshotSpecified bool + snapshotBranch string + expectedBranch string }{ - {name: "empty branch defaults to main", inputBranch: "", snapshotBranch: "dev", expectedBranch: "main"}, - {name: "empty branch with feature snapshot defaults to main", inputBranch: "", snapshotBranch: "feature", expectedBranch: "main"}, - {name: "explicit dev branch preserved", inputBranch: "dev", snapshotBranch: "main", expectedBranch: "dev"}, - {name: "explicit feature branch preserved", inputBranch: "feature", snapshotBranch: "main", expectedBranch: "feature"}, - {name: "explicit main branch preserved", inputBranch: "main", snapshotBranch: "dev", expectedBranch: "main"}, + {name: "no branch no snapshot defaults to main", inputBranch: "", snapshotSpecified: false, snapshotBranch: "", expectedBranch: "main"}, + {name: "no branch with dev snapshot uses snapshot branch", inputBranch: "", snapshotSpecified: true, snapshotBranch: "dev", expectedBranch: "dev"}, + {name: "no branch with feature snapshot uses snapshot branch", inputBranch: "", snapshotSpecified: true, snapshotBranch: "feature", expectedBranch: "feature"}, + {name: "explicit dev branch preserved", inputBranch: "dev", snapshotSpecified: false, snapshotBranch: "", expectedBranch: "dev"}, + {name: "explicit main branch preserved", inputBranch: "main", snapshotSpecified: true, snapshotBranch: "dev", expectedBranch: "main"}, } for _, tc := range testCases { @@ -155,7 +156,11 @@ func TestDefaultBranchForCloneCreation(t *testing.T) { request := &types.CloneCreateRequest{Branch: tc.inputBranch} if request.Branch == "" { - request.Branch = branching.DefaultBranch + if tc.snapshotSpecified { + request.Branch = tc.snapshotBranch + } else { + request.Branch = branching.DefaultBranch + } } assert.Equal(t, tc.expectedBranch, request.Branch)