From 98c797d4f587920742aa894a35b1ad578f6abe4b Mon Sep 17 00:00:00 2001 From: Denys Vitali Date: Mon, 18 Jan 2021 19:16:35 +0100 Subject: [PATCH 1/2] feat: add fromFile in create --- go.mod | 2 +- go.sum | 3 +-- jiracmd/create.go | 50 +++++++++++++++++++++++++++++++++++------------ 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 9cca9267..bf4ef945 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/imdario/mergo v0.3.7 // indirect github.com/jinzhu/copier v0.0.0-20180308034124-7e38e58719c3 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 - github.com/kr/pretty v0.1.0 + github.com/kr/pretty v0.1.0 // indirect github.com/kr/pty v1.1.4 // indirect github.com/mattn/go-colorable v0.0.9 // indirect github.com/mattn/go-isatty v0.0.3 // indirect diff --git a/go.sum b/go.sum index cfa3b479..84efd8b5 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,6 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZq github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= -github.com/coryb/figtree v0.0.0-20180728224503-071d1ef303df h1:cS4Z9Nlv8J4UqFbLp9ltZypgenm2p3Jeg0yqLfpH2pc= -github.com/coryb/figtree v0.0.0-20180728224503-071d1ef303df/go.mod h1:uAkZUEGm6dROpxfy+8vXLs7JrLCI4O+gQyKAuISxI/g= github.com/coryb/figtree v1.0.1-0.20190907170512-58176d03ef0d h1:99xxg8FYj+5TYg88DxA4xL8ODuI6OvuSu35WQOVPDPg= github.com/coryb/figtree v1.0.1-0.20190907170512-58176d03ef0d/go.mod h1:uAkZUEGm6dROpxfy+8vXLs7JrLCI4O+gQyKAuISxI/g= github.com/coryb/kingpeon v0.0.0-20180107011214-9a669f143f2e h1:tGmk9Tuyz7fKuBq/d3nFJvVWRvc48MEBKQC4uYV3wb0= @@ -81,6 +79,7 @@ golang.org/x/net v0.0.0-20171102191033-01c190206fbd h1:CLQSRrSDQMOMkogMxky7XOkER golang.org/x/net v0.0.0-20171102191033-01c190206fbd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/sys v0.0.0-20180727230415-bd9dbc187b6e h1:3dQ4fR8k5KugjVKO0oqSd1odxuk2yaE2CIfxWP2WarQ= golang.org/x/sys v0.0.0-20180727230415-bd9dbc187b6e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/AlecAivazis/survey.v1 v1.6.1 h1:HyWkjKGBpzhNxrpaKRLDqoa4L1f4cMVBNU4bnVmU8Mw= gopkg.in/AlecAivazis/survey.v1 v1.6.1/go.mod h1:2Ehl7OqkBl3Xb8VmC4oFW2bItAhnUfzIjrOzwRxCrOU= diff --git a/jiracmd/create.go b/jiracmd/create.go index b5edea5c..17a43693 100644 --- a/jiracmd/create.go +++ b/jiracmd/create.go @@ -2,6 +2,7 @@ package jiracmd import ( "fmt" + "io/ioutil" "os" "strings" @@ -11,8 +12,8 @@ import ( "github.com/go-jira/jira" "github.com/go-jira/jira/jiracli" "github.com/go-jira/jira/jiradata" - kingpin "gopkg.in/alecthomas/kingpin.v2" - yaml "gopkg.in/coryb/yaml.v2" + "gopkg.in/alecthomas/kingpin.v2" + "gopkg.in/coryb/yaml.v2" ) type CreateOptions struct { @@ -22,6 +23,7 @@ type CreateOptions struct { IssueType string `yaml:"issuetype,omitempty" json:"issuetype,omitempty"` Overrides map[string]string `yaml:"overrides,omitempty" json:"overrides,omitempty"` SaveFile string `yaml:"savefile,omitempty" json:"savefile,omitempty"` + FromFile string `yaml:"fromfile,omitempty" json:"fromfile,omitempty"` } func CmdCreateRegistry() *jiracli.CommandRegistryEntry { @@ -49,6 +51,7 @@ func CmdCreateUsage(cmd *kingpin.CmdClause, opts *CreateOptions) error { jiracli.EditorUsage(cmd, &opts.CommonOptions) jiracli.TemplateUsage(cmd, &opts.CommonOptions) cmd.Flag("noedit", "Disable opening the editor").SetValue(&opts.SkipEditing) + cmd.Flag("fromFile", "Use a file instead of the editor").StringVar(&opts.FromFile) cmd.Flag("project", "project to create issue in").Short('p').StringVar(&opts.Project) cmd.Flag("issuetype", "issuetype in to create").Short('i').StringVar(&opts.IssueType) cmd.Flag("comment", "Comment message for issue").Short('m').PreAction(func(ctx *kingpin.ParseContext) error { @@ -94,18 +97,41 @@ func CmdCreate(o *oreo.Client, globals *jiracli.GlobalOptions, opts *CreateOptio input.Overrides["login"] = globals.Login.Value var issueResp *jiradata.IssueCreateResponse - err = jiracli.EditLoop(&opts.CommonOptions, &input, &issueUpdate, func() error { - if globals.JiraDeploymentType.Value == jiracli.CloudDeploymentType { - err := fixGDPRUserFields(o, globals.Endpoint.Value, createMeta.Fields, issueUpdate.Fields) - if err != nil { - return err - } + + if opts.FromFile != "" { + // Loading from file + inputFile, err := os.Open(opts.FromFile) + if err != nil { + return err + } + + inputFileBytes, err := ioutil.ReadAll(inputFile) + if err != nil { + return err + } + + err = yaml.Unmarshal(inputFileBytes, &issueUpdate) + if err != nil { + return fmt.Errorf("invalid yaml provided: %v", err) } issueResp, err = jira.CreateIssue(o, globals.Endpoint.Value, &issueUpdate) - return err - }) - if err != nil { - return err + if err != nil { + return err + } + } else { + err = jiracli.EditLoop(&opts.CommonOptions, &input, &issueUpdate, func() error { + if globals.JiraDeploymentType.Value == jiracli.CloudDeploymentType { + err := fixGDPRUserFields(o, globals.Endpoint.Value, createMeta.Fields, issueUpdate.Fields) + if err != nil { + return err + } + } + issueResp, err = jira.CreateIssue(o, globals.Endpoint.Value, &issueUpdate) + return err + }) + if err != nil { + return err + } } browseLink := jira.URLJoin(globals.Endpoint.Value, "browse", issueResp.Key) From d195081617ff4ed9ce1053ad985510147fc62125 Mon Sep 17 00:00:00 2001 From: Denys Vitali Date: Mon, 18 Jan 2021 22:19:30 +0100 Subject: [PATCH 2/2] feat: archive, restore --- issue.go | 36 +++++++++++++++++++++++++ jiracmd/archive.go | 66 +++++++++++++++++++++++++++++++++++++++++++++ jiracmd/registry.go | 2 ++ jiracmd/restore.go | 66 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 jiracmd/archive.go create mode 100644 jiracmd/restore.go diff --git a/issue.go b/issue.go index d36ad27a..095c00b5 100644 --- a/issue.go +++ b/issue.go @@ -545,6 +545,42 @@ type UserProvider interface { ProvideUser() *jiradata.User } +// https://docs.atlassian.com/software/jira/docs/api/REST/8.12.2/#api/2/issue-archiveIssues +func IssueArchive(ua HttpClient, endpoint string, issue string) error { + issues := []string{issue} + encoded, err := json.Marshal(issues) + if err != nil { + return err + } + uri := URLJoin(endpoint, "rest/api/2/issue/archive") + resp, err := ua.Post(uri, "application/json", bytes.NewBuffer(encoded)) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode == 200 { + return nil + } + return responseError(resp) +} + +// https://docs.atlassian.com/software/jira/docs/api/REST/8.12.2/#api/2/issue-restoreIssue +func IssueRestore(ua HttpClient, endpoint string, issue string) error { + uri := URLJoin(endpoint, "rest/api/2/issue/", issue, "/restore") + resp, err := ua.Put(uri, "application/json", nil) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode == 204 { + return nil + } + return responseError(resp) +} + + // https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-assign func (j *Jira) IssueAssign(issue, name string) error { return IssueAssign(j.UA, j.Endpoint, issue, name) diff --git a/jiracmd/archive.go b/jiracmd/archive.go new file mode 100644 index 00000000..965ddd17 --- /dev/null +++ b/jiracmd/archive.go @@ -0,0 +1,66 @@ +package jiracmd + +import ( + "fmt" + "strings" + + "github.com/coryb/figtree" + "github.com/coryb/oreo" + "github.com/go-jira/jira" + "github.com/go-jira/jira/jiracli" + kingpin "gopkg.in/alecthomas/kingpin.v2" +) + +type ArchiveOptions 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"` +} + +func CmdArchiveRegistry() *jiracli.CommandRegistryEntry { + opts := AssignOptions{} + + return &jiracli.CommandRegistryEntry{ + "Archive issue", + func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error { + jiracli.LoadConfigs(cmd, fig, &opts) + return CmdArchiveUsage(cmd, &opts) + }, + func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) + return CmdArchive(o, globals, &opts) + }, + } +} + +func CmdArchiveUsage(cmd *kingpin.CmdClause, opts *AssignOptions) error { + jiracli.BrowseUsage(cmd, &opts.CommonOptions) + cmd.Arg("ISSUE", "issue to archive").Required().StringVar(&opts.Issue) + return nil +} + +// CmdArchive will archive an issue +func CmdArchive(o *oreo.Client, globals *jiracli.GlobalOptions, opts *AssignOptions) error { + if globals.JiraDeploymentType.Value == "" { + serverInfo, err := jira.ServerInfo(o, globals.Endpoint.Value) + if err != nil { + return err + } + globals.JiraDeploymentType.Value = strings.ToLower(serverInfo.DeploymentType) + } + + err := jira.IssueArchive(o, globals.Endpoint.Value, opts.Issue) + if err != nil { + return err + } + + if !globals.Quiet.Value { + fmt.Printf("OK %s %s\n", opts.Issue, jira.URLJoin(globals.Endpoint.Value, "browse", opts.Issue)) + } + + if opts.Browse.Value { + return CmdBrowse(globals, opts.Issue) + } + + return nil +} diff --git a/jiracmd/registry.go b/jiracmd/registry.go index 0dad82c6..8e209ecf 100644 --- a/jiracmd/registry.go +++ b/jiracmd/registry.go @@ -5,6 +5,7 @@ import "github.com/go-jira/jira/jiracli" func RegisterAllCommands() { jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "acknowledge", Entry: CmdTransitionRegistry("acknowledge"), Aliases: []string{"ack"}}) jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "assign", Entry: CmdAssignRegistry(), Aliases: []string{"give"}}) + jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "archive", Entry: CmdArchiveRegistry()}) jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "attach create", Entry: CmdAttachCreateRegistry()}) jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "attach get", Entry: CmdAttachGetRegistry()}) jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "attach list", Entry: CmdAttachListRegistry(), Aliases: []string{"ls"}}) @@ -42,6 +43,7 @@ func RegisterAllCommands() { jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "reopen", Entry: CmdTransitionRegistry("reopen")}) jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "request", Entry: CmdRequestRegistry(), Aliases: []string{"req"}}) jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "resolve", Entry: CmdTransitionRegistry("resolve")}) + jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "restore", Entry: CmdRestoreRegistry()}) jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "start", Entry: CmdTransitionRegistry("start")}) jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "stop", Entry: CmdTransitionRegistry("stop")}) jiracli.RegisterCommand(jiracli.CommandRegistry{Command: "subtask", Entry: CmdSubtaskRegistry()}) diff --git a/jiracmd/restore.go b/jiracmd/restore.go new file mode 100644 index 00000000..1c7e8276 --- /dev/null +++ b/jiracmd/restore.go @@ -0,0 +1,66 @@ +package jiracmd + +import ( + "fmt" + "strings" + + "github.com/coryb/figtree" + "github.com/coryb/oreo" + "github.com/go-jira/jira" + "github.com/go-jira/jira/jiracli" + kingpin "gopkg.in/alecthomas/kingpin.v2" +) + +type RestoreOptions 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"` +} + +func CmdRestoreRegistry() *jiracli.CommandRegistryEntry { + opts := AssignOptions{} + + return &jiracli.CommandRegistryEntry{ + "Restore issue", + func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error { + jiracli.LoadConfigs(cmd, fig, &opts) + return CmdRestoreUsage(cmd, &opts) + }, + func(o *oreo.Client, globals *jiracli.GlobalOptions) error { + opts.Issue = jiracli.FormatIssue(opts.Issue, opts.Project) + return CmdRestore(o, globals, &opts) + }, + } +} + +func CmdRestoreUsage(cmd *kingpin.CmdClause, opts *AssignOptions) error { + jiracli.BrowseUsage(cmd, &opts.CommonOptions) + cmd.Arg("ISSUE", "issue to restore").Required().StringVar(&opts.Issue) + return nil +} + +// CmdRestore will restore an issue +func CmdRestore(o *oreo.Client, globals *jiracli.GlobalOptions, opts *AssignOptions) error { + if globals.JiraDeploymentType.Value == "" { + serverInfo, err := jira.ServerInfo(o, globals.Endpoint.Value) + if err != nil { + return err + } + globals.JiraDeploymentType.Value = strings.ToLower(serverInfo.DeploymentType) + } + + err := jira.IssueRestore(o, globals.Endpoint.Value, opts.Issue) + if err != nil { + return err + } + + if !globals.Quiet.Value { + fmt.Printf("OK %s %s\n", opts.Issue, jira.URLJoin(globals.Endpoint.Value, "browse", opts.Issue)) + } + + if opts.Browse.Value { + return CmdBrowse(globals, opts.Issue) + } + + return nil +}