feat(refinery): implement handleSuccess for merge queue
Implement success handling for the merge queue Engineer: - Add handleSuccess method that handles successful merge completion - Update MR body with merge_commit SHA and close_reason - Close MR with 'merged' reason - Close source issue with reference to MR ID - Delete source branch if delete_merged_branches is configured - Add DeleteRemoteBranch method to git package - Add git client to Engineer struct - Add tests for new functionality Closes gt-3x1.5 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -347,7 +347,7 @@ func (g *Git) RemoteBranchExists(remote, branch string) (bool, error) {
|
||||
return out != "", nil
|
||||
}
|
||||
|
||||
// DeleteBranch deletes a branch.
|
||||
// DeleteBranch deletes a local branch.
|
||||
func (g *Git) DeleteBranch(name string, force bool) error {
|
||||
flag := "-d"
|
||||
if force {
|
||||
@@ -357,6 +357,12 @@ func (g *Git) DeleteBranch(name string, force bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteRemoteBranch deletes a branch from the remote.
|
||||
func (g *Git) DeleteRemoteBranch(remote, branch string) error {
|
||||
_, err := g.run("push", remote, "--delete", branch)
|
||||
return err
|
||||
}
|
||||
|
||||
// Rev returns the commit hash for the given ref.
|
||||
func (g *Git) Rev(ref string) (string, error) {
|
||||
return g.run("rev-parse", ref)
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/steveyegge/gastown/internal/beads"
|
||||
"github.com/steveyegge/gastown/internal/git"
|
||||
"github.com/steveyegge/gastown/internal/rig"
|
||||
)
|
||||
|
||||
@@ -67,6 +68,7 @@ func DefaultMergeQueueConfig() *MergeQueueConfig {
|
||||
type Engineer struct {
|
||||
rig *rig.Rig
|
||||
beads *beads.Beads
|
||||
git *git.Git
|
||||
config *MergeQueueConfig
|
||||
workDir string
|
||||
|
||||
@@ -79,6 +81,7 @@ func NewEngineer(r *rig.Rig) *Engineer {
|
||||
return &Engineer{
|
||||
rig: r,
|
||||
beads: beads.New(r.Path),
|
||||
git: git.NewGit(r.Path),
|
||||
config: DefaultMergeQueueConfig(),
|
||||
workDir: r.Path,
|
||||
stopCh: make(chan struct{}),
|
||||
@@ -256,12 +259,7 @@ func (e *Engineer) processOnce(ctx context.Context) error {
|
||||
|
||||
// 6. Handle result
|
||||
if result.Success {
|
||||
// Close with merged reason
|
||||
reason := fmt.Sprintf("merged: %s", result.MergeCommit)
|
||||
if err := e.beads.CloseWithReason(reason, mr.ID); err != nil {
|
||||
fmt.Printf("[Engineer] Warning: failed to close MR %s: %v\n", mr.ID, err)
|
||||
}
|
||||
fmt.Printf("[Engineer] ✓ Merged: %s\n", mr.ID)
|
||||
e.handleSuccess(mr, result)
|
||||
} else {
|
||||
// Failure handling (detailed implementation in gt-3x1.4)
|
||||
e.handleFailure(mr, result)
|
||||
@@ -305,6 +303,56 @@ func (e *Engineer) ProcessMR(ctx context.Context, mr *beads.Issue) ProcessResult
|
||||
}
|
||||
}
|
||||
|
||||
// handleSuccess handles a successful merge completion.
|
||||
// Steps:
|
||||
// 1. Update MR with merge_commit SHA
|
||||
// 2. Close MR with reason 'merged'
|
||||
// 3. Close source issue with reference to MR
|
||||
// 4. Delete source branch if configured
|
||||
// 5. Log success
|
||||
func (e *Engineer) handleSuccess(mr *beads.Issue, result ProcessResult) {
|
||||
// Parse MR fields from description
|
||||
mrFields := beads.ParseMRFields(mr)
|
||||
if mrFields == nil {
|
||||
mrFields = &beads.MRFields{}
|
||||
}
|
||||
|
||||
// 1. Update MR with merge_commit SHA
|
||||
mrFields.MergeCommit = result.MergeCommit
|
||||
mrFields.CloseReason = "merged"
|
||||
newDesc := beads.SetMRFields(mr, mrFields)
|
||||
if err := e.beads.Update(mr.ID, beads.UpdateOptions{Description: &newDesc}); err != nil {
|
||||
fmt.Printf("[Engineer] Warning: failed to update MR %s with merge commit: %v\n", mr.ID, err)
|
||||
}
|
||||
|
||||
// 2. Close MR with reason 'merged'
|
||||
if err := e.beads.CloseWithReason("merged", mr.ID); err != nil {
|
||||
fmt.Printf("[Engineer] Warning: failed to close MR %s: %v\n", mr.ID, err)
|
||||
}
|
||||
|
||||
// 3. Close source issue with reference to MR
|
||||
if mrFields.SourceIssue != "" {
|
||||
closeReason := fmt.Sprintf("Merged in %s", mr.ID)
|
||||
if err := e.beads.CloseWithReason(closeReason, mrFields.SourceIssue); err != nil {
|
||||
fmt.Printf("[Engineer] Warning: failed to close source issue %s: %v\n", mrFields.SourceIssue, err)
|
||||
} else {
|
||||
fmt.Printf("[Engineer] Closed source issue: %s\n", mrFields.SourceIssue)
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Delete source branch if configured
|
||||
if e.config.DeleteMergedBranches && mrFields.Branch != "" {
|
||||
if err := e.git.DeleteRemoteBranch("origin", mrFields.Branch); err != nil {
|
||||
fmt.Printf("[Engineer] Warning: failed to delete branch %s: %v\n", mrFields.Branch, err)
|
||||
} else {
|
||||
fmt.Printf("[Engineer] Deleted branch: %s\n", mrFields.Branch)
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Log success
|
||||
fmt.Printf("[Engineer] ✓ Merged: %s (commit: %s)\n", mr.ID, result.MergeCommit)
|
||||
}
|
||||
|
||||
// handleFailure handles a failed merge request.
|
||||
// This is a placeholder that will be fully implemented in gt-3x1.4.
|
||||
func (e *Engineer) handleFailure(mr *beads.Issue, result ProcessResult) {
|
||||
|
||||
@@ -200,6 +200,9 @@ func TestNewEngineer(t *testing.T) {
|
||||
if e.beads == nil {
|
||||
t.Error("expected beads client to be initialized")
|
||||
}
|
||||
if e.git == nil {
|
||||
t.Error("expected git client to be initialized")
|
||||
}
|
||||
if e.config == nil {
|
||||
t.Error("expected config to be initialized with defaults")
|
||||
}
|
||||
@@ -207,3 +210,11 @@ func TestNewEngineer(t *testing.T) {
|
||||
t.Error("expected stopCh to be initialized")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEngineer_DeleteMergedBranchesConfig(t *testing.T) {
|
||||
// Test that DeleteMergedBranches is true by default
|
||||
cfg := DefaultMergeQueueConfig()
|
||||
if !cfg.DeleteMergedBranches {
|
||||
t.Error("expected DeleteMergedBranches to be true by default")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user