Skip to content

Commit 4513738

Browse files
committed
fix(submit): check for existing PR before prompting for details
When a branch already has a PR on GitHub but the association isn't stored in local git config, `gh stack submit` would prompt the user for PR title and description, only to discover (via API error) that the PR already exists. Now we call `FindPRByHead` before prompting. If a PR exists, we adopt it immediately without unnecessary prompting. Refactored `adoptExistingPR` to extract `adoptExistingPRDirect`, avoiding a redundant API call when we've already fetched the PR.
1 parent 1d1cd6a commit 4513738

1 file changed

Lines changed: 18 additions & 0 deletions

File tree

cmd/submit.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,18 @@ func doSubmitPRs(g *git.Git, cfg *config.Config, root *tree.Node, branches []*tr
335335
// If a PR already exists for the branch, it adopts the existing PR instead.
336336
// Returns (prNumber, adopted, error) where adopted is true if we adopted an existing PR.
337337
func createPRForBranch(g *git.Git, ghClient *github.Client, cfg *config.Config, root *tree.Node, branch, base, trunk string, remoteBranches map[string]bool, s *style.Style) (int, bool, error) {
338+
// Check for existing PR on GitHub BEFORE prompting user for title/description.
339+
// This avoids the confusing UX where we prompt then immediately say "oh, PR already exists".
340+
existingPR, err := ghClient.FindPRByHead(branch)
341+
if err != nil {
342+
// Non-fatal: proceed with creation attempt which will give clearer error if needed
343+
fmt.Printf("%s could not check for existing PR: %v\n", s.WarningIcon(), err)
344+
} else if existingPR != nil {
345+
// PR exists on GitHub but wasn't in local config - adopt it without prompting
346+
prNum, adoptErr := adoptExistingPRDirect(ghClient, cfg, root, branch, base, trunk, remoteBranches, existingPR, s)
347+
return prNum, true, adoptErr
348+
}
349+
338350
// Determine if draft (not targeting trunk = middle of stack)
339351
draft := base != trunk
340352

@@ -500,6 +512,12 @@ func adoptExistingPR(ghClient *github.Client, cfg *config.Config, root *tree.Nod
500512
return 0, fmt.Errorf("PR creation failed but no existing PR found for branch %q", branch)
501513
}
502514

515+
return adoptExistingPRDirect(ghClient, cfg, root, branch, base, trunk, remoteBranches, existingPR, s)
516+
}
517+
518+
// adoptExistingPRDirect adopts an already-fetched PR into the stack.
519+
// This is the implementation shared by adoptExistingPR and the early-detection path in createPRForBranch.
520+
func adoptExistingPRDirect(ghClient *github.Client, cfg *config.Config, root *tree.Node, branch, base, trunk string, remoteBranches map[string]bool, existingPR *github.PR, s *style.Style) (int, error) {
503521
// Store PR number in config
504522
if err := cfg.SetPR(branch, existingPR.Number); err != nil {
505523
return existingPR.Number, fmt.Errorf("failed to store PR number: %w", err)

0 commit comments

Comments
 (0)