diff --git a/Makefile b/Makefile index 45bc2d2..ae4ce34 100644 --- a/Makefile +++ b/Makefile @@ -89,8 +89,8 @@ clean-password-store: rm -f "$(CWD)/_t/.password-store/GoJira/api-token:mothra@corybennett.org.gpg" test-password-store: - ln -s "$(CWD)/_t/.password-store/GoJira/api-token__gojira@corybennett.org.gpg" "$(CWD)/_t/.password-store/GoJira/api-token:gojira@corybennett.org.gpg" - ln -s "$(CWD)/_t/.password-store/GoJira/api-token__mothra@corybennett.org.gpg" "$(CWD)/_t/.password-store/GoJira/api-token:mothra@corybennett.org.gpg" + ln -s "api-token__gojira@corybennett.org.gpg" "$(CWD)/_t/.password-store/GoJira/api-token:gojira@corybennett.org.gpg" + ln -s "api-token__mothra@corybennett.org.gpg" "$(CWD)/_t/.password-store/GoJira/api-token:mothra@corybennett.org.gpg" prove: test-password-store chmod -R g-rwx,o-rwx $(CWD)/_t/.gnupg diff --git a/_t/101default.t b/_t/101default.t new file mode 100755 index 0000000..3ceac54 --- /dev/null +++ b/_t/101default.t @@ -0,0 +1,48 @@ +#!/bin/bash +eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)" +cd $(dirname $0) +jira="../jira" +. env.sh + +PLAN 6 + +# reset login +RUNS $jira logout +RUNS $jira login + +# cleanup from previous failed test executions +($jira ls --project BASIC | awk -F: '{print $1}' | while read issue; do ../jira done $issue; done) | sed 's/^/# CLEANUP: /g' + +############################################################################### +## Create an issue +############################################################################### +RUNS $jira create --project BASIC -o summary=summary -o description=description --noedit --saveFile issue.props +issue=$(awk '/issue/{print $2}' issue.props) + +DIFF < 1 { + return fmt.Sprintf("%s-%s", strings.ToUpper(parts[0]), parts[1]) + } + + // if issue is not PROJ-1234 then it might just be 1234, so verify + // it is a number here otherwise warn and return input + if _, err := strconv.Atoi(issueKey); err != nil { + log.Warningf("Unexpected issue format %q, expected PROJ-1234", issueKey) + return issueKey + } + + if project == "" { + log.Warningf("Using abbreviated issue %q but `project` property is not defined", issueKey) + return issueKey + } + + return fmt.Sprintf("%s-%s", strings.ToUpper(project), issueKey) +} diff --git a/jiracli/password.go b/jiracli/password.go index 2a083eb..b1028e5 100644 --- a/jiracli/password.go +++ b/jiracli/password.go @@ -42,8 +42,10 @@ func (o *GlobalOptions) keyName() string { } func (o *GlobalOptions) GetPass() string { + log.Debugf("Getting Password") passwd := "" if o.PasswordSource.Value != "" { + log.Debugf("password-source: %s", o.PasswordSource) if o.PasswordSource.Value == "keyring" { var err error passwd, err = keyringGet(o.keyName()) @@ -53,18 +55,23 @@ func (o *GlobalOptions) GetPass() string { } else if o.PasswordSource.Value == "gopass" { if o.PasswordDirectory.Value != "" { orig := os.Getenv("PASSWORD_STORE_DIR") + log.Debugf("using password-directory: %s", o.PasswordDirectory) os.Setenv("PASSWORD_STORE_DIR", o.PasswordDirectory.Value) defer os.Setenv("PASSWORD_STORE_DIR", orig) } + if passDir := os.Getenv("PASSWORD_STORE_DIR"); passDir != "" { + log.Debugf("using PASSWORD_STORE_DIR=%s", passDir) + } if bin, err := exec.LookPath("gopass"); err == nil { + log.Debugf("found gopass at: %s", bin) buf := bytes.NewBufferString("") cmd := exec.Command(bin, "show", "-o", o.keyName()) cmd.Stdout = buf - cmd.Stderr = buf + cmd.Stderr = os.Stderr if err := cmd.Run(); err == nil { passwd = strings.TrimSpace(buf.String()) } else { - panic(err) + log.Warningf("gopass command failed with:\n%s", buf.String()) } } else { log.Warning("Gopass binary was not found! Fallback to default password behaviour!") @@ -72,21 +79,26 @@ func (o *GlobalOptions) GetPass() string { } else if o.PasswordSource.Value == "pass" { if o.PasswordDirectory.Value != "" { orig := os.Getenv("PASSWORD_STORE_DIR") + log.Debugf("using password-directory: %s", o.PasswordDirectory) os.Setenv("PASSWORD_STORE_DIR", o.PasswordDirectory.Value) defer os.Setenv("PASSWORD_STORE_DIR", orig) } + if passDir := os.Getenv("PASSWORD_STORE_DIR"); passDir != "" { + log.Debugf("using PASSWORD_STORE_DIR=%s", passDir) + } if bin, err := exec.LookPath("pass"); err == nil { + log.Debugf("found pass at: %s", bin) buf := bytes.NewBufferString("") cmd := exec.Command(bin, o.keyName()) cmd.Stdout = buf - cmd.Stderr = buf + cmd.Stderr = os.Stderr if err := cmd.Run(); err == nil { passwd = strings.TrimSpace(buf.String()) } else { - panic(err) + log.Warningf("pass command failed with:\n%s", buf.String()) } } else { - log.Warning("Pass binary was not found! Fallback to default password behaviour!") + log.Warning("pass binary was not found! Fallback to default password behaviour!") } } else if o.PasswordSource.Value == "stdin" { allBytes, err := ioutil.ReadAll(os.Stdin) @@ -132,6 +144,11 @@ func (o *GlobalOptions) GetPass() string { } func (o *GlobalOptions) SetPass(passwd string) error { + // dont reset password to empty string + if passwd == "" { + return nil + } + if o.PasswordSource.Value == "keyring" { // save password in keychain so that it can be used for subsequent http requests err := keyringSet(o.keyName(), passwd) @@ -158,11 +175,6 @@ func (o *GlobalOptions) SetPass(passwd string) error { if err := cmd.Run(); err != nil { return fmt.Errorf("Failed to insert password: %s", out.String()) } - } else { - // clear the `pass` entry on empty password - if err := exec.Command(bin, "rm", "--force", passName).Run(); err != nil { - return fmt.Errorf("Failed to clear password for %s", passName) - } } } else { return fmt.Errorf("Gopass binary not found!") @@ -176,21 +188,14 @@ func (o *GlobalOptions) SetPass(passwd string) error { if bin, err := exec.LookPath("pass"); err == nil { log.Debugf("using %s", bin) passName := o.keyName() - if passwd != "" { - in := bytes.NewBufferString(fmt.Sprintf("%s\n%s\n", passwd, passwd)) - out := bytes.NewBufferString("") - cmd := exec.Command(bin, "insert", "--force", passName) - cmd.Stdin = in - cmd.Stdout = out - cmd.Stderr = out - if err := cmd.Run(); err != nil { - return fmt.Errorf("Failed to insert password: %s", out.String()) - } - } else { - // clear the `pass` entry on empty password - if err := exec.Command(bin, "rm", "--force", passName).Run(); err != nil { - return fmt.Errorf("Failed to clear password for %s", passName) - } + in := bytes.NewBufferString(fmt.Sprintf("%s\n%s\n", passwd, passwd)) + out := bytes.NewBufferString("") + cmd := exec.Command(bin, "insert", "--force", passName) + cmd.Stdin = in + cmd.Stdout = out + cmd.Stderr = out + if err := cmd.Run(); err != nil { + return fmt.Errorf("Failed to insert password: %s", out.String()) } } else { return fmt.Errorf("Pass binary not found!") diff --git a/jiracli/usage.go b/jiracli/usage.go index f684df5..a75f8d5 100644 --- a/jiracli/usage.go +++ b/jiracli/usage.go @@ -173,7 +173,7 @@ func ParseCommandLine(app *kingpin.Application, args []string) { if ctx.SelectedCommand == nil { next := ctx.Next() if next != nil { - if ok, err := regexp.MatchString("^[A-Z]+-[0-9]+$", next.Value); err != nil { + if ok, err := regexp.MatchString("^([A-Z]+-)?[0-9]+$", next.Value); err != nil { log.Errorf("Invalid Regex: %s", err) } else if ok { // insert "view" at i=1 (2nd position) diff --git a/jiracmd/assign.go b/jiracmd/assign.go index 268ddad..a33531e 100644 --- a/jiracmd/assign.go +++ b/jiracmd/assign.go @@ -12,6 +12,7 @@ import ( type AssignOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` Assignee string `yaml:"assignee,omitempty" json:"assignee,omitempty"` } @@ -26,6 +27,7 @@ func CmdAssignRegistry() *jiracli.CommandRegistryEntry { return CmdAssignUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdAssign(o, globals, &opts) }, } diff --git a/jiracmd/attachCreate.go b/jiracmd/attachCreate.go index e079203..bd40af9 100644 --- a/jiracmd/attachCreate.go +++ b/jiracmd/attachCreate.go @@ -17,6 +17,7 @@ import ( type AttachCreateOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` Attachment string `yaml:"attachment,omitempty" json:"attachment,omitempty"` Filename string `yaml:"filename,omitempty" json:"filename,omitempty"` @@ -33,6 +34,7 @@ func CmdAttachCreateRegistry() *jiracli.CommandRegistryEntry { return CmdAttachCreateUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdAttachCreate(o, globals, &opts) }, } diff --git a/jiracmd/attachList.go b/jiracmd/attachList.go index 6ee8ceb..5099394 100644 --- a/jiracmd/attachList.go +++ b/jiracmd/attachList.go @@ -13,6 +13,7 @@ import ( type AttachListOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` } @@ -30,6 +31,7 @@ func CmdAttachListRegistry() *jiracli.CommandRegistryEntry { return CmdAttachListUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdAttachList(o, globals, &opts) }, } diff --git a/jiracmd/block.go b/jiracmd/block.go index 14fe0fc..ba2faa1 100644 --- a/jiracmd/block.go +++ b/jiracmd/block.go @@ -15,6 +15,7 @@ import ( type BlockOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` jiradata.LinkIssueRequest `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` } func CmdBlockRegistry() *jiracli.CommandRegistryEntry { @@ -38,6 +39,8 @@ func CmdBlockRegistry() *jiracli.CommandRegistryEntry { return CmdBlockUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.OutwardIssue.Key = jiracli.FormatIssue(opts.OutwardIssue.Key, opts.Project) + opts.InwardIssue.Key = jiracli.FormatIssue(opts.InwardIssue.Key, opts.Project) return CmdBlock(o, globals, &opts) }, } diff --git a/jiracmd/browse.go b/jiracmd/browse.go index 24d29cb..e5796be 100644 --- a/jiracmd/browse.go +++ b/jiracmd/browse.go @@ -9,17 +9,23 @@ import ( kingpin "gopkg.in/alecthomas/kingpin.v2" ) +type BrowseOptions struct { + Project string `yaml:"project,omitempty" json:"project,omitempty"` + Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` +} + func CmdBrowseRegistry() *jiracli.CommandRegistryEntry { - issue := "" + opts := BrowseOptions{} return &jiracli.CommandRegistryEntry{ "Open issue in browser", func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error { - cmd.Arg("ISSUE", "Issue to browse to").Required().StringVar(&issue) + cmd.Arg("ISSUE", "Issue to browse to").Required().StringVar(&opts.Issue) return nil }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { - return CmdBrowse(globals, issue) + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) + return CmdBrowse(globals, opts.Issue) }, } } diff --git a/jiracmd/comment.go b/jiracmd/comment.go index f12ed01..9900b82 100644 --- a/jiracmd/comment.go +++ b/jiracmd/comment.go @@ -14,6 +14,7 @@ import ( type CommentOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Overrides map[string]string `yaml:"overrides,omitempty" json:"overrides,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` } @@ -33,6 +34,7 @@ func CmdCommentRegistry() *jiracli.CommandRegistryEntry { return CmdCommentUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdComment(o, globals, &opts) }, } diff --git a/jiracmd/dup.go b/jiracmd/dup.go index dc84b2a..f2cd8c4 100644 --- a/jiracmd/dup.go +++ b/jiracmd/dup.go @@ -15,8 +15,7 @@ import ( type DupOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` jiradata.LinkIssueRequest `yaml:",inline" json:",inline" figtree:",inline"` - Duplicate string `yaml:"duplicate,omitempty" json:"duplicate,omitempty"` - Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` } func CmdDupRegistry() *jiracli.CommandRegistryEntry { @@ -40,6 +39,8 @@ func CmdDupRegistry() *jiracli.CommandRegistryEntry { return CmdDupUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.OutwardIssue.Key = jiracli.FormatIssue(opts.OutwardIssue.Key, opts.Project) + opts.InwardIssue.Key = jiracli.FormatIssue(opts.InwardIssue.Key, opts.Project) return CmdDup(o, globals, &opts) }, } diff --git a/jiracmd/edit.go b/jiracmd/edit.go index 4f411a4..f7b5c7c 100644 --- a/jiracmd/edit.go +++ b/jiracmd/edit.go @@ -36,6 +36,7 @@ func CmdEditRegistry() *jiracli.CommandRegistryEntry { return CmdEditUsage(cmd, &opts, fig) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) if opts.QueryFields == "" { opts.QueryFields = "assignee,created,priority,reporter,status,summary,updated,issuetype,comment,description,votes,created,customfield_10110,components" } diff --git a/jiracmd/editmeta.go b/jiracmd/editmeta.go index 8716acb..019c363 100644 --- a/jiracmd/editmeta.go +++ b/jiracmd/editmeta.go @@ -10,6 +10,7 @@ import ( type EditMetaOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` } @@ -28,6 +29,7 @@ func CmdEditMetaRegistry() *jiracli.CommandRegistryEntry { return CmdEditMetaUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdEditMeta(o, globals, &opts) }, } diff --git a/jiracmd/epicAdd.go b/jiracmd/epicAdd.go index 90bf415..73200d0 100644 --- a/jiracmd/epicAdd.go +++ b/jiracmd/epicAdd.go @@ -14,6 +14,7 @@ import ( type EpicAddOptions struct { jiradata.EpicIssues `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Epic string `yaml:"epic,omitempty" json:"epic,omitempty"` } @@ -27,6 +28,10 @@ func CmdEpicAddRegistry() *jiracli.CommandRegistryEntry { return CmdEpicAddUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Epic = jiracli.FormatIssue(opts.Epic, opts.Project) + for i := range opts.Issues { + opts.Issues[i] = jiracli.FormatIssue(opts.Issues[i], opts.Project) + } return CmdEpicAdd(o, globals, &opts) }, } diff --git a/jiracmd/epicList.go b/jiracmd/epicList.go index 46b1653..2c8644f 100644 --- a/jiracmd/epicList.go +++ b/jiracmd/epicList.go @@ -29,6 +29,7 @@ func CmdEpicListRegistry() *jiracli.CommandRegistryEntry { return CmdEpicListUsage(cmd, &opts, fig) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Epic = jiracli.FormatIssue(opts.Epic, opts.Project) if opts.MaxResults == 0 { opts.MaxResults = 500 } diff --git a/jiracmd/epicRemove.go b/jiracmd/epicRemove.go index 8a3596c..70a1e98 100644 --- a/jiracmd/epicRemove.go +++ b/jiracmd/epicRemove.go @@ -14,6 +14,7 @@ import ( type EpicRemoveOptions struct { jiradata.EpicIssues `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` } func CmdEpicRemoveRegistry() *jiracli.CommandRegistryEntry { @@ -26,6 +27,9 @@ func CmdEpicRemoveRegistry() *jiracli.CommandRegistryEntry { return CmdEpicRemoveUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + for i := range opts.Issues { + opts.Issues[i] = jiracli.FormatIssue(opts.Issues[i], opts.Project) + } return CmdEpicRemove(o, globals, &opts) }, } diff --git a/jiracmd/issuelink.go b/jiracmd/issuelink.go index fb657b4..60f64a2 100644 --- a/jiracmd/issuelink.go +++ b/jiracmd/issuelink.go @@ -16,6 +16,7 @@ type IssueLinkOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` jiradata.LinkIssueRequest `yaml:",inline" json:",inline" figtree:",inline"` LinkType string `yaml:"linktype,omitempty" json:"linktype,omitempty"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` } func CmdIssueLinkRegistry() *jiracli.CommandRegistryEntry { @@ -33,6 +34,8 @@ func CmdIssueLinkRegistry() *jiracli.CommandRegistryEntry { return CmdIssueLinkUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.OutwardIssue.Key = jiracli.FormatIssue(opts.OutwardIssue.Key, opts.Project) + opts.InwardIssue.Key = jiracli.FormatIssue(opts.InwardIssue.Key, opts.Project) return CmdIssueLink(o, globals, &opts) }, } diff --git a/jiracmd/labelsAdd.go b/jiracmd/labelsAdd.go index 4a550b6..b3ab348 100644 --- a/jiracmd/labelsAdd.go +++ b/jiracmd/labelsAdd.go @@ -14,6 +14,7 @@ import ( type LabelsAddOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` Labels []string `yaml:"labels,omitempty" json:"labels,omitempty"` } @@ -27,6 +28,7 @@ func CmdLabelsAddRegistry() *jiracli.CommandRegistryEntry { return CmdLabelsAddUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdLabelsAdd(o, globals, &opts) }, } diff --git a/jiracmd/labelsRemove.go b/jiracmd/labelsRemove.go index b7d77de..4fbfe66 100644 --- a/jiracmd/labelsRemove.go +++ b/jiracmd/labelsRemove.go @@ -14,6 +14,7 @@ import ( type LabelsRemoveOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` Labels []string `yaml:"labels,omitempty" json:"labels,omitempty"` } @@ -27,6 +28,7 @@ func CmdLabelsRemoveRegistry() *jiracli.CommandRegistryEntry { return CmdLabelsRemoveUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdLabelsRemove(o, globals, &opts) }, } diff --git a/jiracmd/labelsSet.go b/jiracmd/labelsSet.go index bda93d5..2f098ab 100644 --- a/jiracmd/labelsSet.go +++ b/jiracmd/labelsSet.go @@ -14,6 +14,7 @@ import ( type LabelsSetOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` Labels []string `yaml:"labels,omitempty" json:"labels,omitempty"` } @@ -27,6 +28,7 @@ func CmdLabelsSetRegistry() *jiracli.CommandRegistryEntry { return CmdLabelsSetUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdLabelsSet(o, globals, &opts) }, } diff --git a/jiracmd/rank.go b/jiracmd/rank.go index 29f6e5f..2a17dc4 100644 --- a/jiracmd/rank.go +++ b/jiracmd/rank.go @@ -14,6 +14,7 @@ import ( type RankOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` First string `yaml:"first,omitempty" json:"first,omitempty"` Second string `yaml:"second,omitempty" json:"second,omitempty"` Order string `yaml:"order,omitempty" json:"order,omitempty"` @@ -29,6 +30,8 @@ func CmdRankRegistry() *jiracli.CommandRegistryEntry { return CmdRankUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.First = jiracli.FormatIssue(opts.First, opts.Project) + opts.Second = jiracli.FormatIssue(opts.Second, opts.Project) return CmdRank(o, globals, &opts) }, } diff --git a/jiracmd/subtask.go b/jiracmd/subtask.go index ad3495b..75875f1 100644 --- a/jiracmd/subtask.go +++ b/jiracmd/subtask.go @@ -36,6 +36,7 @@ func CmdSubtaskRegistry() *jiracli.CommandRegistryEntry { return CmdSubtaskUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) if opts.IssueType == "" { opts.IssueType = "Sub-task" } diff --git a/jiracmd/take.go b/jiracmd/take.go index 85f8ed6..646ce46 100644 --- a/jiracmd/take.go +++ b/jiracmd/take.go @@ -17,6 +17,7 @@ func CmdTakeRegistry() *jiracli.CommandRegistryEntry { return CmdAssignUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) if opts.Assignee == "" { opts.Assignee = globals.User.Value } diff --git a/jiracmd/transition.go b/jiracmd/transition.go index c363571..85200de 100644 --- a/jiracmd/transition.go +++ b/jiracmd/transition.go @@ -15,6 +15,7 @@ import ( type TransitionOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Overrides map[string]string `yaml:"overrides,omitempty" json:"overrides,omitempty"` Transition string `yaml:"transition,omitempty" json:"transition,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` @@ -45,6 +46,7 @@ func CmdTransitionRegistry(transition string) *jiracli.CommandRegistryEntry { return CmdTransitionUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdTransition(o, globals, &opts) }, } diff --git a/jiracmd/transitions.go b/jiracmd/transitions.go index 2c7c9f6..c0a7915 100644 --- a/jiracmd/transitions.go +++ b/jiracmd/transitions.go @@ -10,6 +10,7 @@ import ( type TransitionsOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` } @@ -27,6 +28,7 @@ func CmdTransitionsRegistry(defaultTemplate string) *jiracli.CommandRegistryEntr return CmdTransitionsUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdTransitions(o, globals, &opts) }, } diff --git a/jiracmd/unassign.go b/jiracmd/unassign.go index 1c99b91..d00b356 100644 --- a/jiracmd/unassign.go +++ b/jiracmd/unassign.go @@ -17,6 +17,7 @@ func CmdUnassignRegistry() *jiracli.CommandRegistryEntry { return CmdAssignUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdAssign(o, globals, &opts) }, } diff --git a/jiracmd/view.go b/jiracmd/view.go index 0b218c2..6a5b4d8 100644 --- a/jiracmd/view.go +++ b/jiracmd/view.go @@ -11,6 +11,7 @@ import ( type ViewOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` jira.IssueOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` } @@ -28,6 +29,7 @@ func CmdViewRegistry() *jiracli.CommandRegistryEntry { return CmdViewUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdView(o, globals, &opts) }, } diff --git a/jiracmd/vote.go b/jiracmd/vote.go index 900145e..0996677 100644 --- a/jiracmd/vote.go +++ b/jiracmd/vote.go @@ -20,6 +20,7 @@ const ( type VoteOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` Action VoteAction `yaml:"-" json:"-"` } @@ -37,6 +38,7 @@ func CmdVoteRegistry() *jiracli.CommandRegistryEntry { return CmdVoteUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdVote(o, globals, &opts) }, } diff --git a/jiracmd/watch.go b/jiracmd/watch.go index 52d6b16..27616c5 100644 --- a/jiracmd/watch.go +++ b/jiracmd/watch.go @@ -20,6 +20,7 @@ const ( type WatchOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` Watcher string `yaml:"watcher,omitempty" json:"watcher,omitempty"` Action WatchAction `yaml:"-" json:"-"` @@ -38,6 +39,7 @@ func CmdWatchRegistry() *jiracli.CommandRegistryEntry { return CmdWatchUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdWatch(o, globals, &opts) }, } diff --git a/jiracmd/worklogAdd.go b/jiracmd/worklogAdd.go index eea7799..7653555 100644 --- a/jiracmd/worklogAdd.go +++ b/jiracmd/worklogAdd.go @@ -14,6 +14,7 @@ import ( type WorklogAddOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` jiradata.Worklog `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` } @@ -30,6 +31,7 @@ func CmdWorklogAddRegistry() *jiracli.CommandRegistryEntry { return CmdWorklogAddUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdWorklogAdd(o, globals, &opts) }, } diff --git a/jiracmd/worklogList.go b/jiracmd/worklogList.go index e000479..11057e6 100644 --- a/jiracmd/worklogList.go +++ b/jiracmd/worklogList.go @@ -11,6 +11,7 @@ import ( type WorklogListOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` + Project string `yaml:"project,omitempty" json:"project,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` } @@ -27,6 +28,7 @@ func CmdWorklogListRegistry() *jiracli.CommandRegistryEntry { return CmdWorklogListUsage(cmd, &opts) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) return CmdWorklogList(o, globals, &opts) }, }