Skip to content

Commit 3334bdd

Browse files
author
Nate Smith
authored
Merge pull request cli#668 from cli/mislav/check-if-pr-exists
Check for existing pull request on `pr create`
2 parents 75ebf16 + 5b76881 commit 3334bdd

File tree

2 files changed

+73
-7
lines changed

2 files changed

+73
-7
lines changed

command/pr_create.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,26 @@ func prCreate(cmd *cobra.Command, _ []string) error {
123123
if defaultsErr != nil {
124124
return fmt.Errorf("could not compute title or body defaults: %w", defaultsErr)
125125
}
126-
action = SubmitAction
127126
title = defs.Title
128127
body = defs.Body
129-
} else {
128+
}
129+
130+
if !isWeb {
131+
headBranchLabel := headBranch
132+
if headRepo != nil && !ghrepo.IsSame(baseRepo, headRepo) {
133+
headBranchLabel = fmt.Sprintf("%s:%s", headRepo.RepoOwner(), headBranch)
134+
}
135+
existingPR, err := api.PullRequestForBranch(client, baseRepo, headBranchLabel)
136+
var notFound *api.NotFoundError
137+
if err != nil && !errors.As(err, &notFound) {
138+
return fmt.Errorf("error checking for existing pull request: %w", err)
139+
}
140+
if err == nil {
141+
return fmt.Errorf("a pull request for branch %q already exists:\n%s", headBranchLabel, existingPR.URL)
142+
}
143+
}
144+
145+
if !isWeb && !autofill {
130146
fmt.Fprintf(colorableErr(cmd), "\nCreating pull request for %s into %s in %s\n\n",
131147
utils.Cyan(headBranch),
132148
utils.Cyan(baseBranch),

command/pr_create_test.go

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ func TestPRCreate(t *testing.T) {
1414
initBlankContext("OWNER/REPO", "feature")
1515
http := initFakeHTTP()
1616
http.StubRepoResponse("OWNER", "REPO")
17+
http.StubResponse(200, bytes.NewBufferString(`
18+
{ "data": { "repository": { "pullRequests": { "nodes" : [
19+
] } } } }
20+
`))
1721
http.StubResponse(200, bytes.NewBufferString(`
1822
{ "data": { "createPullRequest": { "pullRequest": {
1923
"URL": "https://github.com/OWNER/REPO/pull/12"
@@ -30,7 +34,7 @@ func TestPRCreate(t *testing.T) {
3034
output, err := RunCommand(prCreateCmd, `pr create -t "my title" -b "my body"`)
3135
eq(t, err, nil)
3236

33-
bodyBytes, _ := ioutil.ReadAll(http.Requests[1].Body)
37+
bodyBytes, _ := ioutil.ReadAll(http.Requests[2].Body)
3438
reqBody := struct {
3539
Variables struct {
3640
Input struct {
@@ -53,6 +57,32 @@ func TestPRCreate(t *testing.T) {
5357
eq(t, output.String(), "https://github.com/OWNER/REPO/pull/12\n")
5458
}
5559

60+
func TestPRCreate_alreadyExists(t *testing.T) {
61+
initBlankContext("OWNER/REPO", "feature")
62+
http := initFakeHTTP()
63+
http.StubRepoResponse("OWNER", "REPO")
64+
http.StubResponse(200, bytes.NewBufferString(`
65+
{ "data": { "repository": { "pullRequests": { "nodes": [
66+
{ "url": "https://github.com/OWNER/REPO/pull/123",
67+
"headRefName": "feature" }
68+
] } } } }
69+
`))
70+
71+
cs, cmdTeardown := initCmdStubber()
72+
defer cmdTeardown()
73+
74+
cs.Stub("") // git status
75+
cs.Stub("1234567890,commit 0\n2345678901,commit 1") // git log
76+
77+
_, err := RunCommand(prCreateCmd, `pr create`)
78+
if err == nil {
79+
t.Fatal("error expected, got nil")
80+
}
81+
if err.Error() != "a pull request for branch \"feature\" already exists:\nhttps://github.com/OWNER/REPO/pull/123" {
82+
t.Errorf("got error %q", err)
83+
}
84+
}
85+
5686
func TestPRCreate_web(t *testing.T) {
5787
initBlankContext("OWNER/REPO", "feature")
5888
http := initFakeHTTP()
@@ -83,6 +113,10 @@ func TestPRCreate_ReportsUncommittedChanges(t *testing.T) {
83113
http := initFakeHTTP()
84114

85115
http.StubRepoResponse("OWNER", "REPO")
116+
http.StubResponse(200, bytes.NewBufferString(`
117+
{ "data": { "repository": { "pullRequests": { "nodes" : [
118+
] } } } }
119+
`))
86120
http.StubResponse(200, bytes.NewBufferString(`
87121
{ "data": { "createPullRequest": { "pullRequest": {
88122
"URL": "https://github.com/OWNER/REPO/pull/12"
@@ -149,6 +183,10 @@ func TestPRCreate_cross_repo_same_branch(t *testing.T) {
149183
"viewerPermission": "WRITE"
150184
} } }
151185
`))
186+
http.StubResponse(200, bytes.NewBufferString(`
187+
{ "data": { "repository": { "pullRequests": { "nodes" : [
188+
] } } } }
189+
`))
152190
http.StubResponse(200, bytes.NewBufferString(`
153191
{ "data": { "createPullRequest": { "pullRequest": {
154192
"URL": "https://github.com/OWNER/REPO/pull/12"
@@ -165,7 +203,7 @@ func TestPRCreate_cross_repo_same_branch(t *testing.T) {
165203
output, err := RunCommand(prCreateCmd, `pr create -t "cross repo" -b "same branch"`)
166204
eq(t, err, nil)
167205

168-
bodyBytes, _ := ioutil.ReadAll(http.Requests[1].Body)
206+
bodyBytes, _ := ioutil.ReadAll(http.Requests[2].Body)
169207
reqBody := struct {
170208
Variables struct {
171209
Input struct {
@@ -194,6 +232,10 @@ func TestPRCreate_survey_defaults_multicommit(t *testing.T) {
194232
initBlankContext("OWNER/REPO", "cool_bug-fixes")
195233
http := initFakeHTTP()
196234
http.StubRepoResponse("OWNER", "REPO")
235+
http.StubResponse(200, bytes.NewBufferString(`
236+
{ "data": { "repository": { "pullRequests": { "nodes" : [
237+
] } } } }
238+
`))
197239
http.StubResponse(200, bytes.NewBufferString(`
198240
{ "data": { "createPullRequest": { "pullRequest": {
199241
"URL": "https://github.com/OWNER/REPO/pull/12"
@@ -231,7 +273,7 @@ func TestPRCreate_survey_defaults_multicommit(t *testing.T) {
231273
output, err := RunCommand(prCreateCmd, `pr create`)
232274
eq(t, err, nil)
233275

234-
bodyBytes, _ := ioutil.ReadAll(http.Requests[1].Body)
276+
bodyBytes, _ := ioutil.ReadAll(http.Requests[2].Body)
235277
reqBody := struct {
236278
Variables struct {
237279
Input struct {
@@ -260,6 +302,10 @@ func TestPRCreate_survey_defaults_monocommit(t *testing.T) {
260302
initBlankContext("OWNER/REPO", "feature")
261303
http := initFakeHTTP()
262304
http.StubRepoResponse("OWNER", "REPO")
305+
http.StubResponse(200, bytes.NewBufferString(`
306+
{ "data": { "repository": { "pullRequests": { "nodes" : [
307+
] } } } }
308+
`))
263309
http.StubResponse(200, bytes.NewBufferString(`
264310
{ "data": { "createPullRequest": { "pullRequest": {
265311
"URL": "https://github.com/OWNER/REPO/pull/12"
@@ -298,7 +344,7 @@ func TestPRCreate_survey_defaults_monocommit(t *testing.T) {
298344
output, err := RunCommand(prCreateCmd, `pr create`)
299345
eq(t, err, nil)
300346

301-
bodyBytes, _ := ioutil.ReadAll(http.Requests[1].Body)
347+
bodyBytes, _ := ioutil.ReadAll(http.Requests[2].Body)
302348
reqBody := struct {
303349
Variables struct {
304350
Input struct {
@@ -327,6 +373,10 @@ func TestPRCreate_survey_autofill(t *testing.T) {
327373
initBlankContext("OWNER/REPO", "feature")
328374
http := initFakeHTTP()
329375
http.StubRepoResponse("OWNER", "REPO")
376+
http.StubResponse(200, bytes.NewBufferString(`
377+
{ "data": { "repository": { "pullRequests": { "nodes" : [
378+
] } } } }
379+
`))
330380
http.StubResponse(200, bytes.NewBufferString(`
331381
{ "data": { "createPullRequest": { "pullRequest": {
332382
"URL": "https://github.com/OWNER/REPO/pull/12"
@@ -346,7 +396,7 @@ func TestPRCreate_survey_autofill(t *testing.T) {
346396
output, err := RunCommand(prCreateCmd, `pr create -f`)
347397
eq(t, err, nil)
348398

349-
bodyBytes, _ := ioutil.ReadAll(http.Requests[1].Body)
399+
bodyBytes, _ := ioutil.ReadAll(http.Requests[2].Body)
350400
reqBody := struct {
351401
Variables struct {
352402
Input struct {

0 commit comments

Comments
 (0)