mirror of
https://github.com/Threnklyn/jira.git
synced 2026-05-19 20:53:27 +02:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| abc82b909e | |||
| dabf4cf034 | |||
| 79a6381307 | |||
| 893454fc69 | |||
| d5b9631cf4 | |||
| e841270b83 | |||
| 2ededeeaf7 | |||
| 00cba793ad | |||
| fb43753c31 | |||
| 5085a14494 | |||
| 5da04c1f86 |
@@ -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'
|
||||
open: |
|
||||
resolution = unresolved {{if .project}}AND project = '{{.project}}'{{end}} AND status = 'Open'
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
## 1.0.7 - 2017-09-15
|
||||
|
||||
* [[#87](https://github.com/Netflix-Skunkworks/go-jira/issues/87)] add various commands for interacting with epics [Cory Bennett] [[893454f](https://github.com/Netflix-Skunkworks/go-jira/commit/893454f)]
|
||||
|
||||
## 1.0.6 - 2017-09-13
|
||||
|
||||
* tweaks for templates in named queries to work better [Cory Bennett] [[00cba79](https://github.com/Netflix-Skunkworks/go-jira/commit/00cba79)]
|
||||
* [[#99](https://github.com/Netflix-Skunkworks/go-jira/issues/99)] add support for named queries to be stored in configs [Cory Bennett] [[fb43753](https://github.com/Netflix-Skunkworks/go-jira/commit/fb43753)]
|
||||
* [[#98](https://github.com/Netflix-Skunkworks/go-jira/issues/98)] add `--status` option for JQL filter on status with `list` command [Cory Bennett] [[5da04c1](https://github.com/Netflix-Skunkworks/go-jira/commit/5da04c1)]
|
||||
|
||||
## 1.0.5 - 2017-09-11
|
||||
|
||||
* use --gjq for GJson Query to filter json response data [Cory Bennett] [[608e586](https://github.com/Netflix-Skunkworks/go-jira/commit/608e586)]
|
||||
|
||||
Generated
+1
-1
@@ -23,7 +23,7 @@
|
||||
branch = "master"
|
||||
name = "github.com/coryb/figtree"
|
||||
packages = ["."]
|
||||
revision = "86e7c859d0326621c45ba7be2c32e3b3ae203213"
|
||||
revision = "c7d8fbf1d7746b5864b8262fabffec813b5a43fa"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[](https://gitter.im/go-jira-cli/help?utm_source=badge&utm_medium=badge&utm_content=badge)
|
||||
[](https://travis-ci.org/Netflix-Skunkworks/go-jira)
|
||||
[](https://godoc.org/gopkg.in/Netflix-Skunkworks/go-jira.v1)
|
||||
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
|
||||
# go-jira
|
||||
simple command line client for Atlassian's Jira service written in Go
|
||||
@@ -429,14 +429,17 @@ Commands:
|
||||
Prints list of issues for given search criteria
|
||||
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
-a, --assignee=ASSIGNEE User assigned the issue
|
||||
-c, --component=COMPONENT Component to search for
|
||||
-i, --issuetype=ISSUETYPE Issue type to search for
|
||||
-l, --limit=LIMIT Maximum number of results to return in search
|
||||
-p, --project=PROJECT Project to search for
|
||||
-n, --named-query=NAMED-QUERY The name of a query in the `queries` configuration
|
||||
-q, --query=QUERY Jira Query Language (JQL) expression for the search
|
||||
-f, --queryfields=QUERYFIELDS Fields that are used in "list" template
|
||||
-r, --reporter=REPORTER Reporter to search for
|
||||
-S, --status=STATUS Filter on issue status
|
||||
-s, --sort=SORT Sort order to return
|
||||
-w, --watcher=WATCHER Watcher to search for
|
||||
|
||||
@@ -445,6 +448,7 @@ Commands:
|
||||
|
||||
-b, --browse Open issue(s) in browser after operation
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
--expand=EXPAND ... field to expand for the issue
|
||||
--field=FIELD ... field to return for the issue
|
||||
--property=PROPERTY ... property to return for issue
|
||||
@@ -465,13 +469,14 @@ Commands:
|
||||
edit [<flags>] [<ISSUE>]
|
||||
Edit issue details
|
||||
|
||||
-b, --browse Open issue(s) in browser after operation
|
||||
--editor=EDITOR Editor to use
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--noedit Disable opening the editor
|
||||
-q, --query=QUERY Jira Query Language (JQL) expression for the search to edit multiple issues
|
||||
-m, --comment=COMMENT Comment message for issue
|
||||
-o, --override=OVERRIDE ... Set issue property
|
||||
-b, --browse Open issue(s) in browser after operation
|
||||
--editor=EDITOR Editor to use
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--noedit Disable opening the editor
|
||||
-n, --named-query=NAMED-QUERY The name of a query in the `queries` configuration
|
||||
-q, --query=QUERY Jira Query Language (JQL) expression for the search to edit multiple issues
|
||||
-m, --comment=COMMENT Comment message for issue
|
||||
-o, --override=OVERRIDE ... Set issue property
|
||||
|
||||
comment [<flags>] [<ISSUE>]
|
||||
Add comment to issue
|
||||
@@ -482,11 +487,51 @@ Commands:
|
||||
--noedit Disable opening the editor
|
||||
-m, --comment=COMMENT Comment message for issue
|
||||
|
||||
epic create [<flags>]
|
||||
Create Epic
|
||||
|
||||
-b, --browse Open issue(s) in browser after operation
|
||||
--editor=EDITOR Editor to use
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--noedit Disable opening the editor
|
||||
-p, --project=PROJECT project to create epic in
|
||||
-n, --epic-name=EPIC-NAME Epic Name
|
||||
-m, --comment=COMMENT Comment message for epic
|
||||
-o, --override=OVERRIDE ... Set epic property
|
||||
--saveFile=SAVEFILE Write epic as yaml to file
|
||||
|
||||
epic list [<flags>] <EPIC>
|
||||
Prints list of issues for an epic with optional search criteria
|
||||
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
-a, --assignee=ASSIGNEE User assigned the issue
|
||||
-c, --component=COMPONENT Component to search for
|
||||
-i, --issuetype=ISSUETYPE Issue type to search for
|
||||
-l, --limit=LIMIT Maximum number of results to return in search
|
||||
-p, --project=PROJECT Project to search for
|
||||
-n, --named-query=NAMED-QUERY The name of a query in the `queries` configuration
|
||||
-q, --query=QUERY Jira Query Language (JQL) expression for the search
|
||||
-f, --queryfields=QUERYFIELDS Fields that are used in "list" template
|
||||
-r, --reporter=REPORTER Reporter to search for
|
||||
-S, --status=STATUS Filter on issue status
|
||||
-s, --sort=SORT Sort order to return
|
||||
-w, --watcher=WATCHER Watcher to search for
|
||||
|
||||
epic add <EPIC> <ISSUE>...
|
||||
Add issues to Epic
|
||||
|
||||
|
||||
epic remove <ISSUE>...
|
||||
Remove issues from Epic
|
||||
|
||||
|
||||
worklog list [<flags>] <ISSUE>
|
||||
Prints the worklog data for given issue
|
||||
|
||||
-b, --browse Open issue(s) in browser after operation
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
|
||||
worklog add [<flags>] <ISSUE>
|
||||
Add a worklog to an issue
|
||||
@@ -497,16 +542,19 @@ Commands:
|
||||
--noedit Disable opening the editor
|
||||
-m, --comment=COMMENT Comment message for worklog
|
||||
-T, --time-spent=TIME-SPENT Time spent working on issue
|
||||
-S, --started=STARTED Time you started work
|
||||
|
||||
fields [<flags>]
|
||||
Prints all fields, both System and Custom
|
||||
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
|
||||
createmeta [<flags>]
|
||||
View 'create' metadata
|
||||
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
-p, --project=PROJECT project to fetch create metadata
|
||||
-i, --issuetype=ISSUETYPE issuetype in project to fetch create metadata
|
||||
|
||||
@@ -515,6 +563,7 @@ Commands:
|
||||
|
||||
-b, --browse Open issue(s) in browser after operation
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
|
||||
subtask [<flags>] [<ISSUE>]
|
||||
Subtask issue
|
||||
@@ -555,6 +604,7 @@ Commands:
|
||||
Show the issue link types
|
||||
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
|
||||
transition [<flags>] <TRANSITION> <ISSUE>
|
||||
Transition issue to given state
|
||||
@@ -570,12 +620,14 @@ Commands:
|
||||
|
||||
-b, --browse Open issue(s) in browser after operation
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
|
||||
transmeta [<flags>] <ISSUE>
|
||||
List valid issue transitions
|
||||
|
||||
-b, --browse Open issue(s) in browser after operation
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
|
||||
close [<flags>] <ISSUE>
|
||||
Transition issue to close state
|
||||
@@ -732,12 +784,14 @@ Commands:
|
||||
Show components for a project
|
||||
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
-p, --project=PROJECT project to list components
|
||||
|
||||
issuetypes [<flags>]
|
||||
Show issue types for a project
|
||||
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
-p, --project=PROJECT project to list issueTypes
|
||||
|
||||
export-templates [<flags>]
|
||||
@@ -759,5 +813,7 @@ Commands:
|
||||
request [<flags>] <API> [<JSON>]
|
||||
Open issue in requestr
|
||||
|
||||
-M, --method=METHOD HTTP request method to use
|
||||
-t, --template=TEMPLATE Template to use for output
|
||||
--gjq=GJQ GJSON Query to filter output, see https://goo.gl/iaYwJ5
|
||||
-M, --method=METHOD HTTP request method to use
|
||||
```
|
||||
|
||||
+24
-1
@@ -131,6 +131,24 @@ func main() {
|
||||
Command: "comment",
|
||||
Entry: jiracmd.CmdCommentRegistry(),
|
||||
},
|
||||
jiracli.CommandRegistry{
|
||||
Command: "epic create",
|
||||
Entry: jiracmd.CmdEpicCreateRegistry(),
|
||||
},
|
||||
jiracli.CommandRegistry{
|
||||
Command: "epic list",
|
||||
Entry: jiracmd.CmdEpicListRegistry(),
|
||||
Aliases: []string{"ls"},
|
||||
},
|
||||
jiracli.CommandRegistry{
|
||||
Command: "epic add",
|
||||
Entry: jiracmd.CmdEpicAddRegistry(),
|
||||
},
|
||||
jiracli.CommandRegistry{
|
||||
Command: "epic remove",
|
||||
Entry: jiracmd.CmdEpicRemoveRegistry(),
|
||||
Aliases: []string{"rm"},
|
||||
},
|
||||
jiracli.CommandRegistry{
|
||||
Command: "worklog list",
|
||||
Entry: jiracmd.CmdWorklogListRegistry(),
|
||||
@@ -338,7 +356,12 @@ func main() {
|
||||
|
||||
// checking for default usage of `jira ISSUE-123` but need to allow
|
||||
// for global options first like: `jira --user mothra ISSUE-123`
|
||||
ctx, _ := app.ParseContext(os.Args[1:])
|
||||
ctx, err := app.ParseContext(os.Args[1:])
|
||||
if err != nil && ctx == nil {
|
||||
// This is an internal kingpin usage error, duplicate options/commands
|
||||
log.Fatalf("error: %s, ctx: %v", err, ctx)
|
||||
}
|
||||
|
||||
if ctx != nil {
|
||||
if ctx.SelectedCommand == nil {
|
||||
next := ctx.Next()
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
package jira
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/coryb/oreo"
|
||||
|
||||
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
|
||||
)
|
||||
|
||||
// https://docs.atlassian.com/jira-software/REST/latest/#agile/1.0/epic-getIssuesForEpic
|
||||
func (j *Jira) EpicSearch(epic string, sp SearchProvider) (*jiradata.SearchResults, error) {
|
||||
return EpicSearch(j.UA, j.Endpoint, epic, sp)
|
||||
}
|
||||
|
||||
func EpicSearch(ua HttpClient, endpoint string, epic string, sp SearchProvider) (*jiradata.SearchResults, error) {
|
||||
req := sp.ProvideSearchRequest()
|
||||
// encoded, err := json.Marshal(req)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
uri, err := url.Parse(fmt.Sprintf("%s/rest/agile/1.0/epic/%s/issue", endpoint, epic))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params := url.Values{}
|
||||
if len(req.Fields) > 0 {
|
||||
params.Add("fields", strings.Join(req.Fields, ","))
|
||||
}
|
||||
if req.JQL != "" {
|
||||
params.Add("jql", req.JQL)
|
||||
}
|
||||
if req.MaxResults != 0 {
|
||||
params.Add("maxResults", fmt.Sprintf("%d", req.MaxResults))
|
||||
}
|
||||
if req.StartAt != 0 {
|
||||
params.Add("startAt", fmt.Sprintf("%d", req.StartAt))
|
||||
}
|
||||
if req.ValidateQuery != "" {
|
||||
params.Add("validateQuery", req.ValidateQuery)
|
||||
}
|
||||
uri.RawQuery = params.Encode()
|
||||
|
||||
resp, err := ua.Do(oreo.RequestBuilder(uri).WithHeader("Accept", "application/json").Build())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == 200 {
|
||||
results := &jiradata.SearchResults{}
|
||||
return results, readJSON(resp.Body, results)
|
||||
}
|
||||
return nil, responseError(resp)
|
||||
}
|
||||
|
||||
type EpicIssuesProvider interface {
|
||||
ProvideEpicIssues() *jiradata.EpicIssues
|
||||
}
|
||||
|
||||
// https://docs.atlassian.com/jira-software/REST/latest/#agile/1.0/epic-moveIssuesToEpic
|
||||
func (j *Jira) EpicAddIssues(epic string, eip EpicIssuesProvider) error {
|
||||
return EpicAddIssues(j.UA, j.Endpoint, epic, eip)
|
||||
}
|
||||
|
||||
func EpicAddIssues(ua HttpClient, endpoint string, epic string, eip EpicIssuesProvider) error {
|
||||
req := eip.ProvideEpicIssues()
|
||||
encoded, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("%s/rest/agile/1.0/epic/%s/issue", endpoint, epic)
|
||||
resp, err := ua.Post(uri, "application/json", bytes.NewBuffer(encoded))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == 204 {
|
||||
return nil
|
||||
}
|
||||
return responseError(resp)
|
||||
}
|
||||
|
||||
// https://docs.atlassian.com/jira-software/REST/latest/#agile/1.0/epic-removeIssuesFromEpic
|
||||
func (j *Jira) EpicRemoveIssues(eip EpicIssuesProvider) error {
|
||||
return EpicRemoveIssues(j.UA, j.Endpoint, eip)
|
||||
}
|
||||
|
||||
func EpicRemoveIssues(ua HttpClient, endpoint string, eip EpicIssuesProvider) error {
|
||||
req := eip.ProvideEpicIssues()
|
||||
encoded, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("%s/rest/agile/1.0/epic/none/issue", endpoint)
|
||||
resp, err := ua.Post(uri, "application/json", bytes.NewBuffer(encoded))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == 204 {
|
||||
return nil
|
||||
}
|
||||
return responseError(resp)
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
var log = logging.MustGetLogger("jira")
|
||||
|
||||
const VERSION = "1.0.5"
|
||||
const VERSION = "1.0.7"
|
||||
|
||||
type Jira struct {
|
||||
Endpoint string `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
|
||||
|
||||
+74
-16
@@ -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 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)
|
||||
@@ -205,6 +236,8 @@ var AllTemplates = map[string]string{
|
||||
"debug": defaultDebugTemplate,
|
||||
"edit": defaultEditTemplate,
|
||||
"editmeta": defaultDebugTemplate,
|
||||
"epic-create": defaultEpicCreateTemplate,
|
||||
"epic-list": defaultTableTemplate,
|
||||
"fields": defaultDebugTemplate,
|
||||
"issuelinktypes": defaultDebugTemplate,
|
||||
"issuetypes": defaultIssuetypesTemplate,
|
||||
@@ -356,6 +389,31 @@ fields:
|
||||
- name: {{.}}{{end}}
|
||||
- name:{{end}}`
|
||||
|
||||
const defaultEpicCreateTemplate = `{{/* epic create template */ -}}
|
||||
fields:
|
||||
project:
|
||||
key: {{ or .overrides.project "" }}
|
||||
# Epic Name
|
||||
customfield_10120: {{ or (index .overrides "epic-name") "" }}
|
||||
summary: >-
|
||||
{{ or .overrides.summary "" }}{{if .meta.fields.priority.allowedValues}}
|
||||
priority: # Values: {{ range .meta.fields.priority.allowedValues }}{{.name}}, {{end}}
|
||||
name: {{ or .overrides.priority ""}}{{end}}{{if .meta.fields.components.allowedValues}}
|
||||
components: # Values: {{ range .meta.fields.components.allowedValues }}{{.name}}, {{end}}{{ range split "," (or .overrides.components "")}}
|
||||
- name: {{ . }}{{end}}{{end}}
|
||||
description: |~
|
||||
{{ or .overrides.description "" | indent 4 }}{{if .meta.fields.assignee}}
|
||||
assignee:
|
||||
name: {{ or .overrides.assignee "" }}{{end}}{{if .meta.fields.reporter}}
|
||||
reporter:
|
||||
name: {{ or .overrides.reporter .overrides.user }}{{end}}{{if .meta.fields.customfield_10110}}
|
||||
# watchers
|
||||
customfield_10110: {{ range split "," (or .overrides.watchers "")}}
|
||||
- name: {{.}}{{end}}
|
||||
- name:{{end}}
|
||||
issuetype:
|
||||
name: Epic`
|
||||
|
||||
const defaultSubtaskTemplate = `{{/* create subtask template */ -}}
|
||||
fields:
|
||||
project:
|
||||
|
||||
+12
-2
@@ -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').PreAction(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")
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package jiracmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/coryb/figtree"
|
||||
"github.com/coryb/oreo"
|
||||
|
||||
"gopkg.in/Netflix-Skunkworks/go-jira.v1"
|
||||
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
|
||||
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
|
||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
type EpicAddOptions struct {
|
||||
jiradata.EpicIssues `yaml:",inline" json:",inline" figtree:",inline"`
|
||||
Epic string `yaml:"epic,omitempty" json:"epic,omitempty"`
|
||||
}
|
||||
|
||||
func CmdEpicAddRegistry() *jiracli.CommandRegistryEntry {
|
||||
opts := EpicAddOptions{}
|
||||
|
||||
return &jiracli.CommandRegistryEntry{
|
||||
"Add issues to Epic",
|
||||
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
|
||||
jiracli.LoadConfigs(cmd, fig, &opts)
|
||||
return CmdEpicAddUsage(cmd, &opts)
|
||||
},
|
||||
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
|
||||
return CmdEpicAdd(o, globals, &opts)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func CmdEpicAddUsage(cmd *kingpin.CmdClause, opts *EpicAddOptions) error {
|
||||
cmd.Arg("EPIC", "Epic Key or ID to add issues to").Required().StringVar(&opts.Epic)
|
||||
cmd.Arg("ISSUE", "Issues to add to epic").Required().StringsVar(&opts.Issues)
|
||||
return nil
|
||||
}
|
||||
|
||||
func CmdEpicAdd(o *oreo.Client, globals *jiracli.GlobalOptions, opts *EpicAddOptions) error {
|
||||
if err := jira.EpicAddIssues(o, globals.Endpoint.Value, opts.Epic, &opts.EpicIssues); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !globals.Quiet.Value {
|
||||
fmt.Printf("OK %s %s/browse/%s\n", opts.Epic, globals.Endpoint.Value, opts.Epic)
|
||||
for _, issue := range opts.Issues {
|
||||
fmt.Printf("OK %s %s/browse/%s\n", issue, globals.Endpoint.Value, issue)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package jiracmd
|
||||
|
||||
import (
|
||||
"github.com/coryb/figtree"
|
||||
"github.com/coryb/oreo"
|
||||
|
||||
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
|
||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
func CmdEpicCreateRegistry() *jiracli.CommandRegistryEntry {
|
||||
opts := CreateOptions{
|
||||
CommonOptions: jiracli.CommonOptions{
|
||||
Template: figtree.NewStringOption("epic-create"),
|
||||
},
|
||||
Overrides: map[string]string{},
|
||||
}
|
||||
|
||||
return &jiracli.CommandRegistryEntry{
|
||||
"Create Epic",
|
||||
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
|
||||
jiracli.LoadConfigs(cmd, fig, &opts)
|
||||
return CmdEpicCreateUsage(cmd, &opts)
|
||||
},
|
||||
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
|
||||
return CmdCreate(o, globals, &opts)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func CmdEpicCreateUsage(cmd *kingpin.CmdClause, opts *CreateOptions) 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("project", "project to create epic in").Short('p').StringVar(&opts.Project)
|
||||
cmd.Flag("epic-name", "Epic Name").Short('n').PreAction(func(ctx *kingpin.ParseContext) error {
|
||||
opts.Overrides["epic-name"] = jiracli.FlagValue(ctx, "epic-name")
|
||||
return nil
|
||||
}).String()
|
||||
cmd.Flag("comment", "Comment message for epic").Short('m').PreAction(func(ctx *kingpin.ParseContext) error {
|
||||
opts.Overrides["comment"] = jiracli.FlagValue(ctx, "comment")
|
||||
return nil
|
||||
}).String()
|
||||
cmd.Flag("override", "Set epic property").Short('o').StringMapVar(&opts.Overrides)
|
||||
cmd.Flag("saveFile", "Write epic as yaml to file").StringVar(&opts.SaveFile)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package jiracmd
|
||||
|
||||
import (
|
||||
"github.com/coryb/figtree"
|
||||
"github.com/coryb/oreo"
|
||||
"gopkg.in/Netflix-Skunkworks/go-jira.v1"
|
||||
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
|
||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
type EpicListOptions struct {
|
||||
ListOptions `yaml:",inline" json:",inline" figtree:",inline"`
|
||||
Epic string `yaml:"epic,omitempty" json:"epic,omitempty"`
|
||||
}
|
||||
|
||||
func CmdEpicListRegistry() *jiracli.CommandRegistryEntry {
|
||||
opts := EpicListOptions{
|
||||
ListOptions: ListOptions{
|
||||
CommonOptions: jiracli.CommonOptions{
|
||||
Template: figtree.NewStringOption("epic-list"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return &jiracli.CommandRegistryEntry{
|
||||
"Prints list of issues for an epic with optional search criteria",
|
||||
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
|
||||
jiracli.LoadConfigs(cmd, fig, &opts)
|
||||
if opts.MaxResults == 0 {
|
||||
opts.MaxResults = 500
|
||||
}
|
||||
if opts.QueryFields == "" {
|
||||
opts.QueryFields = "assignee,created,priority,reporter,status,summary,updated"
|
||||
}
|
||||
if opts.Sort == "" {
|
||||
opts.Sort = "priority asc, key"
|
||||
}
|
||||
return CmdEpicListUsage(cmd, &opts, fig)
|
||||
},
|
||||
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
|
||||
return CmdEpicList(o, globals, &opts)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func CmdEpicListUsage(cmd *kingpin.CmdClause, opts *EpicListOptions, fig *figtree.FigTree) error {
|
||||
CmdListUsage(cmd, &opts.ListOptions, fig)
|
||||
cmd.Arg("EPIC", "Epic Key or ID to list").Required().StringVar(&opts.Epic)
|
||||
return nil
|
||||
}
|
||||
|
||||
func CmdEpicList(o *oreo.Client, globals *jiracli.GlobalOptions, opts *EpicListOptions) error {
|
||||
data, err := jira.EpicSearch(o, globals.Endpoint.Value, opts.Epic, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return opts.PrintTemplate(data)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package jiracmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/coryb/figtree"
|
||||
"github.com/coryb/oreo"
|
||||
|
||||
"gopkg.in/Netflix-Skunkworks/go-jira.v1"
|
||||
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
|
||||
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
|
||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
type EpicRemoveOptions struct {
|
||||
jiradata.EpicIssues `yaml:",inline" json:",inline" figtree:",inline"`
|
||||
}
|
||||
|
||||
func CmdEpicRemoveRegistry() *jiracli.CommandRegistryEntry {
|
||||
opts := EpicRemoveOptions{}
|
||||
|
||||
return &jiracli.CommandRegistryEntry{
|
||||
"Remove issues from Epic",
|
||||
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
|
||||
jiracli.LoadConfigs(cmd, fig, &opts)
|
||||
return CmdEpicRemoveUsage(cmd, &opts)
|
||||
},
|
||||
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
|
||||
return CmdEpicRemove(o, globals, &opts)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func CmdEpicRemoveUsage(cmd *kingpin.CmdClause, opts *EpicRemoveOptions) error {
|
||||
cmd.Arg("ISSUE", "Issues to remove from any epic").Required().StringsVar(&opts.Issues)
|
||||
return nil
|
||||
}
|
||||
|
||||
func CmdEpicRemove(o *oreo.Client, globals *jiracli.GlobalOptions, opts *EpicRemoveOptions) error {
|
||||
if err := jira.EpicRemoveIssues(o, globals.Endpoint.Value, &opts.EpicIssues); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !globals.Quiet.Value {
|
||||
for _, issue := range opts.Issues {
|
||||
fmt.Printf("OK %s %s/browse/%s\n", issue, globals.Endpoint.Value, issue)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+15
-2
@@ -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,9 +52,19 @@ 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').PreAction(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)
|
||||
cmd.Flag("status", "Filter on issue status").Short('S').StringVar(&opts.Status)
|
||||
cmd.Flag("sort", "Sort order to return").Short('s').StringVar(&opts.Sort)
|
||||
cmd.Flag("watcher", "Watcher to search for").Short('w').StringVar(&opts.Watcher)
|
||||
return nil
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package jiradata
|
||||
|
||||
type EpicIssues struct {
|
||||
Issues []string `json:"issues,omitempty" yaml:"issues,omitempty"`
|
||||
}
|
||||
@@ -25,3 +25,7 @@ func (c *Comment) ProvideComment() *Comment {
|
||||
func (c *Component) ProvideComponent() *Component {
|
||||
return c
|
||||
}
|
||||
|
||||
func (e *EpicIssues) ProvideEpicIssues() *EpicIssues {
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -14,16 +14,17 @@ type SearchProvider interface {
|
||||
}
|
||||
|
||||
type SearchOptions struct {
|
||||
Assignee string
|
||||
Query string
|
||||
QueryFields string
|
||||
Project string
|
||||
Component string
|
||||
IssueType string
|
||||
Watcher string
|
||||
Reporter string
|
||||
Sort string
|
||||
MaxResults int
|
||||
Assignee string `yaml:"assignee,omitempty" json:"assignee,omitempty"`
|
||||
Query string `yaml:"query,omitempty" json:"query,omitempty"`
|
||||
QueryFields string `yaml:"query-fields,omitempty" json:"query-fields,omitempty"`
|
||||
Project string `yaml:"project,omitempty" json:"project,omitempty"`
|
||||
Component string `yaml:"component,omitempty" json:"component,omitempty"`
|
||||
IssueType string `yaml:"issue-type,omitempty" json:"issue-type,omitempty"`
|
||||
Watcher string `yaml:"watcher,omitempty" json:"watcher,omitempty"`
|
||||
Reporter string `yaml:"reporter,omitempty" json:"reporter,omitempty"`
|
||||
Status string `yaml:"status,omitempty" json:"status,omitempty"`
|
||||
Sort string `yaml:"sort,omitempty" json:"sort,omitempty"`
|
||||
MaxResults int `yaml:"max-results,omitempty" json:"max-results,omitempty"`
|
||||
}
|
||||
|
||||
func (o *SearchOptions) ProvideSearchRequest() *jiradata.SearchRequest {
|
||||
@@ -49,6 +50,9 @@ func (o *SearchOptions) ProvideSearchRequest() *jiradata.SearchRequest {
|
||||
if o.Reporter != "" {
|
||||
qbuff.WriteString(fmt.Sprintf(" AND reporter = '%s'", o.Reporter))
|
||||
}
|
||||
if o.Status != "" {
|
||||
qbuff.WriteString(fmt.Sprintf(" AND status = '%s'", o.Status))
|
||||
}
|
||||
if o.Sort != "" {
|
||||
qbuff.WriteString(fmt.Sprintf(" ORDER BY %s", o.Sort))
|
||||
}
|
||||
|
||||
@@ -46,15 +46,7 @@ EOF
|
||||
###############################################################################
|
||||
|
||||
RUNS $jira env
|
||||
DIFF <<'EOF'
|
||||
JIRACLOUD=1
|
||||
JIRA_CUSTOM_COMMANDS=[{"name":"env","script":"env | sort | grep JIRA","help":"print the JIRA environment variables available to custom commands"},{"name":"print-project","script":"echo $JIRA_PROJECT","help":"print the name of the configured project"},{"name":"jira-path","script":"echo {{jira}}","help":"print the path the jira command that is running this alias"},{"name":"mine","script":"if [ -n \"$JIRA_PROJECT\" ]; then\n # if `project: ...` configured just list the issues for current project\n {{jira}} list --template table --query \"resolution = unresolved and assignee=currentuser() and project = $JIRA_PROJECT ORDER BY priority asc, created\"\nelse\n # otherwise list issues for all project\n {{jira}} list --template table --query \"resolution = unresolved and assignee=currentuser() ORDER BY priority asc, created\"\nfi","help":"display issues assigned to me"},{"name":"argtest","args":[{"name":"ARG","help":"string to echo for testing"}],"script":"echo {{args.ARG}}","help":"testing passing args"},{"name":"opttest","options":[{"name":"OPT","help":"string to echo for testing"}],"script":"echo {{options.OPT}}","help":"testing passing option flags"}]
|
||||
JIRA_ENDPOINT=https://go-jira.atlassian.net
|
||||
JIRA_LOG_FORMAT=%{level:-5s} %{message}
|
||||
JIRA_PASSWORD_SOURCE=pass
|
||||
JIRA_PROJECT=BASIC
|
||||
JIRA_USER=gojira
|
||||
EOF
|
||||
GREP ^JIRA_PROJECT=BASIC
|
||||
|
||||
###############################################################################
|
||||
## Testing the example custom commands, argtest
|
||||
|
||||
Executable
+121
@@ -0,0 +1,121 @@
|
||||
#!/bin/bash
|
||||
eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
|
||||
cd $(dirname $0)
|
||||
jira="../jira"
|
||||
. env.sh
|
||||
|
||||
PLAN 22
|
||||
|
||||
# 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 epic
|
||||
###############################################################################
|
||||
RUNS $jira epic create --project BASIC -o summary="Totally Epic" -o description=description --epic-name "Basic Epic" --noedit --saveFile issue.props
|
||||
epic=$(awk '/issue/{print $2}' issue.props)
|
||||
|
||||
DIFF <<EOF
|
||||
OK $epic $ENDPOINT/browse/$epic
|
||||
EOF
|
||||
|
||||
###############################################################################
|
||||
## Create issues we can assign to epic
|
||||
###############################################################################
|
||||
RUNS $jira create --project BASIC -o summary="summary" -o description=description --noedit --saveFile issue.props
|
||||
issue1=$(awk '/issue/{print $2}' issue.props)
|
||||
|
||||
DIFF <<EOF
|
||||
OK $issue1 $ENDPOINT/browse/$issue1
|
||||
EOF
|
||||
|
||||
RUNS $jira create --project BASIC -o summary="summary" -o description=description --noedit --saveFile issue.props
|
||||
issue2=$(awk '/issue/{print $2}' issue.props)
|
||||
|
||||
DIFF <<EOF
|
||||
OK $issue2 $ENDPOINT/browse/$issue2
|
||||
EOF
|
||||
|
||||
###############################################################################
|
||||
## List the issues for the epic
|
||||
###############################################################################
|
||||
RUNS $jira epic list $epic
|
||||
|
||||
DIFF<<EOF
|
||||
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
|
||||
| Issue | Summary | Priority | Status | Age | Reporter | Assignee |
|
||||
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
|
||||
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
|
||||
EOF
|
||||
|
||||
###############################################################################
|
||||
## Add issues to an epic
|
||||
###############################################################################
|
||||
RUNS $jira epic add $epic $issue1 $issue2
|
||||
|
||||
DIFF<<EOF
|
||||
OK $epic $ENDPOINT/browse/$epic
|
||||
OK $issue1 $ENDPOINT/browse/$issue1
|
||||
OK $issue2 $ENDPOINT/browse/$issue2
|
||||
EOF
|
||||
|
||||
###############################################################################
|
||||
## List the issues for the epic
|
||||
###############################################################################
|
||||
RUNS $jira epic list $epic
|
||||
|
||||
DIFF<<EOF
|
||||
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
|
||||
| Issue | Summary | Priority | Status | Age | Reporter | Assignee |
|
||||
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
|
||||
| $(printf %-14s $issue1) | summary | Medium | To Do | a minute | gojira | gojira |
|
||||
| $(printf %-14s $issue2) | summary | Medium | To Do | a minute | gojira | gojira |
|
||||
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
|
||||
EOF
|
||||
|
||||
###############################################################################
|
||||
## Remove an issue from an Epic
|
||||
###############################################################################
|
||||
RUNS $jira epic remove $issue1
|
||||
|
||||
DIFF<<EOF
|
||||
OK $issue1 $ENDPOINT/browse/$issue1
|
||||
EOF
|
||||
|
||||
###############################################################################
|
||||
## List the issues for the epic
|
||||
###############################################################################
|
||||
RUNS $jira epic list $epic
|
||||
|
||||
DIFF<<EOF
|
||||
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
|
||||
| Issue | Summary | Priority | Status | Age | Reporter | Assignee |
|
||||
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
|
||||
| $(printf %-14s $issue2) | summary | Medium | To Do | a minute | gojira | gojira |
|
||||
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
|
||||
EOF
|
||||
|
||||
###############################################################################
|
||||
## Remove last issue from an Epic
|
||||
###############################################################################
|
||||
RUNS $jira epic remove $issue2
|
||||
|
||||
DIFF<<EOF
|
||||
OK $issue2 $ENDPOINT/browse/$issue2
|
||||
EOF
|
||||
|
||||
###############################################################################
|
||||
## List the issues for the epic
|
||||
###############################################################################
|
||||
RUNS $jira epic list $epic
|
||||
|
||||
DIFF<<EOF
|
||||
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
|
||||
| Issue | Summary | Priority | Status | Age | Reporter | Assignee |
|
||||
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
|
||||
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
|
||||
EOF
|
||||
+73
@@ -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
|
||||
+47
@@ -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"
|
||||
+8
@@ -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
|
||||
|
||||
-36
@@ -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
|
||||
-18
@@ -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
|
||||
Reference in New Issue
Block a user