From fb43753c3140b110da0b152402ffffa686602712 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Wed, 13 Sep 2017 11:12:58 -0700 Subject: [PATCH] [#99] add support for named queries to be stored in configs --- .jira.d/config.yml | 6 ++ Gopkg.lock | 2 +- jiracli/templates.go | 63 ++++++++++++++----- jiracmd/edit.go | 14 ++++- jiracmd/list.go | 16 ++++- vendor/github.com/coryb/figtree/Gopkg.lock | 73 ++++++++++++++++++++++ vendor/github.com/coryb/figtree/Gopkg.toml | 47 ++++++++++++++ vendor/github.com/coryb/figtree/figtree.go | 8 +++ vendor/github.com/coryb/figtree/glide.lock | 36 ----------- vendor/github.com/coryb/figtree/glide.yaml | 18 ------ 10 files changed, 208 insertions(+), 75 deletions(-) create mode 100644 vendor/github.com/coryb/figtree/Gopkg.lock create mode 100644 vendor/github.com/coryb/figtree/Gopkg.toml delete mode 100644 vendor/github.com/coryb/figtree/glide.lock delete mode 100644 vendor/github.com/coryb/figtree/glide.yaml diff --git a/.jira.d/config.yml b/.jira.d/config.yml index 7ed6421d..607faf21 100644 --- a/.jira.d/config.yml +++ b/.jira.d/config.yml @@ -3,3 +3,9 @@ config: password-source: pass endpoint: https://go-jira.atlassian.net user: admin + +queries: + todo: |- + resolution = unresolved {{if .project}}AND project = '{{.project}}'{{end}} AND status = 'To Do' + progress: |- + resolution = unresolved {{if .project}}AND project = '{{.project}}'{{end}} AND status = 'In Progress' diff --git a/Gopkg.lock b/Gopkg.lock index 7c345e75..eb1d67a2 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -23,7 +23,7 @@ branch = "master" name = "github.com/coryb/figtree" packages = ["."] - revision = "86e7c859d0326621c45ba7be2c32e3b3ae203213" + revision = "c7d8fbf1d7746b5864b8262fabffec813b5a43fa" [[projects]] branch = "master" diff --git a/jiracli/templates.go b/jiracli/templates.go index bdaf873e..491555a5 100644 --- a/jiracli/templates.go +++ b/jiracli/templates.go @@ -13,9 +13,11 @@ import ( "strings" "text/template" + yaml "gopkg.in/coryb/yaml.v2" + + "github.com/coryb/figtree" "github.com/mgutz/ansi" "golang.org/x/crypto/ssh/terminal" - yaml "gopkg.in/coryb/yaml.v2" ) func findTemplate(name string) ([]byte, error) { @@ -157,6 +159,48 @@ func TemplateProcessor() *template.Template { return template.New("gojira").Funcs(funcs) } +func ConfigTemplate(fig *figtree.FigTree, template, command string, opts interface{}) (string, error) { + tmp, err := translateOptions(opts) + if err != nil { + return "", err + } + fig.LoadAllConfigs(command+".yml", tmp) + fig.LoadAllConfigs("config.yml", tmp) + + tmpl, err := TemplateProcessor().Parse(template) + if err != nil { + return "", err + } + buf := bytes.NewBufferString("") + if err := tmpl.Execute(buf, &tmp); err != nil { + return "", err + } + return buf.String(), nil +} + +func translateOptions(opts interface{}) (interface{}, error) { + // HACK HACK HACK: convert data formats to json for backwards compatibilty with templates + jsonData, err := json.Marshal(opts) + if err != nil { + return nil, err + } + + defer func(mapType, iface reflect.Type) { + yaml.DefaultMapType = mapType + yaml.IfaceType = iface + }(yaml.DefaultMapType, yaml.IfaceType) + + yaml.DefaultMapType = reflect.TypeOf(map[string]interface{}{}) + yaml.IfaceType = yaml.DefaultMapType.Elem() + + var rawData map[string]interface{} + if err := yaml.Unmarshal(jsonData, &rawData); err != nil { + return nil, err + } + return &rawData, nil + +} + func RunTemplate(templateName string, data interface{}, out io.Writer) error { templateContent, err := getTemplate(templateName) @@ -168,22 +212,9 @@ func RunTemplate(templateName string, data interface{}, out io.Writer) error { out = os.Stdout } - // HACK HACK HACK: convert data formats to json for backwards compatibilty with templates - var rawData interface{} - if jsonData, err := json.Marshal(data); err != nil { + rawData, err := translateOptions(data) + if err != nil { return err - } else { - defer func(mapType, iface reflect.Type) { - yaml.DefaultMapType = mapType - yaml.IfaceType = iface - }(yaml.DefaultMapType, yaml.IfaceType) - - yaml.DefaultMapType = reflect.TypeOf(map[string]interface{}{}) - yaml.IfaceType = yaml.DefaultMapType.Elem() - - if err := yaml.Unmarshal(jsonData, &rawData); err != nil { - return err - } } tmpl, err := TemplateProcessor().Parse(templateContent) diff --git a/jiracmd/edit.go b/jiracmd/edit.go index 629186be..61c8eba9 100644 --- a/jiracmd/edit.go +++ b/jiracmd/edit.go @@ -18,6 +18,7 @@ type EditOptions struct { jira.SearchOptions `yaml:",inline" json:",inline" figtree:",inline"` Overrides map[string]string `yaml:"overrides,omitempty" json:"overrides,omitempty"` Issue string `yaml:"issue,omitempty" json:"issue,omitempty"` + Queries map[string]string `yaml:"queries,omitempty" json:"queries,omitempty"` } func CmdEditRegistry() *jiracli.CommandRegistryEntry { @@ -32,7 +33,7 @@ func CmdEditRegistry() *jiracli.CommandRegistryEntry { "Edit issue details", func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error { jiracli.LoadConfigs(cmd, fig, &opts) - return CmdEditUsage(cmd, &opts) + return CmdEditUsage(cmd, &opts, fig) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { return CmdEdit(o, globals, &opts) @@ -40,11 +41,20 @@ func CmdEditRegistry() *jiracli.CommandRegistryEntry { } } -func CmdEditUsage(cmd *kingpin.CmdClause, opts *EditOptions) error { +func CmdEditUsage(cmd *kingpin.CmdClause, opts *EditOptions, fig *figtree.FigTree) error { jiracli.BrowseUsage(cmd, &opts.CommonOptions) jiracli.EditorUsage(cmd, &opts.CommonOptions) jiracli.TemplateUsage(cmd, &opts.CommonOptions) cmd.Flag("noedit", "Disable opening the editor").SetValue(&opts.SkipEditing) + cmd.Flag("named-query", "The name of a query in the `queries` configuration").Short('n').Action(func(ctx *kingpin.ParseContext) error { + name := jiracli.FlagValue(ctx, "named-query") + if query, ok := opts.Queries[name]; ok && query != "" { + var err error + opts.Query, err = jiracli.ConfigTemplate(fig, query, cmd.FullCommand(), opts) + return err + } + return fmt.Errorf("A valid named-query %q not found in `queries` configuration", name) + }).String() cmd.Flag("query", "Jira Query Language (JQL) expression for the search to edit multiple issues").Short('q').StringVar(&opts.Query) cmd.Flag("comment", "Comment message for issue").Short('m').PreAction(func(ctx *kingpin.ParseContext) error { opts.Overrides["comment"] = jiracli.FlagValue(ctx, "comment") diff --git a/jiracmd/list.go b/jiracmd/list.go index f26e576f..13db0bb9 100644 --- a/jiracmd/list.go +++ b/jiracmd/list.go @@ -1,6 +1,8 @@ package jiracmd import ( + "fmt" + "github.com/coryb/figtree" "github.com/coryb/oreo" "gopkg.in/Netflix-Skunkworks/go-jira.v1" @@ -11,6 +13,7 @@ import ( type ListOptions struct { jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"` jira.SearchOptions `yaml:",inline" json:",inline" figtree:",inline"` + Queries map[string]string `yaml:"queries,omitempty" json:"queries,omitempty"` } func CmdListRegistry() *jiracli.CommandRegistryEntry { @@ -33,7 +36,7 @@ func CmdListRegistry() *jiracli.CommandRegistryEntry { if opts.Sort == "" { opts.Sort = "priority asc, key" } - return CmdListUsage(cmd, &opts) + return CmdListUsage(cmd, &opts, fig) }, func(o *oreo.Client, globals *jiracli.GlobalOptions) error { return CmdList(o, globals, &opts) @@ -41,7 +44,7 @@ func CmdListRegistry() *jiracli.CommandRegistryEntry { } } -func CmdListUsage(cmd *kingpin.CmdClause, opts *ListOptions) error { +func CmdListUsage(cmd *kingpin.CmdClause, opts *ListOptions, fig *figtree.FigTree) error { jiracli.TemplateUsage(cmd, &opts.CommonOptions) jiracli.GJsonQueryUsage(cmd, &opts.CommonOptions) cmd.Flag("assignee", "User assigned the issue").Short('a').StringVar(&opts.Assignee) @@ -49,6 +52,15 @@ func CmdListUsage(cmd *kingpin.CmdClause, opts *ListOptions) error { cmd.Flag("issuetype", "Issue type to search for").Short('i').StringVar(&opts.IssueType) cmd.Flag("limit", "Maximum number of results to return in search").Short('l').IntVar(&opts.MaxResults) cmd.Flag("project", "Project to search for").Short('p').StringVar(&opts.Project) + cmd.Flag("named-query", "The name of a query in the `queries` configuration").Short('n').Action(func(ctx *kingpin.ParseContext) error { + name := jiracli.FlagValue(ctx, "named-query") + if query, ok := opts.Queries[name]; ok && query != "" { + var err error + opts.Query, err = jiracli.ConfigTemplate(fig, query, cmd.FullCommand(), opts) + return err + } + return fmt.Errorf("A valid named-query %q not found in `queries` configuration", name) + }).String() cmd.Flag("query", "Jira Query Language (JQL) expression for the search").Short('q').StringVar(&opts.Query) cmd.Flag("queryfields", "Fields that are used in \"list\" template").Short('f').StringVar(&opts.QueryFields) cmd.Flag("reporter", "Reporter to search for").Short('r').StringVar(&opts.Reporter) diff --git a/vendor/github.com/coryb/figtree/Gopkg.lock b/vendor/github.com/coryb/figtree/Gopkg.lock new file mode 100644 index 00000000..892c5533 --- /dev/null +++ b/vendor/github.com/coryb/figtree/Gopkg.lock @@ -0,0 +1,73 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/alecthomas/template" + packages = [".","parse"] + revision = "a0175ee3bccc567396460bf5acd36800cb10c49c" + +[[projects]] + branch = "master" + name = "github.com/alecthomas/units" + packages = ["."] + revision = "2efee857e7cfd4f3d0138cc3cbb1b4966962b93a" + +[[projects]] + branch = "master" + name = "github.com/cheekybits/genny" + packages = ["generic"] + revision = "9127e812e1e9e501ce899a18121d316ecb52e4ba" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "6d212800a42e8ab5c146b8ace3490ee17e5225f9" + +[[projects]] + branch = "master" + name = "github.com/fatih/camelcase" + packages = ["."] + revision = "f6a740d52f961c60348ebb109adde9f4635d7540" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "d8ed2627bdf02c080bf22230dbb337003b7aba2d" + +[[projects]] + name = "github.com/stretchr/testify" + packages = ["assert"] + revision = "69483b4bd14f5845b5a1e55bca19e954e827f1d0" + version = "v1.1.4" + +[[projects]] + name = "gopkg.in/alecthomas/kingpin.v2" + packages = ["."] + revision = "7f0871f2e17818990e4eed73f9b5c2f429501228" + version = "v2.2.4" + +[[projects]] + branch = "v2" + name = "gopkg.in/coryb/yaml.v2" + packages = ["."] + revision = "fb7cb9628c6e3bdd76c29fb91798d51a09832470" + +[[projects]] + name = "gopkg.in/op/go-logging.v1" + packages = ["."] + revision = "b2cb9fa56473e98db8caba80237377e83fe44db5" + version = "v1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1879d7c016fcc8e210ca7fdeed4b099f4e7fc931d34ff47a170222c60eea8aab" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/coryb/figtree/Gopkg.toml b/vendor/github.com/coryb/figtree/Gopkg.toml new file mode 100644 index 00000000..53fc1222 --- /dev/null +++ b/vendor/github.com/coryb/figtree/Gopkg.toml @@ -0,0 +1,47 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + name = "github.com/cheekybits/genny" + +[[constraint]] + name = "github.com/fatih/camelcase" + +[[constraint]] + name = "github.com/pkg/errors" + version = "0.8.0" + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.1.4" + +[[constraint]] + name = "gopkg.in/alecthomas/kingpin.v2" + version = "2.2.4" + +[[constraint]] + name = "gopkg.in/coryb/yaml.v2" + +[[constraint]] + name = "gopkg.in/op/go-logging.v1" + version = "1.0.0" diff --git a/vendor/github.com/coryb/figtree/figtree.go b/vendor/github.com/coryb/figtree/figtree.go index 8e25b32a..1cfc5b25 100644 --- a/vendor/github.com/coryb/figtree/figtree.go +++ b/vendor/github.com/coryb/figtree/figtree.go @@ -81,6 +81,14 @@ func (f *FigTree) LoadAllConfigs(configFile string, options interface{}) error { func (f *FigTree) LoadConfigBytes(config []byte, source string, options interface{}) (err error) { f.populateEnv(options) + defer func(mapType, iface reflect.Type) { + yaml.DefaultMapType = mapType + yaml.IfaceType = iface + }(yaml.DefaultMapType, yaml.IfaceType) + + yaml.DefaultMapType = reflect.TypeOf(map[string]interface{}{}) + yaml.IfaceType = yaml.DefaultMapType.Elem() + m := &merger{sourceFile: source} type tmpOpts struct { Config ConfigOptions diff --git a/vendor/github.com/coryb/figtree/glide.lock b/vendor/github.com/coryb/figtree/glide.lock deleted file mode 100644 index 7a10d2de..00000000 --- a/vendor/github.com/coryb/figtree/glide.lock +++ /dev/null @@ -1,36 +0,0 @@ -hash: 4c141f4247c76717823951388fcd50678e63195fa40b0d5bc7097d0267003052 -updated: 2017-07-06T23:09:17.970073816-07:00 -imports: -- name: github.com/cheekybits/genny - version: 9127e812e1e9e501ce899a18121d316ecb52e4ba - subpackages: - - generic -- name: github.com/fatih/camelcase - version: f6a740d52f961c60348ebb109adde9f4635d7540 -- name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: gopkg.in/coryb/yaml.v2 - version: f284bc8aa3c31dfdda9cc7917c610398c49b3acd -- name: gopkg.in/op/go-logging.v1 - version: b2cb9fa56473e98db8caba80237377e83fe44db5 -testImports: -- name: github.com/alecthomas/template - version: a0175ee3bccc567396460bf5acd36800cb10c49c - subpackages: - - parse -- name: github.com/alecthomas/units - version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a -- name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 - subpackages: - - spew -- name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d - subpackages: - - difflib -- name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 - subpackages: - - assert -- name: gopkg.in/alecthomas/kingpin.v2 - version: 7f0871f2e17818990e4eed73f9b5c2f429501228 diff --git a/vendor/github.com/coryb/figtree/glide.yaml b/vendor/github.com/coryb/figtree/glide.yaml deleted file mode 100644 index e2e1ee43..00000000 --- a/vendor/github.com/coryb/figtree/glide.yaml +++ /dev/null @@ -1,18 +0,0 @@ -package: github.com/coryb/figtree -import: -- package: github.com/cheekybits/genny - subpackages: - - generic -- package: github.com/pkg/errors - version: ^0.8.0 -- package: gopkg.in/coryb/yaml.v2 -- package: gopkg.in/op/go-logging.v1 - version: ^1.0.0 -- package: github.com/fatih/camelcase -testImport: -- package: github.com/stretchr/testify - version: ^1.1.4 - subpackages: - - assert -- package: gopkg.in/alecthomas/kingpin.v2 - version: ^2.2.4