Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions api/queries_issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,22 @@ 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)

return err
}
45 changes: 43 additions & 2 deletions command/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -82,11 +83,17 @@ With '--web', open the issue in a web browser instead.`,
RunE: issueView,
}
var issueCloseCmd = &cobra.Command{
Use: "close <number>",
Short: "close and issue issues",
Use: "close <numberOrURL>",
Short: "close issue",
Args: cobra.ExactArgs(1),
RunE: issueClose,
}
var issueReopenCmd = &cobra.Command{
Use: "reopen <numberOrURL>",
Short: "reopen issue",
Args: cobra.ExactArgs(1),
RunE: issueReopen,
}

func issueList(cmd *cobra.Command, args []string) error {
ctx := contextForCommand(cmd)
Expand Down Expand Up @@ -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 is already open\n", utils.Yellow("!"), issue.Number)
return nil
}

err = api.IssueReopen(apiClient, baseRepo, *issue)
if err != nil {
return fmt.Errorf("API call failed:%w", err)
}

fmt.Fprintf(colorableErr(cmd), "%s Reopened issue #%d\n", utils.Green("✔"), issue.Number)

return nil
}

func displayURL(urlStr string) string {
Expand Down
73 changes: 73 additions & 0 deletions command/issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -753,3 +753,76 @@ 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": 2, "closed": true}
} } }
`))

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(`Reopened issue #2`)

if !r.MatchString(output.Stderr()) {
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())
}
}

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)
}
}