From aacc9f44e419bd838dfc0b2dc286e9e10dd693de Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sun, 13 Aug 2017 22:11:06 -0700 Subject: [PATCH] add `issuelink` command --- cmd/jira/main.go | 98 ++------------------------------------------ jiracli/block.go | 23 +++++------ jiracli/dup.go | 31 +++++++------- jiracli/issuelink.go | 69 +++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 124 deletions(-) create mode 100644 jiracli/issuelink.go diff --git a/cmd/jira/main.go b/cmd/jira/main.go index c26bde67..c52b0439 100644 --- a/cmd/jira/main.go +++ b/cmd/jira/main.go @@ -124,6 +124,10 @@ func main() { Command: "block", Entry: cli.CmdBlockRegistry(), }, + jiracli.CommandRegistry{ + Command: "issuelink", + Entry: cli.CmdIssueLinkRegistry(), + }, jiracli.CommandRegistry{ Command: "transition", Aliases: []string{"trans"}, @@ -217,8 +221,6 @@ func main() { // } // output := fmt.Sprintf(` // Usage: - // jira BLOCKER blocks ISSUE - // jira issuelink OUTWARDISSUE ISSUELINKTYPE INWARDISSUE // jira vote ISSUE [--down] // jira rank ISSUE (after|before) ISSUE // jira watch ISSUE [-w WATCHER] [--remove] @@ -285,8 +287,6 @@ func main() { // } // jiraCommands := map[string]string{ - // "blocks": "blocks", - // "issuelink": "issuelink", // "watch": "watch", // "comment": "comment", // "label": "labels", @@ -456,93 +456,15 @@ func main() { // var err error // switch command { - // case "issuelink": - // requireArgs(3) - // err = c.CmdIssueLink(args[0], args[1], args[2]) - // case "login": - // err = c.CmdLogin() - // case "logout": - // err = c.CmdLogout() - // case "fields": - // err = c.CmdFields() - // case "list": - // err = c.CmdList() - // case "edit": - // setEditing(true) - // if len(args) > 0 { - // err = c.CmdEdit(args[0]) - // } else { - // var data interface{} - // if data, err = c.FindIssues(); err == nil { - // issues := data.(map[string]interface{})["issues"].([]interface{}) - // for _, issue := range issues { - // if err = c.CmdEdit(issue.(map[string]interface{})["key"].(string)); err != nil { - // switch err.(type) { - // case jira.NoChangesFound: - // log.Warning("No Changes found: %s", err) - // err = nil - // continue - // } - // break - // } - // } - // } - // } - // case "editmeta": - // requireArgs(1) - // err = c.CmdEditMeta(args[0]) - // case "transmeta": - // requireArgs(1) - // err = c.CmdTransitionMeta(args[0]) // case "issuelinktypes": // err = c.CmdIssueLinkTypes() // case "issuetypes": // err = c.CmdIssueTypes() - // case "createmeta": - // err = c.CmdCreateMeta() - // case "create": - // setEditing(true) - // err = c.CmdCreate() - // case "subtask": - // setEditing(true) - // err = c.CmdSubtask(args[0]) - // case "transitions": - // requireArgs(1) - // err = c.CmdTransitions(args[0]) - // case "blocks": - // requireArgs(2) - // err = c.CmdBlocks(args[0], args[1]) - // case "dups": - // setEditing(true) - // requireArgs(2) - // if err = c.CmdDups(args[0], args[1]); err == nil { - // opts["resolution"] = "Duplicate" - // trans, err := c.ValidTransitions(args[0]) - // if err == nil { - // if trans.Find("close") != nil { - // err = c.CmdTransition(args[0], "close") - // } else if trans.Find("done") != nil { - // // for now just assume if there is no "close", then - // // there is a "done" state - // err = c.CmdTransition(args[0], "done") - // } else if trans.Find("start") != nil { - // err = c.CmdTransition(args[0], "start") - // if err == nil { - // err = c.CmdTransition(args[0], "stop") - // } - // } - // } - - // } // case "watch": // requireArgs(1) // watcher := c.GetOptString("watcher", opts["user"].(string)) // remove := c.GetOptBool("remove", false) // err = c.CmdWatch(args[0], watcher, remove) - // case "transition": - // requireArgs(2) - // setEditing(true) - // err = c.CmdTransition(args[1], args[0]) // case "comment": // requireArgs(1) // setEditing(true) @@ -589,18 +511,6 @@ func main() { // case "unassign": // requireArgs(1) // err = c.CmdUnassign(args[0]) - // case "view": - // requireArgs(1) - // err = c.CmdView(args[0]) - // case "worklog": - // if len(args) > 0 && args[0] == "add" { - // setEditing(true) - // requireArgs(2) - // err = c.CmdWorklog(args[0], args[1]) - // } else { - // requireArgs(1) - // err = c.CmdWorklogs(args[0]) - // } // case "vote": // requireArgs(1) // if val, ok := opts["down"]; ok { diff --git a/jiracli/block.go b/jiracli/block.go index e03f82c0..e5d339bb 100644 --- a/jiracli/block.go +++ b/jiracli/block.go @@ -19,6 +19,14 @@ func (jc *JiraCli) CmdBlockRegistry() *CommandRegistryEntry { GlobalOptions: GlobalOptions{ Template: "edit", }, + LinkIssueRequest: jiradata.LinkIssueRequest{ + Type: &jiradata.IssueLinkType{ + // FIXME is this consitent across multiple jira installs? + Name: "Blocks", + }, + InwardIssue: &jiradata.IssueRef{}, + OutwardIssue: &jiradata.IssueRef{}, + }, } return &CommandRegistryEntry{ @@ -44,25 +52,14 @@ func (jc *JiraCli) CmdBlockUsage(cmd *kingpin.CmdClause, opts *BlockOptions) err } return nil }).String() - cmd.Arg("BLOCKER", "blocker issue").Required().StringVar(&opts.Blocker) - cmd.Arg("ISSUE", "issue that is blocked").Required().StringVar(&opts.Issue) + cmd.Arg("BLOCKER", "blocker issue").Required().StringVar(&opts.OutwardIssue.Key) + cmd.Arg("ISSUE", "issue that is blocked").Required().StringVar(&opts.InwardIssue.Key) return nil } // CmdBlock will update the given issue as being a duplicate by the given dup issue // and will attempt to resolve the dup issue func (jc *JiraCli) CmdBlock(opts *BlockOptions) error { - opts.Type = &jiradata.IssueLinkType{ - // FIXME is this consitent across multiple jira installs? - Name: "Blocks", - } - opts.InwardIssue = &jiradata.IssueRef{ - Key: opts.Issue, - } - opts.OutwardIssue = &jiradata.IssueRef{ - Key: opts.Blocker, - } - if err := jc.LinkIssues(&opts.LinkIssueRequest); err != nil { return err } diff --git a/jiracli/dup.go b/jiracli/dup.go index 40c7a704..f35ada4a 100644 --- a/jiracli/dup.go +++ b/jiracli/dup.go @@ -19,6 +19,14 @@ func (jc *JiraCli) CmdDupRegistry() *CommandRegistryEntry { GlobalOptions: GlobalOptions{ Template: "edit", }, + LinkIssueRequest: jiradata.LinkIssueRequest{ + Type: &jiradata.IssueLinkType{ + // FIXME is this consitent across multiple jira installs? + Name: "Duplicate", + }, + InwardIssue: &jiradata.IssueRef{}, + OutwardIssue: &jiradata.IssueRef{}, + }, } return &CommandRegistryEntry{ @@ -44,31 +52,20 @@ func (jc *JiraCli) CmdDupUsage(cmd *kingpin.CmdClause, opts *DupOptions) error { } return nil }).String() - cmd.Arg("DUPLICATE", "duplicate issue to mark closed").Required().StringVar(&opts.Duplicate) - cmd.Arg("ISSUE", "duplicate issue to leave open").Required().StringVar(&opts.Issue) + cmd.Arg("DUPLICATE", "duplicate issue to mark closed").Required().StringVar(&opts.InwardIssue.Key) + cmd.Arg("ISSUE", "duplicate issue to leave open").Required().StringVar(&opts.OutwardIssue.Key) return nil } // CmdDups will update the given issue as being a duplicate by the given dup issue // and will attempt to resolve the dup issue func (jc *JiraCli) CmdDup(opts *DupOptions) error { - opts.Type = &jiradata.IssueLinkType{ - // FIXME is this consitent across multiple jira installs? - Name: "Duplicate", - } - opts.InwardIssue = &jiradata.IssueRef{ - Key: opts.Duplicate, - } - opts.OutwardIssue = &jiradata.IssueRef{ - Key: opts.Issue, - } - if err := jc.LinkIssues(&opts.LinkIssueRequest); err != nil { return err } - fmt.Printf("OK %s %s/browse/%s\n", opts.Issue, jc.Endpoint, opts.Issue) + fmt.Printf("OK %s %s/browse/%s\n", opts.OutwardIssue.Key, jc.Endpoint, opts.OutwardIssue.Key) - meta, err := jc.GetIssueTransitions(opts.Duplicate) + meta, err := jc.GetIssueTransitions(opts.InwardIssue.Key) if err != nil { return err } @@ -78,7 +75,7 @@ func (jc *JiraCli) CmdDup(opts *DupOptions) error { issueUpdate := jiradata.IssueUpdate{ Transition: transMeta, } - if err = jc.TransitionIssue(opts.Duplicate, &issueUpdate); err != nil { + if err = jc.TransitionIssue(opts.InwardIssue.Key, &issueUpdate); err != nil { return err } // if we just started the issue now we need to stop it @@ -88,7 +85,7 @@ func (jc *JiraCli) CmdDup(opts *DupOptions) error { } } - fmt.Printf("OK %s %s/browse/%s\n", opts.Duplicate, jc.Endpoint, opts.Duplicate) + fmt.Printf("OK %s %s/browse/%s\n", opts.InwardIssue.Key, jc.Endpoint, opts.InwardIssue.Key) // FIXME implement browse diff --git a/jiracli/issuelink.go b/jiracli/issuelink.go new file mode 100644 index 00000000..06514aab --- /dev/null +++ b/jiracli/issuelink.go @@ -0,0 +1,69 @@ +package jiracli + +import ( + "fmt" + + "gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata" + kingpin "gopkg.in/alecthomas/kingpin.v2" +) + +type IssueLinkOptions struct { + GlobalOptions + jiradata.LinkIssueRequest + LinkType string +} + +func (jc *JiraCli) CmdIssueLinkRegistry() *CommandRegistryEntry { + opts := IssueLinkOptions{ + GlobalOptions: GlobalOptions{ + Template: "edit", + }, + LinkIssueRequest: jiradata.LinkIssueRequest{ + Type: &jiradata.IssueLinkType{}, + InwardIssue: &jiradata.IssueRef{}, + OutwardIssue: &jiradata.IssueRef{}, + }, + } + return &CommandRegistryEntry{ + "Link two issues", + func() error { + return jc.CmdIssueLink(&opts) + }, + func(cmd *kingpin.CmdClause) error { + return jc.CmdIssueLinkUsage(cmd, &opts) + }, + } +} + +func (jc *JiraCli) CmdIssueLinkUsage(cmd *kingpin.CmdClause, opts *IssueLinkOptions) 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 when linking issue").Short('m').PreAction(func(ctx *kingpin.ParseContext) error { + opts.Comment = &jiradata.Comment{ + Body: flagValue(ctx, "comment"), + } + return nil + }).String() + cmd.Arg("OUTWARDISSUE", "outward issue").Required().StringVar(&opts.OutwardIssue.Key) + cmd.Arg("ISSUELINKTYPE", "issue link type").Required().StringVar(&opts.Type.Name) + cmd.Arg("INWARDISSUE", "inward issue").Required().StringVar(&opts.InwardIssue.Key) + return nil +} + +// CmdBlock will update the given issue as being a duplicate by the given dup issue +// and will attempt to resolve the dup issue +func (jc *JiraCli) CmdIssueLink(opts *IssueLinkOptions) error { + if err := jc.LinkIssues(&opts.LinkIssueRequest); err != nil { + return err + } + + fmt.Printf("OK %s %s/browse/%s\n", opts.InwardIssue.Key, jc.Endpoint, opts.InwardIssue.Key) + fmt.Printf("OK %s %s/browse/%s\n", opts.OutwardIssue.Key, jc.Endpoint, opts.OutwardIssue.Key) + + // FIXME implement browse + + return nil +}