fix: detect workspace root default branch
This commit is contained in:
parent
5ccaf3afd7
commit
c1c1ff7fe2
|
|
@ -174,6 +174,60 @@ func TestOrchestratorManagedPath(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestCreateWorkspaceProjectOrchestratorCreatesRootAndChildWorktrees(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
parentRepo := gitRepoWithInitialCommit(t, filepath.Join(t.TempDir(), "workspace-root"), "main")
|
||||
childRepo := gitRepoWithInitialCommit(t, filepath.Join(t.TempDir(), "api"), "main")
|
||||
ws, err := New(Options{ManagedRoot: root, RepoResolver: StaticRepoResolver{"proj": parentRepo}})
|
||||
if err != nil {
|
||||
t.Fatalf("new: %v", err)
|
||||
}
|
||||
|
||||
info, err := ws.CreateWorkspaceProject(context.Background(), ports.WorkspaceProjectConfig{
|
||||
ProjectID: "proj",
|
||||
SessionID: "proj-1",
|
||||
Kind: domain.KindOrchestrator,
|
||||
SessionPrefix: "proj",
|
||||
Branch: "ao/proj-1",
|
||||
RootRepoPath: parentRepo,
|
||||
BaseBranch: "main",
|
||||
Repos: []ports.WorkspaceProjectRepoConfig{{
|
||||
Name: "api",
|
||||
RelativePath: "api",
|
||||
RepoPath: childRepo,
|
||||
BaseBranch: "main",
|
||||
}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateWorkspaceProject: %v", err)
|
||||
}
|
||||
wantRoot := filepath.Join(ws.managedRoot, "proj", "orchestrator", "proj-orchestrator")
|
||||
wantChild := filepath.Join(wantRoot, "api")
|
||||
wantChildRepo, err := physicalAbs(childRepo)
|
||||
if err != nil {
|
||||
t.Fatalf("child physical path: %v", err)
|
||||
}
|
||||
if info.Root.Path != wantRoot || info.Root.Branch != "ao/proj-1" {
|
||||
t.Fatalf("root = %#v, want path %q branch ao/proj-1", info.Root, wantRoot)
|
||||
}
|
||||
if len(info.Worktrees) != 2 {
|
||||
t.Fatalf("worktrees = %d, want root and api: %#v", len(info.Worktrees), info.Worktrees)
|
||||
}
|
||||
if info.Worktrees[1].Path != wantChild || info.Worktrees[1].RepoPath != wantChildRepo {
|
||||
t.Fatalf("child worktree = %#v, want path %q repo %q", info.Worktrees[1], wantChild, wantChildRepo)
|
||||
}
|
||||
if out, err := exec.Command("git", "-C", parentRepo, "worktree", "list", "--porcelain").CombinedOutput(); err != nil {
|
||||
t.Fatalf("root worktree list: %v (%s)", err, out)
|
||||
} else if !strings.Contains(string(out), wantRoot) {
|
||||
t.Fatalf("root worktree list missing %q:\n%s", wantRoot, out)
|
||||
}
|
||||
if out, err := exec.Command("git", "-C", childRepo, "worktree", "list", "--porcelain").CombinedOutput(); err != nil {
|
||||
t.Fatalf("child worktree list: %v (%s)", err, out)
|
||||
} else if !strings.Contains(string(out), wantChild) {
|
||||
t.Fatalf("child worktree list missing %q:\n%s", wantChild, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateReusesRegisteredWorktreeAtExpectedPath(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
repo := t.TempDir()
|
||||
|
|
@ -532,3 +586,26 @@ func mkdirFile(dir, name string) error {
|
|||
}
|
||||
return os.WriteFile(filepath.Join(dir, name), []byte("data"), 0o644)
|
||||
}
|
||||
|
||||
func gitRepoWithInitialCommit(t *testing.T, dir, branch string) string {
|
||||
t.Helper()
|
||||
if out, err := exec.Command("git", "init", "-b", branch, dir).CombinedOutput(); err != nil {
|
||||
t.Fatalf("git init: %v (%s)", err, out)
|
||||
}
|
||||
if out, err := exec.Command("git", "-C", dir, "config", "user.email", "ao@example.com").CombinedOutput(); err != nil {
|
||||
t.Fatalf("git config email: %v (%s)", err, out)
|
||||
}
|
||||
if out, err := exec.Command("git", "-C", dir, "config", "user.name", "AO Test").CombinedOutput(); err != nil {
|
||||
t.Fatalf("git config name: %v (%s)", err, out)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "README.md"), []byte("hello\n"), 0o644); err != nil {
|
||||
t.Fatalf("write readme: %v", err)
|
||||
}
|
||||
if out, err := exec.Command("git", "-C", dir, "add", "README.md").CombinedOutput(); err != nil {
|
||||
t.Fatalf("git add: %v (%s)", err, out)
|
||||
}
|
||||
if out, err := exec.Command("git", "-C", dir, "commit", "-m", "initial").CombinedOutput(); err != nil {
|
||||
t.Fatalf("git commit: %v (%s)", err, out)
|
||||
}
|
||||
return dir
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,6 +196,11 @@ func (m *Service) Add(ctx context.Context, in AddInput) (Project, error) {
|
|||
if err != nil {
|
||||
return Project{}, err
|
||||
}
|
||||
if row.Config.DefaultBranch == "" {
|
||||
if branch := resolveDefaultBranch(path); branch != "" && branch != domain.DefaultBranchName {
|
||||
row.Config.DefaultBranch = branch
|
||||
}
|
||||
}
|
||||
row.Kind = domain.ProjectKindWorkspace
|
||||
row.RepoOriginURL = resolveGitOriginURL(path)
|
||||
if err := m.store.UpsertWorkspaceProject(ctx, row, repos); err != nil {
|
||||
|
|
|
|||
|
|
@ -634,6 +634,30 @@ func TestManager_AddWorkspaceDetectsChildDefaultBranches(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestManager_AddWorkspaceDetectsParentDefaultBranch(t *testing.T) {
|
||||
configureCommitter(t)
|
||||
ctx := context.Background()
|
||||
m := newManager(t)
|
||||
parent := t.TempDir()
|
||||
gitRepoWithCommitOnBranch(t, parent, "master")
|
||||
gitRepoWithCommit(t, filepath.Join(parent, "api"))
|
||||
|
||||
proj, err := m.Add(ctx, project.AddInput{Path: parent, ProjectID: ptr("ws"), AsWorkspace: true})
|
||||
if err != nil {
|
||||
t.Fatalf("Add workspace: %v", err)
|
||||
}
|
||||
if proj.DefaultBranch != "master" {
|
||||
t.Fatalf("workspace parent default branch = %q, want master", proj.DefaultBranch)
|
||||
}
|
||||
got, err := m.Get(ctx, "ws")
|
||||
if err != nil {
|
||||
t.Fatalf("Get workspace: %v", err)
|
||||
}
|
||||
if got.Project == nil || got.Project.DefaultBranch != "master" {
|
||||
t.Fatalf("stored workspace default branch = %#v, want master", got.Project)
|
||||
}
|
||||
}
|
||||
|
||||
func TestManager_AddWorkspaceRejectsUncommittedChild(t *testing.T) {
|
||||
configureCommitter(t)
|
||||
ctx := context.Background()
|
||||
|
|
|
|||
|
|
@ -679,6 +679,45 @@ func TestSpawn_WorkspaceProjectRecordsRootAndChildWorktrees(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSpawn_WorkspaceProjectOrchestratorUsesOrchestratorPath(t *testing.T) {
|
||||
st := newFakeStore()
|
||||
st.projects["mer"] = domain.ProjectRecord{
|
||||
ID: "mer",
|
||||
Path: "/repo/mer",
|
||||
Kind: domain.ProjectKindWorkspace,
|
||||
Config: testRoleAgents(),
|
||||
}
|
||||
st.workspaceRepo["mer"] = []domain.WorkspaceRepoRecord{{Name: "api", RelativePath: "api", DefaultBranch: "main"}}
|
||||
rt := &fakeRuntime{}
|
||||
ws := &fakeWorkspace{path: "/managed/mer/orchestrator/mer-orchestrator"}
|
||||
m := New(Deps{
|
||||
Runtime: rt, Agents: fakeAgents{}, Workspace: ws, Store: st,
|
||||
Messenger: &fakeMessenger{}, Lifecycle: &fakeLCM{store: st},
|
||||
LookPath: func(string) (string, error) { return "/bin/true", nil },
|
||||
})
|
||||
|
||||
rec, err := m.Spawn(ctx, ports.SpawnConfig{ProjectID: "mer", Kind: domain.KindOrchestrator})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if rec.Kind != domain.KindOrchestrator {
|
||||
t.Fatalf("kind = %q, want orchestrator", rec.Kind)
|
||||
}
|
||||
if rec.Metadata.WorkspacePath != "/managed/mer/orchestrator/mer-orchestrator" {
|
||||
t.Fatalf("workspace path = %q", rec.Metadata.WorkspacePath)
|
||||
}
|
||||
if ws.lastProjectCfg.Kind != domain.KindOrchestrator {
|
||||
t.Fatalf("workspace project kind = %q, want orchestrator", ws.lastProjectCfg.Kind)
|
||||
}
|
||||
if ws.lastProjectCfg.Branch != "ao/mer-1" {
|
||||
t.Fatalf("workspace project branch = %q, want ao/mer-1", ws.lastProjectCfg.Branch)
|
||||
}
|
||||
rows := st.worktrees["mer-1"]
|
||||
if len(rows) != 2 {
|
||||
t.Fatalf("session worktree rows = %d, want root and api: %#v", len(rows), rows)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpawn_WorkspaceProjectRollsBackAllWorktreesOnRuntimeFailure(t *testing.T) {
|
||||
m, st, _, ws := newManager()
|
||||
st.projects["mer"] = domain.ProjectRecord{
|
||||
|
|
|
|||
Loading…
Reference in New Issue