From 3afec6f90aea8707de7610ce6a539faaf766c6fa Mon Sep 17 00:00:00 2001 From: Pavel Borzenkov Date: Sat, 27 Jun 2020 19:03:25 +0300 Subject: [PATCH] api: gracefully handle already deleted remote refs If a GitHub repo is configured to automatically delete branches after PR is merged, `gh pr merge` fails with error like: failed to delete remote branch: ... (422): 'Reference does not exist' Gracefully handle such case and don't report the error. Signed-off-by: Pavel Borzenkov --- api/queries_pr.go | 11 ++++++++++- api/queries_pr_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 api/queries_pr_test.go diff --git a/api/queries_pr.go b/api/queries_pr.go index 00d01661a..b42a94eec 100644 --- a/api/queries_pr.go +++ b/api/queries_pr.go @@ -1015,7 +1015,16 @@ func BranchDeleteRemote(client *Client, repo ghrepo.Interface, branch string) er NodeID string `json:"node_id"` } path := fmt.Sprintf("repos/%s/%s/git/refs/heads/%s", repo.RepoOwner(), repo.RepoName(), branch) - return client.REST("DELETE", path, nil, &response) + err := client.REST("DELETE", path, nil, &response) + if err != nil { + var httpErr HTTPError + // The ref might have already been deleted by GitHub + if !errors.As(err, &httpErr) || httpErr.Code != 422 { + return err + } + } + + return nil } func min(a, b int) int { diff --git a/api/queries_pr_test.go b/api/queries_pr_test.go new file mode 100644 index 000000000..3b8bf0a65 --- /dev/null +++ b/api/queries_pr_test.go @@ -0,0 +1,42 @@ +package api + +import ( + "bytes" + "testing" + + "github.com/cli/cli/internal/ghrepo" + "github.com/cli/cli/pkg/httpmock" +) + +func TestBranchDeleteRemote(t *testing.T) { + var tests = []struct { + name string + code int + body string + expectError bool + }{ + {name: "success", code: 204, body: "", expectError: false}, + {name: "error", code: 500, body: `{"message": "oh no"}`, expectError: true}, + { + name: "already_deleted", + code: 422, + body: `{"message": "Reference does not exist"}`, + expectError: false, + }, + } + + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + http := &httpmock.Registry{} + client := NewClient(ReplaceTripper(http)) + + http.StubResponse(tc.code, bytes.NewBufferString(tc.body)) + repo, _ := ghrepo.FromFullName("OWNER/REPO") + err := BranchDeleteRemote(client, repo, "branch") + if isError := err != nil; isError != tc.expectError { + t.Fatalf("unexpected result: %v", err) + } + }) + } +}