From b0eba939e6c887ee8963b305a53e468da4e2b2ce Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Wed, 29 Apr 2020 12:21:44 -0700 Subject: [PATCH 1/8] Add test --- command/issue_test.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/command/issue_test.go b/command/issue_test.go index 4f75cde3ab5..570115d45ac 100644 --- a/command/issue_test.go +++ b/command/issue_test.go @@ -753,3 +753,29 @@ func TestIssueClose_issuesDisabled(t *testing.T) { t.Fatalf("got unexpected error: %s", err) } } + +func TestIssueReopen(t *testing.T) { + initBlankContext("", "OWNER/REPO", "master") + http := initFakeHTTP() + http.StubRepoResponse("OWNER", "REPO") + + http.StubResponse(200, bytes.NewBufferString(` + { "data": { "repository": { + "hasIssuesEnabled": true, + "issue": { "number": 1} + } } } + `)) + + http.StubResponse(200, bytes.NewBufferString(`{"id": "THE-ID"}`)) + + output, err := RunCommand(issueReopenCmd, "issue reopen 1") + if err != nil { + t.Fatalf("error running command `issue reopen`: %v", err) + } + + r := regexp.MustCompile(`Reopened issue #13`) + + if !r.MatchString(output.Stderr()) { + t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr()) + } +} From 49e5ef757f571a9251018cf0a74ddd46446ca184 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Wed, 29 Apr 2020 12:29:32 -0700 Subject: [PATCH 2/8] Fix test --- command/issue_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/command/issue_test.go b/command/issue_test.go index 570115d45ac..05d1049b594 100644 --- a/command/issue_test.go +++ b/command/issue_test.go @@ -762,18 +762,18 @@ func TestIssueReopen(t *testing.T) { http.StubResponse(200, bytes.NewBufferString(` { "data": { "repository": { "hasIssuesEnabled": true, - "issue": { "number": 1} + "issue": { "number": 2, "closed": true} } } } `)) http.StubResponse(200, bytes.NewBufferString(`{"id": "THE-ID"}`)) - output, err := RunCommand(issueReopenCmd, "issue reopen 1") + output, err := RunCommand(issueReopenCmd, "issue reopen 2") if err != nil { t.Fatalf("error running command `issue reopen`: %v", err) } - r := regexp.MustCompile(`Reopened issue #13`) + r := regexp.MustCompile(`Reopened issue #2`) if !r.MatchString(output.Stderr()) { t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr()) From f7162d7591a28fdb2d0bec6552b48d0b4ef4f6a9 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Wed, 29 Apr 2020 12:29:41 -0700 Subject: [PATCH 3/8] Implement issue reopen --- command/issue.go | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/command/issue.go b/command/issue.go index d1b57485ea0..331e8944311 100644 --- a/command/issue.go +++ b/command/issue.go @@ -41,6 +41,7 @@ func init() { issueViewCmd.Flags().BoolP("web", "w", false, "Open an issue in the browser") issueCmd.AddCommand(issueCloseCmd) + issueCmd.AddCommand(issueReopenCmd) } var issueCmd = &cobra.Command{ @@ -82,11 +83,17 @@ With '--web', open the issue in a web browser instead.`, RunE: issueView, } var issueCloseCmd = &cobra.Command{ - Use: "close ", - Short: "close and issue issues", + Use: "close ", + Short: "close issue", Args: cobra.ExactArgs(1), RunE: issueClose, } +var issueReopenCmd = &cobra.Command{ + Use: "reopen ", + Short: "reopen issue", + Args: cobra.ExactArgs(1), + RunE: issueReopen, +} func issueList(cmd *cobra.Command, args []string) error { ctx := contextForCommand(cmd) @@ -559,7 +566,41 @@ func issueClose(cmd *cobra.Command, args []string) error { fmt.Fprintf(colorableErr(cmd), "%s Closed issue #%d\n", utils.Red("✔"), issue.Number) return nil +} + +func issueReopen(cmd *cobra.Command, args []string) error { + ctx := contextForCommand(cmd) + apiClient, err := apiClientForContext(ctx) + if err != nil { + return err + } + + baseRepo, err := determineBaseRepo(cmd, ctx) + if err != nil { + return err + } + + issue, err := issueFromArg(apiClient, baseRepo, args[0]) + var idErr *api.IssuesDisabledError + if errors.As(err, &idErr) { + return fmt.Errorf("issues disabled for %s", ghrepo.FullName(baseRepo)) + } else if err != nil { + return fmt.Errorf("failed to find issue #%d: %w", issue.Number, err) + } + + if !issue.Closed { + fmt.Fprintf(colorableErr(cmd), "%s Issue #%d was already open\n", utils.Yellow("!"), issue.Number) + return nil + } + + err = api.IssueClose(apiClient, baseRepo, *issue) + if err != nil { + return fmt.Errorf("API call failed:%w", err) + } + fmt.Fprintf(colorableErr(cmd), "%s Reopened issue #%d\n", utils.Red("✔"), issue.Number) + + return nil } func displayURL(urlStr string) string { From abf6d59ee65103679b494a4d0f4d9691d0269639 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Wed, 29 Apr 2020 13:56:00 -0700 Subject: [PATCH 4/8] Green boi --- command/issue.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/issue.go b/command/issue.go index 331e8944311..68491764b3d 100644 --- a/command/issue.go +++ b/command/issue.go @@ -598,7 +598,7 @@ func issueReopen(cmd *cobra.Command, args []string) error { return fmt.Errorf("API call failed:%w", err) } - fmt.Fprintf(colorableErr(cmd), "%s Reopened issue #%d\n", utils.Red("✔"), issue.Number) + fmt.Fprintf(colorableErr(cmd), "%s Reopened issue #%d\n", utils.Green("✔"), issue.Number) return nil } From 7df1b992db85e003e0ba694f8a49310e0479a46f Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Wed, 29 Apr 2020 13:57:53 -0700 Subject: [PATCH 5/8] Add "already open" test --- command/issue.go | 2 +- command/issue_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/command/issue.go b/command/issue.go index 68491764b3d..0271c4e4ce9 100644 --- a/command/issue.go +++ b/command/issue.go @@ -589,7 +589,7 @@ func issueReopen(cmd *cobra.Command, args []string) error { } if !issue.Closed { - fmt.Fprintf(colorableErr(cmd), "%s Issue #%d was already open\n", utils.Yellow("!"), issue.Number) + fmt.Fprintf(colorableErr(cmd), "%s Issue #%d is already open\n", utils.Yellow("!"), issue.Number) return nil } diff --git a/command/issue_test.go b/command/issue_test.go index 05d1049b594..eee7218c334 100644 --- a/command/issue_test.go +++ b/command/issue_test.go @@ -779,3 +779,29 @@ func TestIssueReopen(t *testing.T) { t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr()) } } + +func TestIssueReopen_alreadyOpen(t *testing.T) { + initBlankContext("", "OWNER/REPO", "master") + http := initFakeHTTP() + http.StubRepoResponse("OWNER", "REPO") + + http.StubResponse(200, bytes.NewBufferString(` + { "data": { "repository": { + "hasIssuesEnabled": true, + "issue": { "number": 2, "closed": false} + } } } + `)) + + http.StubResponse(200, bytes.NewBufferString(`{"id": "THE-ID"}`)) + + output, err := RunCommand(issueReopenCmd, "issue reopen 2") + if err != nil { + t.Fatalf("error running command `issue reopen`: %v", err) + } + + r := regexp.MustCompile(`#2 is already open`) + + if !r.MatchString(output.Stderr()) { + t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr()) + } +} From a9f34069f1b93b851c4a9437d3ddd07cb930fe11 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Wed, 29 Apr 2020 13:58:47 -0700 Subject: [PATCH 6/8] Add "issues disabled" test --- command/issue_test.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/command/issue_test.go b/command/issue_test.go index eee7218c334..e408ce3ccb7 100644 --- a/command/issue_test.go +++ b/command/issue_test.go @@ -805,3 +805,24 @@ func TestIssueReopen_alreadyOpen(t *testing.T) { t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr()) } } + +func TestIssueReopen_issuesDisabled(t *testing.T) { + initBlankContext("", "OWNER/REPO", "master") + http := initFakeHTTP() + http.StubRepoResponse("OWNER", "REPO") + + http.StubResponse(200, bytes.NewBufferString(` + { "data": { "repository": { + "hasIssuesEnabled": false + } } } + `)) + + _, err := RunCommand(issueReopenCmd, "issue reopen 2") + if err == nil { + t.Fatalf("expected error when issues are disabled") + } + + if !strings.Contains(err.Error(), "issues disabled") { + t.Fatalf("got unexpected error: %s", err) + } +} From 23c072b39d60160183c6e8b4a05907556354d523 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Wed, 29 Apr 2020 14:14:50 -0700 Subject: [PATCH 7/8] Add api call --- api/queries_issue.go | 23 +++++++++++++++++++++++ command/issue.go | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/api/queries_issue.go b/api/queries_issue.go index ba9b43d6536..e4838651f4a 100644 --- a/api/queries_issue.go +++ b/api/queries_issue.go @@ -390,3 +390,26 @@ func IssueClose(client *Client, repo ghrepo.Interface, issue Issue) error { return nil } + +func IssueReopen(client *Client, repo ghrepo.Interface, issue Issue) error { + var mutation struct { + ReopenIssue struct { + Issue struct { + ID githubv4.ID + } + } `graphql:"reopenIssue(input: $input)"` + } + + input := githubv4.ReopenIssueInput{ + IssueID: issue.ID, + } + + v4 := githubv4.NewClient(client.http) + err := v4.Mutate(context.Background(), &mutation, input, nil) + + if err != nil { + return err + } + + return nil +} diff --git a/command/issue.go b/command/issue.go index 0271c4e4ce9..f86ad2cd542 100644 --- a/command/issue.go +++ b/command/issue.go @@ -593,7 +593,7 @@ func issueReopen(cmd *cobra.Command, args []string) error { return nil } - err = api.IssueClose(apiClient, baseRepo, *issue) + err = api.IssueReopen(apiClient, baseRepo, *issue) if err != nil { return fmt.Errorf("API call failed:%w", err) } From e2aab3083685bf6b5ddbbb7f9472f7e670b5eed6 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Thu, 30 Apr 2020 08:59:14 -0700 Subject: [PATCH 8/8] just return the err Co-authored-by: Nate Smith --- api/queries_issue.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/api/queries_issue.go b/api/queries_issue.go index e4838651f4a..56a04edd906 100644 --- a/api/queries_issue.go +++ b/api/queries_issue.go @@ -407,9 +407,5 @@ func IssueReopen(client *Client, repo ghrepo.Interface, issue Issue) error { v4 := githubv4.NewClient(client.http) err := v4.Mutate(context.Background(), &mutation, input, nil) - if err != nil { - return err - } - - return nil + return err }