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

Skip to content
Closed
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 @@ -123,6 +123,25 @@ func IssueCreate(client *Client, repo *Repository, params map[string]interface{}
return &result.CreateIssue.Issue, nil
}

func CommentCreate(client *Client, repoHost string, params map[string]interface{}) error {
query := `
mutation CommentCreate($input: AddCommentInput!) {
addComment(input: $input) { clientMutationId }
}`

variables := map[string]interface{}{
"input": params,
}

err := client.GraphQL(repoHost, query, variables, nil)

if err != nil {
return err
}

return nil
}

func IssueStatus(client *Client, repo ghrepo.Interface, currentUsername string) (*IssuesPayload, error) {
type response struct {
Repository struct {
Expand Down
202 changes: 202 additions & 0 deletions pkg/cmd/issue/comment/comment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
package comment

import (
"fmt"
"net/http"

"github.com/AlecAivazis/survey/v2"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/api"
"github.com/cli/cli/internal/config"
"github.com/cli/cli/internal/ghrepo"
"github.com/cli/cli/pkg/cmd/issue/shared"
"github.com/cli/cli/pkg/cmdutil"
"github.com/cli/cli/pkg/iostreams"
"github.com/cli/cli/pkg/prompt"
"github.com/cli/cli/pkg/surveyext"
"github.com/spf13/cobra"
)

type CommentOptions struct {
HttpClient func() (*http.Client, error)
Config func() (config.Config, error)
IO *iostreams.IOStreams
BaseRepo func() (ghrepo.Interface, error)
Body string
SelectorArg string
Interactive bool
Action Action
}

func NewCmdComment(f *cmdutil.Factory, runF func(*CommentOptions) error) *cobra.Command {
opts := &CommentOptions{
IO: f.IOStreams,
HttpClient: f.HttpClient,
Config: f.Config,
}

cmd := &cobra.Command{
Use: "comment {<number> | <url>}",
Short: "Create comments for the issue",
Example: heredoc.Doc(`
$ gh issue comment --body "I found a bug. Nothing works"
`),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
// support `-R, --repo` override
opts.BaseRepo = f.BaseRepo

bodyProvided := cmd.Flags().Changed("body")

opts.Interactive = !(bodyProvided)

if len(args) > 0 {
opts.SelectorArg = args[0]
}

if runF != nil {
return runF(opts)
}
return commentRun(opts)
},
}

cmd.Flags().StringVarP(&opts.Body, "body", "b", "", "Supply a body.")

return cmd
}

type Action int

const (
SubmitAction Action = iota
CancelAction
)

func titleBodySurvey(editorCommand string, issueState *CommentOptions, apiClient *api.Client, repo ghrepo.Interface, providedBody string) error {
bodyQuestion := &survey.Question{
Name: "body",
Prompt: &surveyext.GhEditor{
BlankAllowed: false,
EditorCommand: editorCommand,
Editor: &survey.Editor{
Message: "Body",
FileName: "*.md",
Default: issueState.Body,
},
},
}

var qs []*survey.Question

if providedBody == "" {
qs = append(qs, bodyQuestion)
}

err := prompt.SurveyAsk(qs, issueState)
if err != nil {
panic(fmt.Sprintf("could not prompt: %v", err))
}

confirmA, err := confirmSubmission()

if err != nil {
panic(fmt.Sprintf("unable to confirm: %v", err))
}

issueState.Action = confirmA
return nil
}

func confirmSubmission() (Action, error) {
const (
submitLabel = "Submit"
cancelLabel = "Cancel"
)

options := []string{submitLabel, cancelLabel}

confirmAnswers := struct {
Confirmation int
}{}
confirmQs := []*survey.Question{
{
Name: "confirmation",
Prompt: &survey.Select{
Message: "What's next?",
Options: options,
},
},
}

err := prompt.SurveyAsk(confirmQs, &confirmAnswers)
if err != nil {
return -1, fmt.Errorf("could not prompt: %w", err)
}

switch options[confirmAnswers.Confirmation] {
case submitLabel:
return SubmitAction, nil
case cancelLabel:
return CancelAction, nil
default:
return -1, fmt.Errorf("invalid index: %d", confirmAnswers.Confirmation)
}
}

func commentRun(opts *CommentOptions) error {
httpClient, err := opts.HttpClient()
if err != nil {
return err
}
apiClient := api.NewClientFromHTTP(httpClient)

issue, baseRepo, err := shared.IssueFromArg(apiClient, opts.BaseRepo, opts.SelectorArg)

if err != nil {
return err
}

isTerminal := opts.IO.IsStdoutTTY()

if isTerminal {
fmt.Fprintf(opts.IO.ErrOut, "\nMake a comment for %s in %s\n\n", issue.Title, ghrepo.FullName(baseRepo))
}

action := SubmitAction
body := opts.Body

if opts.Interactive {
editorCommand, err := cmdutil.DetermineEditor(opts.Config)
if err != nil {
return err
}

err = titleBodySurvey(editorCommand, opts, apiClient, baseRepo, body)

if err != nil {
return err
}

action = opts.Action
}

if action == CancelAction {
return nil
} else if action == SubmitAction {
params := map[string]interface{}{
"subjectId": issue.ID,
"body": opts.Body,
}

err = api.CommentCreate(apiClient, baseRepo.RepoHost(), params)
if err != nil {
return err
}

fmt.Fprintln(opts.IO.Out, issue.URL)

return nil
}
return fmt.Errorf("unexpected action state: %v", action)
}
117 changes: 117 additions & 0 deletions pkg/cmd/issue/comment/comment_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package comment
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will add more tests


import (
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
"reflect"
"regexp"
"testing"

"github.com/cli/cli/internal/config"
"github.com/cli/cli/internal/ghrepo"
"github.com/cli/cli/pkg/cmdutil"
"github.com/cli/cli/pkg/httpmock"
"github.com/cli/cli/pkg/iostreams"
"github.com/cli/cli/test"
"github.com/google/shlex"
)

func eq(t *testing.T, got interface{}, expected interface{}) {
t.Helper()
if !reflect.DeepEqual(got, expected) {
t.Errorf("expected: %v, got: %v", expected, got)
}
}
func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, error) {
io, _, stdout, stderr := iostreams.Test()
io.SetStdoutTTY(isTTY)
io.SetStdinTTY(isTTY)
io.SetStderrTTY(isTTY)

factory := &cmdutil.Factory{
IOStreams: io,
HttpClient: func() (*http.Client, error) {
return &http.Client{Transport: rt}, nil
},
Config: func() (config.Config, error) {
return config.NewBlankConfig(), nil
},
BaseRepo: func() (ghrepo.Interface, error) {
return ghrepo.New("OWNER", "REPO"), nil
},
}

cmd := NewCmdComment(factory, func(opts *CommentOptions) error {
return commentRun(opts)
})
argv, err := shlex.Split(cli)
if err != nil {
return nil, err
}
cmd.SetArgs(argv)

cmd.SetIn(&bytes.Buffer{})
cmd.SetOut(ioutil.Discard)
cmd.SetErr(ioutil.Discard)

_, err = cmd.ExecuteC()
return &test.CmdOut{
OutBuf: stdout,
ErrBuf: stderr,
}, err
}

func TestCommentCreate(t *testing.T) {
http := &httpmock.Registry{}
defer http.Verify(t)

http.StubResponse(200, bytes.NewBufferString(`
{ "data": { "repository": {
"hasIssuesEnabled": true,
"issue": { "number": 96, "title": "The title of the issue"}
} } }
`))

http.StubResponse(200, bytes.NewBufferString(`{"mutationId": "THE-ID"}`))

output, err := runCommand(http, true, `13 -b "cash rules everything around me"`)
if err != nil {
t.Errorf("error running command `issue comment`: %v", err)
}

bodyBytes, _ := ioutil.ReadAll(http.Requests[1].Body)
reqBody := struct {
Variables struct {
Input struct {
Body string
}
}
}{}
_ = json.Unmarshal(bodyBytes, &reqBody)

eq(t, reqBody.Variables.Input.Body, "cash rules everything around me")

r := regexp.MustCompile(`Make a comment for The title of the issue`)

if !r.MatchString(output.Stderr()) {
t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr())
}
}

