Merge pull request #853 from cli/reopen

Add `gh issue reopen <issue number or url>`
This commit is contained in:
Corey Johnson 2020-04-30 09:05:26 -07:00 committed by GitHub
commit 9e9e994ab0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 135 additions and 2 deletions

View file

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

View file

@ -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 <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)
@ -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 {

View file

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