diff --git a/backend/internal/service/project/service_test.go b/backend/internal/service/project/service_test.go index 48e66a653..8088c9415 100644 --- a/backend/internal/service/project/service_test.go +++ b/backend/internal/service/project/service_test.go @@ -584,6 +584,16 @@ func configureCommitter(t *testing.T) { } func gitRepoWithCommit(t *testing.T, dir string) string { + t.Helper() + return gitRepoWithCommitWithOrigin(t, dir, "https://example.com/"+filepath.Base(dir)+".git") +} + +func gitRepoWithCommitNoOrigin(t *testing.T, dir string) string { + t.Helper() + return gitRepoWithCommitWithOrigin(t, dir, "") +} + +func gitRepoWithCommitWithOrigin(t *testing.T, dir, origin string) string { t.Helper() if out, err := exec.Command("git", "init", "-b", "main", dir).CombinedOutput(); err != nil { t.Fatalf("git init: %v (%s)", err, out) @@ -597,6 +607,11 @@ func gitRepoWithCommit(t *testing.T, dir string) string { if out, err := exec.Command("git", "-C", dir, "commit", "-m", "initial").CombinedOutput(); err != nil { t.Fatalf("git commit: %v (%s)", err, out) } + if origin != "" { + if out, err := exec.Command("git", "-C", dir, "remote", "add", "origin", origin).CombinedOutput(); err != nil { + t.Fatalf("git remote add: %v (%s)", err, out) + } + } return dir } @@ -664,6 +679,17 @@ func TestManager_AddWorkspaceRejectsUncommittedChild(t *testing.T) { wantCode(t, err, "WORKSPACE_CHILD_UNBORN") } +func TestManager_AddWorkspaceRejectsChildWithoutOrigin(t *testing.T) { + configureCommitter(t) + ctx := context.Background() + m := newManager(t) + parent := t.TempDir() + gitRepoWithCommitNoOrigin(t, filepath.Join(parent, "api")) + + _, err := m.Add(ctx, project.AddInput{Path: parent, ProjectID: ptr("ws"), AsWorkspace: true}) + wantCode(t, err, "WORKSPACE_CHILD_ORIGIN_REQUIRED") +} + // TestManager_AddWorkspaceAdoptsExistingParent verifies that when the parent is // already a git repo, Add commits only .gitignore changes, preserves the prior // commit history, and registers the children. diff --git a/backend/internal/service/project/workspace_registration.go b/backend/internal/service/project/workspace_registration.go index fe072984c..7f5616e9a 100644 --- a/backend/internal/service/project/workspace_registration.go +++ b/backend/internal/service/project/workspace_registration.go @@ -213,6 +213,12 @@ func validateWorkspaceChild(ctx context.Context, child string) error { "suggestedFix": "Check out the repository's default branch (for example `main`) and retry.", }) } + if origin := resolveGitOriginURL(child); origin == "" { + return apierr.Invalid("WORKSPACE_CHILD_ORIGIN_REQUIRED", "Workspace child repositories must have an origin remote configured", map[string]any{ + "path": child, + "suggestedFix": "Run `git remote add origin ` in the child repository, then retry.", + }) + } return nil }