func TestIssue_Disabled(t *testing.T) {
http := &httpmock.Registry{}
defer http.Verify(t)

http.StubResponse(200, bytes.NewBufferString(`
{ "data": { "repository": {
"hasIssuesEnabled": false
} } }
`))

_, err := runCommand(http, true, "13")
if err == nil || err.Error() != "the 'OWNER/REPO' repository has disabled issues" {
t.Fatalf("got error: %v", err)
}
}
2 changes: 2 additions & 0 deletions pkg/cmd/issue/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package issue
import (
"github.com/MakeNowJust/heredoc"
cmdClose "github.com/cli/cli/pkg/cmd/issue/close"
cmdComment "github.com/cli/cli/pkg/cmd/issue/comment"
cmdCreate "github.com/cli/cli/pkg/cmd/issue/create"
cmdList "github.com/cli/cli/pkg/cmd/issue/list"
cmdReopen "github.com/cli/cli/pkg/cmd/issue/reopen"
Expand Down Expand Up @@ -40,6 +41,7 @@ func NewCmdIssue(f *cmdutil.Factory) *cobra.Command {
cmd.AddCommand(cmdReopen.NewCmdReopen(f, nil))
cmd.AddCommand(cmdStatus.NewCmdStatus(f, nil))
cmd.AddCommand(cmdView.NewCmdView(f, nil))
cmd.AddCommand(cmdComment.NewCmdComment(f, nil))

return cmd
}