Skip to content

Commit 405fc97

Browse files
authored
Remove direct gh pr merge from TUI — daemon handles merging (#24)
m key now only sets merge method via SetMergeMethod (daemon does the actual merge on next poll when autopilot conditions are met). Removes all direct gh pr merge / gh pr comment calls from the picker handlers. Also removes dead mergePickerForConfig field since picker is always config-only now, and simplifies picker option labels (no more "automerge" suffix).
1 parent 4197dde commit 405fc97

3 files changed

Lines changed: 29 additions & 101 deletions

File tree

tui/internal/tui/app.go

Lines changed: 25 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,9 @@ type Model struct {
6565
glowDir int // 1 or -1 for ping-pong
6666
inputMode bool // text input active (for + add PR)
6767
inputBuffer string // text being typed
68-
mergePickerVisible bool // merge strategy picker showing
69-
mergePickerPR *client.TrackedPR // PR being merged (may be nil for config-only mode)
70-
mergePickerPRKey string // "owner/repo#N" — used for SetMergeMethod
71-
mergePickerForConfig bool // true when picker is for configuring method (new repo), not immediate merge
68+
mergePickerVisible bool // merge method picker showing
69+
mergePickerPR *client.TrackedPR // PR being configured (for display)
70+
mergePickerPRKey string // "owner/repo#N" — used for SetMergeMethod
7271
scrollOffset int // scroll position in zoom body
7372
}
7473

@@ -240,7 +239,6 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
240239
}
241240
m.mergePickerPR = found
242241
m.mergePickerPRKey = msg.prKey
243-
m.mergePickerForConfig = true
244242
m.mergePickerVisible = true
245243
return m, nil
246244
}
@@ -504,126 +502,63 @@ end tell`, tabIdx, tabIdx)
504502
}
505503

506504
case "m":
507-
// Merge selected PR — show merge strategy picker (immediate merge + persist).
505+
// Set merge method for selected PR — daemon handles the actual merge.
508506
if pr := m.selectedPR(); pr != nil {
509507
m.mergePickerPR = pr
510508
m.mergePickerPRKey = prKey(pr)
511-
m.mergePickerForConfig = false
512-
m.mergePickerVisible = true
513-
return m, nil
514-
}
515-
516-
case "M":
517-
// Change merge method for selected PR — picker in config-only mode.
518-
if pr := m.selectedPR(); pr != nil {
519-
m.mergePickerPR = pr
520-
m.mergePickerPRKey = prKey(pr)
521-
m.mergePickerForConfig = true
522509
m.mergePickerVisible = true
523510
return m, nil
524511
}
525512

526513
case "1":
527-
// Merge picker: squash automerge.
528-
if m.mergePickerVisible && (m.mergePickerPR != nil || m.mergePickerForConfig) {
529-
pr := m.mergePickerPR
514+
// Merge picker: squash.
515+
if m.mergePickerVisible {
530516
key := m.mergePickerPRKey
531-
forConfig := m.mergePickerForConfig
532517
m.mergePickerVisible = false
533518
m.mergePickerPR = nil
534519
m.mergePickerPRKey = ""
535-
m.mergePickerForConfig = false
536520
return m, func() tea.Msg {
537521
_ = m.client.SetMergeMethod(key, "squash")
538-
if forConfig {
539-
return actionResultMsg{action: "merge method set: squash"}
540-
}
541-
err := exec.Command("gh", "pr", "merge",
542-
fmt.Sprintf("%d", pr.Number),
543-
"--repo", fmt.Sprintf("%s/%s", pr.Owner, pr.Repo),
544-
"--squash", "--auto").Run()
545-
if err != nil {
546-
return actionResultMsg{action: "squash merge", err: err}
547-
}
548-
return actionResultMsg{action: "squash automerge enabled"}
522+
return actionResultMsg{action: "merge method: squash"}
549523
}
550524
}
551525

552526
case "2":
553-
// Merge picker: rebase automerge.
554-
if m.mergePickerVisible && (m.mergePickerPR != nil || m.mergePickerForConfig) {
555-
pr := m.mergePickerPR
527+
// Merge picker: rebase.
528+
if m.mergePickerVisible {
556529
key := m.mergePickerPRKey
557-
forConfig := m.mergePickerForConfig
558530
m.mergePickerVisible = false
559531
m.mergePickerPR = nil
560532
m.mergePickerPRKey = ""
561-
m.mergePickerForConfig = false
562533
return m, func() tea.Msg {
563534
_ = m.client.SetMergeMethod(key, "rebase")
564-
if forConfig {
565-
return actionResultMsg{action: "merge method set: rebase"}
566-
}
567-
err := exec.Command("gh", "pr", "merge",
568-
fmt.Sprintf("%d", pr.Number),
569-
"--repo", fmt.Sprintf("%s/%s", pr.Owner, pr.Repo),
570-
"--rebase", "--auto").Run()
571-
if err != nil {
572-
return actionResultMsg{action: "rebase merge", err: err}
573-
}
574-
return actionResultMsg{action: "rebase automerge enabled"}
535+
return actionResultMsg{action: "merge method: rebase"}
575536
}
576537
}
577538

578539
case "3":
579-
// Merge picker: Aviator merge queue.
580-
if m.mergePickerVisible && (m.mergePickerPR != nil || m.mergePickerForConfig) {
581-
pr := m.mergePickerPR
540+
// Merge picker: Aviator.
541+
if m.mergePickerVisible {
582542
key := m.mergePickerPRKey
583-
forConfig := m.mergePickerForConfig
584543
m.mergePickerVisible = false
585544
m.mergePickerPR = nil
586545
m.mergePickerPRKey = ""
587-
m.mergePickerForConfig = false
588546
return m, func() tea.Msg {
589547
_ = m.client.SetMergeMethod(key, "aviator")
590-
if forConfig {
591-
return actionResultMsg{action: "merge method set: aviator"}
592-
}
593-
err := exec.Command("gh", "pr", "comment",
594-
fmt.Sprintf("%d", pr.Number),
595-
"--repo", fmt.Sprintf("%s/%s", pr.Owner, pr.Repo),
596-
"--body", "/aviator merge").Run()
597-
if err != nil {
598-
return actionResultMsg{action: "aviator merge", err: err}
599-
}
600-
return actionResultMsg{action: "aviator merge queued"}
548+
return actionResultMsg{action: "merge method: aviator"}
601549
}
602550
}
603551

604552
case "4":
605-
// Merge picker: merge commit automerge.
606-
if m.mergePickerVisible && (m.mergePickerPR != nil || m.mergePickerForConfig) {
607-
pr := m.mergePickerPR
553+
// Merge picker: merge commit.
554+
if m.mergePickerVisible {
608555
key := m.mergePickerPRKey
609-
forConfig := m.mergePickerForConfig
610556
m.mergePickerVisible = false
611557
m.mergePickerPR = nil
612558
m.mergePickerPRKey = ""
613-
m.mergePickerForConfig = false
614559
return m, func() tea.Msg {
615560
_ = m.client.SetMergeMethod(key, "merge")
616-
if forConfig {
617-
return actionResultMsg{action: "merge method set: merge commit"}
618-
}
619-
err := exec.Command("gh", "pr", "merge",
620-
fmt.Sprintf("%d", pr.Number),
621-
"--repo", fmt.Sprintf("%s/%s", pr.Owner, pr.Repo),
622-
"--merge", "--auto").Run()
623-
if err != nil {
624-
return actionResultMsg{action: "merge commit", err: err}
625-
}
626-
return actionResultMsg{action: "merge commit automerge enabled"}
561+
return actionResultMsg{action: "merge method: merge commit"}
627562
}
628563
}
629564

@@ -632,7 +567,6 @@ end tell`, tabIdx, tabIdx)
632567
m.mergePickerVisible = false
633568
m.mergePickerPR = nil
634569
m.mergePickerPRKey = ""
635-
m.mergePickerForConfig = false
636570
} else if m.inputMode {
637571
m.inputMode = false
638572
m.inputBuffer = ""
@@ -751,27 +685,22 @@ func (m Model) View() string {
751685

752686
bottomHeight := stripHeight + hintsHeight
753687

754-
// Merge strategy picker overlay.
755-
if m.mergePickerVisible && (m.mergePickerPR != nil || m.mergePickerForConfig) {
688+
// Merge method picker overlay.
689+
if m.mergePickerVisible {
756690
var header string
757-
if m.mergePickerForConfig {
758-
if m.mergePickerPR != nil {
759-
pr := m.mergePickerPR
760-
header = fmt.Sprintf(" Set merge method for #%d %s\n", pr.Number, pr.Title)
761-
} else {
762-
header = fmt.Sprintf(" Set merge method for %s\n", m.mergePickerPRKey)
763-
}
764-
} else {
691+
if m.mergePickerPR != nil {
765692
pr := m.mergePickerPR
766-
header = fmt.Sprintf(" Merge #%d %s\n", pr.Number, pr.Title)
693+
header = fmt.Sprintf(" Set merge method for #%d %s\n", pr.Number, pr.Title)
694+
} else {
695+
header = fmt.Sprintf(" Set merge method for %s\n", m.mergePickerPRKey)
767696
}
768697
picker := lipgloss.NewStyle().Padding(1, 2).Render(
769698
styleZoomHeader.Render(header) + "\n" +
770699
lipgloss.NewStyle().Foreground(colorFg).Render(
771-
" [1] Squash automerge\n"+
772-
" [2] Rebase automerge\n"+
700+
" [1] Squash\n"+
701+
" [2] Rebase\n"+
773702
" [3] Aviator merge queue\n"+
774-
" [4] Merge commit automerge\n"+
703+
" [4] Merge commit\n"+
775704
" [Esc] Cancel"))
776705

777706
return lipgloss.JoinVertical(lipgloss.Left,

tui/internal/tui/hints.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ func renderHints(queueVisible bool, hasPending bool, isPRSelected bool, width in
2323
// PR-specific hints.
2424
keys = append(keys, hint{"Enter", "open PR"})
2525
keys = append(keys, hint{"a", "autopilot"})
26-
keys = append(keys, hint{"m", "merge"})
27-
keys = append(keys, hint{"M", "set method"})
26+
keys = append(keys, hint{"m", "method"})
2827
keys = append(keys, hint{"+", "add PR"})
2928
keys = append(keys, hint{"-", "remove"})
3029
} else {
@@ -110,7 +109,7 @@ func renderHelp(width, height, scrollOffset int) string {
110109
{"a", "Cycle PR autopilot: OFF → AUTO → YOLO"},
111110
{"+", "Add PR to tracking (paste URL)"},
112111
{"-", "Remove selected PR"},
113-
{"m", "Merge — pick strategy"},
112+
{"m", "Set merge method (daemon handles actual merge)"},
114113
{"o", "Open PR in browser"},
115114
{"", ""},
116115
{"h", "Toggle this help screen"},

tui/internal/tui/hints_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ func TestRenderHints_MergedNavigate(t *testing.T) {
8282
func TestRenderHints_PRSelected(t *testing.T) {
8383
out := renderHints(false, false, true, 200)
8484
// Should show PR-specific hints.
85-
if !strings.Contains(out, "merge") {
86-
t.Error("PR selected: hints should contain 'merge'")
85+
if !strings.Contains(out, "method") {
86+
t.Error("PR selected: hints should contain 'method'")
8787
}
8888
if !strings.Contains(out, "add PR") {
8989
t.Error("PR selected: hints should contain 'add PR'")

0 commit comments

Comments
 (0)