From 44521cc50e304b61c44b9a269a8239fd0fef49cd Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Thu, 26 Mar 2026 06:36:32 +0000 Subject: fix: story branch push to bare repo; drain at 3 consecutive failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit createStoryBranch was pushing to 'origin' which doesn't exist — branches never landed in the bare repo so agents couldn't clone them. Now uses the project's RemoteURL (bare repo path) directly for fetch and push. Raise drain threshold from 2 to 3 consecutive failures to reduce false positives from transient errors. Co-Authored-By: Claude Sonnet 4.6 --- internal/api/stories.go | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'internal/api/stories.go') diff --git a/internal/api/stories.go b/internal/api/stories.go index 3d9d25a..629ea7a 100644 --- a/internal/api/stories.go +++ b/internal/api/stories.go @@ -14,25 +14,21 @@ import ( "github.com/thepeterstone/claudomator/internal/task" ) -// createStoryBranch creates a new git branch in localPath from origin/main -// and pushes it to origin. Idempotent: treats "already exists" as success. -func createStoryBranch(localPath, branchName string) error { - // Fetch latest from origin so origin/main is up to date. - if out, err := exec.Command("git", "-C", localPath, "fetch", "origin").CombinedOutput(); err != nil { +// createStoryBranch creates a new git branch in localPath from the latest main +// and pushes it to remoteURL (the bare repo). Idempotent: treats "already exists" as success. +func createStoryBranch(localPath, branchName, remoteURL string) error { + // Fetch latest from the bare repo so we have an up-to-date base. + if out, err := exec.Command("git", "-C", localPath, "fetch", remoteURL, "main").CombinedOutput(); err != nil { return fmt.Errorf("git fetch: %w (output: %s)", err, string(out)) } - base := "origin/main" + base := "FETCH_HEAD" out, err := exec.Command("git", "-C", localPath, "checkout", "-b", branchName, base).CombinedOutput() if err != nil { if !strings.Contains(string(out), "already exists") { return fmt.Errorf("git checkout -b: %w (output: %s)", err, string(out)) } - // Branch exists; switch to it — idempotent. - if out2, err2 := exec.Command("git", "-C", localPath, "checkout", branchName).CombinedOutput(); err2 != nil { - return fmt.Errorf("git checkout: %w (output: %s)", err2, string(out2)) - } } - if out, err := exec.Command("git", "-C", localPath, "push", "origin", branchName).CombinedOutput(); err != nil { + if out, err := exec.Command("git", "-C", localPath, "push", remoteURL, branchName).CombinedOutput(); err != nil { return fmt.Errorf("git push: %w (output: %s)", err, string(out)) } return nil @@ -313,8 +309,8 @@ func (s *Server) handleApproveStory(w http.ResponseWriter, r *http.Request) { // Create the story branch (non-fatal if it fails). if input.BranchName != "" && input.ProjectID != "" { - if proj, err := s.store.GetProject(input.ProjectID); err == nil && proj.LocalPath != "" { - if err := createStoryBranch(proj.LocalPath, input.BranchName); err != nil { + if proj, err := s.store.GetProject(input.ProjectID); err == nil && proj.LocalPath != "" && proj.RemoteURL != "" { + if err := createStoryBranch(proj.LocalPath, input.BranchName, proj.RemoteURL); err != nil { s.logger.Warn("story approve: failed to create branch", "error", err, "branch", input.BranchName) } } -- cgit v1.2.3