diff --git a/cmd/jira/main.go b/cmd/jira/main.go index 69b9912..7a6cd91 100644 --- a/cmd/jira/main.go +++ b/cmd/jira/main.go @@ -91,6 +91,10 @@ func main() { Command: "edit", Entry: cli.CmdEditRegistry(), }, + jiracli.CommandRegistry{ + Command: "comment", + Entry: cli.CmdCommentRegistry(), + }, jiracli.CommandRegistry{ Command: "worklog list", Entry: cli.CmdWorklogListRegistry(), diff --git a/issue.go b/issue.go index 918ee38..3214793 100644 --- a/issue.go +++ b/issue.go @@ -399,3 +399,28 @@ func (j *Jira) IssueRemoveWatcher(issue, user string) error { } return responseError(resp) } + +type CommentProvider interface { + ProvideComment() *jiradata.Comment +} + +// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/comment-addComment +func (j *Jira) IssueAddComment(issue string, cp CommentProvider) (*jiradata.Comment, error) { + req := cp.ProvideComment() + encoded, err := json.Marshal(req) + if err != nil { + return nil, err + } + uri := fmt.Sprintf("%s/rest/api/2/issue/%s/comment", j.Endpoint, issue) + resp, err := j.UA.Post(uri, "application/json", bytes.NewBuffer(encoded)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode == 201 { + results := jiradata.Comment{} + return &results, readJSON(resp.Body, &results) + } + return nil, responseError(resp) +} diff --git a/jiracli/comment.go b/jiracli/comment.go new file mode 100644 index 0000000..79fca80 --- /dev/null +++ b/jiracli/comment.go @@ -0,0 +1,70 @@ +package jiracli + +import ( + "fmt" + + "gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata" + kingpin "gopkg.in/alecthomas/kingpin.v2" +) + +type CommentOptions struct { + GlobalOptions + Overrides map[string]string + Issue string +} + +func (jc *JiraCli) CmdCommentRegistry() *CommandRegistryEntry { + opts := CommentOptions{ + GlobalOptions: GlobalOptions{ + Template: "comment", + }, + Overrides: map[string]string{}, + } + + return &CommandRegistryEntry{ + "Add comment to issue", + func() error { + return jc.CmdComment(&opts) + }, + func(cmd *kingpin.CmdClause) error { + return jc.CmdCommentUsage(cmd, &opts) + }, + } +} + +func (jc *JiraCli) CmdCommentUsage(cmd *kingpin.CmdClause, opts *CommentOptions) error { + if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil { + return err + } + jc.EditorUsage(cmd, &opts.GlobalOptions) + jc.TemplateUsage(cmd, &opts.GlobalOptions) + cmd.Flag("comment", "Comment message for issue").Short('m').PreAction(func(ctx *kingpin.ParseContext) error { + opts.Overrides["comment"] = flagValue(ctx, "comment") + return nil + }).String() + cmd.Arg("ISSUE", "issue id to update").StringVar(&opts.Issue) + return nil +} + +// CmdComment will update issue with comment +func (jc *JiraCli) CmdComment(opts *CommentOptions) error { + comment := jiradata.Comment{} + input := struct { + Overrides map[string]string + }{ + opts.Overrides, + } + err := jc.editLoop(&opts.GlobalOptions, &input, &comment, func() error { + _, err := jc.IssueAddComment(opts.Issue, &comment) + return err + }) + if err != nil { + return err + } + + fmt.Printf("OK %s %s/browse/%s\n", opts.Issue, jc.Endpoint, opts.Issue) + + // FIXME implement browse + + return nil +} diff --git a/jiradata/providers.go b/jiradata/providers.go index 1d36dda..a843f9d 100644 --- a/jiradata/providers.go +++ b/jiradata/providers.go @@ -17,3 +17,7 @@ func (l *LinkIssueRequest) ProvideLinkIssueRequest() *LinkIssueRequest { func (r *RankRequest) ProvideRankRequest() *RankRequest { return r } + +func (c *Comment) ProvideComment() *Comment { + return c +}