mirror of
https://github.com/Threnklyn/jira.git
synced 2026-05-18 20:23:28 +02:00
update for golint
This commit is contained in:
@@ -23,10 +23,12 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
log = logging.MustGetLogger("jira")
|
||||
log = logging.MustGetLogger("jira")
|
||||
// VERSION is the go-jira library version
|
||||
VERSION string
|
||||
)
|
||||
|
||||
// Cli is go-jira client object
|
||||
type Cli struct {
|
||||
endpoint *url.URL
|
||||
opts map[string]interface{}
|
||||
@@ -34,6 +36,7 @@ type Cli struct {
|
||||
ua *http.Client
|
||||
}
|
||||
|
||||
// New creates go-jira client object
|
||||
func New(opts map[string]interface{}) *Cli {
|
||||
homedir := homedir()
|
||||
cookieJar, _ := cookiejar.New(nil)
|
||||
@@ -120,7 +123,7 @@ func (c *Cli) loadCookies() []*http.Cookie {
|
||||
log.Errorf("Failed to open %s: %s", c.cookieFile, err)
|
||||
panic(err)
|
||||
}
|
||||
cookies := make([]*http.Cookie, 0)
|
||||
cookies := []*http.Cookie{}
|
||||
err = json.Unmarshal(bytes, &cookies)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to parse json from file %s: %s", c.cookieFile, err)
|
||||
@@ -140,44 +143,42 @@ func (c *Cli) put(uri string, content string) (*http.Response, error) {
|
||||
return c.makeRequestWithContent("PUT", uri, content)
|
||||
}
|
||||
|
||||
func (c *Cli) delete(uri string) (*http.Response, error) {
|
||||
func (c *Cli) delete(uri string) (resp *http.Response, err error) {
|
||||
method := "DELETE"
|
||||
req, _ := http.NewRequest(method, uri, nil)
|
||||
log.Infof("%s %s", req.Method, req.URL.String())
|
||||
if resp, err := c.makeRequest(req); err != nil {
|
||||
if resp, err = c.makeRequest(req); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if resp.StatusCode == 401 {
|
||||
if err := c.CmdLogin(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req, _ = http.NewRequest(method, uri, nil)
|
||||
return c.makeRequest(req)
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
if resp.StatusCode == 401 {
|
||||
if err = c.CmdLogin(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req, _ = http.NewRequest(method, uri, nil)
|
||||
return c.makeRequest(req)
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (c *Cli) makeRequestWithContent(method string, uri string, content string) (*http.Response, error) {
|
||||
func (c *Cli) makeRequestWithContent(method string, uri string, content string) (resp *http.Response, err error) {
|
||||
buffer := bytes.NewBufferString(content)
|
||||
req, _ := http.NewRequest(method, uri, buffer)
|
||||
|
||||
log.Infof("%s %s", req.Method, req.URL.String())
|
||||
if resp, err := c.makeRequest(req); err != nil {
|
||||
if resp, err = c.makeRequest(req); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if resp.StatusCode == 401 {
|
||||
if err := c.CmdLogin(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req, _ = http.NewRequest(method, uri, bytes.NewBufferString(content))
|
||||
return c.makeRequest(req)
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
if resp.StatusCode == 401 {
|
||||
if err = c.CmdLogin(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req, _ = http.NewRequest(method, uri, bytes.NewBufferString(content))
|
||||
return c.makeRequest(req)
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (c *Cli) get(uri string) (*http.Response, error) {
|
||||
func (c *Cli) get(uri string) (resp *http.Response, err error) {
|
||||
req, _ := http.NewRequest("GET", uri, nil)
|
||||
log.Infof("%s %s", req.Method, req.URL.String())
|
||||
if log.IsEnabledFor(logging.DEBUG) {
|
||||
@@ -186,17 +187,16 @@ func (c *Cli) get(uri string) (*http.Response, error) {
|
||||
log.Debugf("%s", logBuffer)
|
||||
}
|
||||
|
||||
if resp, err := c.makeRequest(req); err != nil {
|
||||
if resp, err = c.makeRequest(req); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if resp.StatusCode == 401 {
|
||||
if err := c.CmdLogin(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.makeRequest(req)
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
if resp.StatusCode == 401 {
|
||||
if err := c.CmdLogin(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.makeRequest(req)
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (c *Cli) makeRequest(req *http.Request) (resp *http.Response, err error) {
|
||||
@@ -217,18 +217,17 @@ func (c *Cli) makeRequest(req *http.Request) (resp *http.Response, err error) {
|
||||
if resp, err = c.ua.Do(req); err != nil {
|
||||
log.Errorf("Failed to %s %s: %s", req.Method, req.URL.String(), err)
|
||||
return nil, err
|
||||
} else {
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 && resp.StatusCode != 401 {
|
||||
log.Errorf("response status: %s", resp.Status)
|
||||
}
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 && resp.StatusCode != 401 {
|
||||
log.Errorf("response status: %s", resp.Status)
|
||||
}
|
||||
|
||||
runtime.SetFinalizer(resp, func(r *http.Response) {
|
||||
r.Body.Close()
|
||||
})
|
||||
runtime.SetFinalizer(resp, func(r *http.Response) {
|
||||
r.Body.Close()
|
||||
})
|
||||
|
||||
if _, ok := resp.Header["Set-Cookie"]; ok {
|
||||
c.saveCookies(resp)
|
||||
}
|
||||
if _, ok := resp.Header["Set-Cookie"]; ok {
|
||||
c.saveCookies(resp)
|
||||
}
|
||||
if log.IsEnabledFor(logging.DEBUG) {
|
||||
out, _ := httputil.DumpResponse(resp, true)
|
||||
@@ -237,6 +236,7 @@ func (c *Cli) makeRequest(req *http.Request) (resp *http.Response, err error) {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetTemplate will return the text/template for the given command name
|
||||
func (c *Cli) GetTemplate(name string) string {
|
||||
return c.getTemplate(name)
|
||||
}
|
||||
@@ -256,10 +256,9 @@ func (c *Cli) getTemplate(name string) string {
|
||||
if override, ok := c.opts["template"].(string); ok {
|
||||
if _, err := os.Stat(override); err == nil {
|
||||
return readFile(override)
|
||||
} else {
|
||||
if t := getLookedUpTemplate(override, all_templates[override]); t != "" {
|
||||
return t
|
||||
}
|
||||
}
|
||||
if t := getLookedUpTemplate(override, allTemplates[override]); t != "" {
|
||||
return t
|
||||
}
|
||||
}
|
||||
// create-bug etc are special, if we dont find it in the path
|
||||
@@ -267,9 +266,11 @@ func (c *Cli) getTemplate(name string) string {
|
||||
if strings.HasPrefix(name, "create-") {
|
||||
return getLookedUpTemplate(name, c.getTemplate("create"))
|
||||
}
|
||||
return getLookedUpTemplate(name, all_templates[name])
|
||||
return getLookedUpTemplate(name, allTemplates[name])
|
||||
}
|
||||
|
||||
// NoChangesFound is an error returned from when editing templates
|
||||
// and no modifications were made while editing
|
||||
type NoChangesFound struct{}
|
||||
|
||||
func (f NoChangesFound) Error() string {
|
||||
@@ -360,27 +361,27 @@ func (c *Cli) editTemplate(template string, tmpFilePrefix string, templateData m
|
||||
}
|
||||
|
||||
edited := make(map[string]interface{})
|
||||
if fh, err := ioutil.ReadFile(tmpFileName); err != nil {
|
||||
var data []byte
|
||||
if data, err = ioutil.ReadFile(tmpFileName); err != nil {
|
||||
log.Errorf("Failed to read tmpfile %s: %s", tmpFileName, err)
|
||||
if editing && promptYN("edit again?", true) {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
} else {
|
||||
if err := yaml.Unmarshal(fh, &edited); err != nil {
|
||||
log.Errorf("Failed to parse YAML: %s", err)
|
||||
if editing && promptYN("edit again?", true) {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
if err := yaml.Unmarshal(data, &edited); err != nil {
|
||||
log.Errorf("Failed to parse YAML: %s", err)
|
||||
if editing && promptYN("edit again?", true) {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if fixed, err := yamlFixup(edited); err != nil {
|
||||
var fixed interface{}
|
||||
if fixed, err = yamlFixup(edited); err != nil {
|
||||
return err
|
||||
} else {
|
||||
edited = fixed.(map[string]interface{})
|
||||
}
|
||||
edited = fixed.(map[string]interface{})
|
||||
|
||||
// if you want to abort editing a jira issue then
|
||||
// you can add the "abort: true" flag to the document
|
||||
@@ -422,6 +423,7 @@ func (c *Cli) editTemplate(template string, tmpFilePrefix string, templateData m
|
||||
return nil
|
||||
}
|
||||
|
||||
// Browse will open up your default browser to the provided issue
|
||||
func (c *Cli) Browse(issue string) error {
|
||||
if val, ok := c.opts["browse"].(bool); ok && val {
|
||||
if runtime.GOOS == "darwin" {
|
||||
@@ -433,6 +435,7 @@ func (c *Cli) Browse(issue string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveData will write out the yaml formated --saveFile file with provided data
|
||||
func (c *Cli) SaveData(data interface{}) error {
|
||||
if val, ok := c.opts["saveFile"].(string); ok && val != "" {
|
||||
yamlWrite(val, data)
|
||||
@@ -440,33 +443,39 @@ func (c *Cli) SaveData(data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ViewIssue will return the details for the given issue id
|
||||
func (c *Cli) ViewIssue(issue string) (interface{}, error) {
|
||||
uri := fmt.Sprintf("%s/rest/api/2/issue/%s", c.endpoint, issue)
|
||||
if x := c.expansions(); len(x) > 0 {
|
||||
uri = fmt.Sprintf("%s?expand=%s", uri, strings.Join(x, ","))
|
||||
}
|
||||
|
||||
data, err := responseToJson(c.get(uri))
|
||||
data, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return data, nil
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// FindIssues will return a list of issues that match the given options.
|
||||
// If the "query" option is undefined it will generate a JQL query
|
||||
// using any/all of the provide options: project, component, assignee,
|
||||
// issuetype, watcher, reporter, sort
|
||||
// Further it will restrict the fields being extracted from the jira
|
||||
// response with the 'queryfields' option
|
||||
func (c *Cli) FindIssues() (interface{}, error) {
|
||||
var query string
|
||||
var ok bool
|
||||
// project = BAKERY and status not in (Resolved, Closed)
|
||||
if query, ok = c.opts["query"].(string); !ok {
|
||||
qbuff := bytes.NewBufferString("resolution = unresolved")
|
||||
if project, ok := c.opts["project"]; !ok {
|
||||
var project string
|
||||
if project, ok = c.opts["project"].(string); !ok {
|
||||
err := fmt.Errorf("Missing required arguments, either 'query' or 'project' are required")
|
||||
log.Errorf("%s", err)
|
||||
return nil, err
|
||||
} else {
|
||||
qbuff.WriteString(fmt.Sprintf(" AND project = '%s'", project))
|
||||
}
|
||||
qbuff.WriteString(fmt.Sprintf(" AND project = '%s'", project))
|
||||
|
||||
if component, ok := c.opts["component"]; ok {
|
||||
qbuff.WriteString(fmt.Sprintf(" AND component = '%s'", component))
|
||||
@@ -495,11 +504,9 @@ func (c *Cli) FindIssues() (interface{}, error) {
|
||||
query = qbuff.String()
|
||||
}
|
||||
|
||||
fields := make([]string, 0)
|
||||
fields := []string{"summary"}
|
||||
if qf, ok := c.opts["queryfields"].(string); ok {
|
||||
fields = strings.Split(qf, ",")
|
||||
} else {
|
||||
fields = append(fields, "summary")
|
||||
}
|
||||
|
||||
json, err := jsonEncode(map[string]interface{}{
|
||||
@@ -514,13 +521,15 @@ func (c *Cli) FindIssues() (interface{}, error) {
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("%s/rest/api/2/search", c.endpoint)
|
||||
if data, err := responseToJson(c.post(uri, json)); err != nil {
|
||||
var data interface{}
|
||||
if data, err = responseToJSON(c.post(uri, json)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return data, nil
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// GetOptString will extract the string from the Cli object options
|
||||
// otherwise return the provided default
|
||||
func (c *Cli) GetOptString(optName string, dflt string) string {
|
||||
return c.getOptString(optName, dflt)
|
||||
}
|
||||
@@ -528,11 +537,12 @@ func (c *Cli) GetOptString(optName string, dflt string) string {
|
||||
func (c *Cli) getOptString(optName string, dflt string) string {
|
||||
if val, ok := c.opts[optName].(string); ok {
|
||||
return val
|
||||
} else {
|
||||
return dflt
|
||||
}
|
||||
return dflt
|
||||
}
|
||||
|
||||
// GetOptBool will extract the boolean value from the Client object options
|
||||
// otherwise return the provided default\
|
||||
func (c *Cli) GetOptBool(optName string, dflt bool) bool {
|
||||
return c.getOptBool(optName, dflt)
|
||||
}
|
||||
@@ -540,14 +550,13 @@ func (c *Cli) GetOptBool(optName string, dflt bool) bool {
|
||||
func (c *Cli) getOptBool(optName string, dflt bool) bool {
|
||||
if val, ok := c.opts[optName].(bool); ok {
|
||||
return val
|
||||
} else {
|
||||
return dflt
|
||||
}
|
||||
return dflt
|
||||
}
|
||||
|
||||
// expansions returns a comma-separated list of values for field expansion
|
||||
func (c *Cli) expansions() []string {
|
||||
expansions := make([]string, 0)
|
||||
var expansions []string
|
||||
if x, ok := c.opts["expand"].(string); ok {
|
||||
expansions = strings.Split(x, ",")
|
||||
}
|
||||
|
||||
+139
-116
@@ -3,7 +3,6 @@ package jira
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/Netflix-Skunkworks/go-jira/data"
|
||||
"github.com/howeyc/gopass"
|
||||
@@ -15,9 +14,10 @@ import (
|
||||
// "github.com/kr/pretty"
|
||||
)
|
||||
|
||||
// CmdLogin will attempt to login into jira server
|
||||
func (c *Cli) CmdLogin() error {
|
||||
uri := fmt.Sprintf("%s/rest/auth/1/session", c.endpoint)
|
||||
for true {
|
||||
for {
|
||||
req, _ := http.NewRequest("GET", uri, nil)
|
||||
user, _ := c.opts["user"].(string)
|
||||
|
||||
@@ -29,60 +29,63 @@ func (c *Cli) CmdLogin() error {
|
||||
passwd := string(pw)
|
||||
|
||||
req.SetBasicAuth(user, passwd)
|
||||
if resp, err := c.makeRequest(req); err != nil {
|
||||
|
||||
resp, err := c.makeRequest(req)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
if resp.StatusCode == 403 {
|
||||
// probably got this, need to redirect the user to login manually
|
||||
// X-Authentication-Denied-Reason: CAPTCHA_CHALLENGE; login-url=https://jira/login.jsp
|
||||
if reason := resp.Header.Get("X-Authentication-Denied-Reason"); reason != "" {
|
||||
err := fmt.Errorf("Authenticaion Failed: %s", reason)
|
||||
log.Errorf("%s", err)
|
||||
return err
|
||||
}
|
||||
err := fmt.Errorf("Authentication Failed: Unknown Reason")
|
||||
}
|
||||
if resp.StatusCode == 403 {
|
||||
// probably got this, need to redirect the user to login manually
|
||||
// X-Authentication-Denied-Reason: CAPTCHA_CHALLENGE; login-url=https://jira/login.jsp
|
||||
if reason := resp.Header.Get("X-Authentication-Denied-Reason"); reason != "" {
|
||||
err := fmt.Errorf("Authenticaion Failed: %s", reason)
|
||||
log.Errorf("%s", err)
|
||||
return err
|
||||
}
|
||||
err := fmt.Errorf("Authentication Failed: Unknown Reason")
|
||||
log.Errorf("%s", err)
|
||||
return err
|
||||
|
||||
} else if resp.StatusCode == 200 {
|
||||
// https://confluence.atlassian.com/display/JIRA043/JIRA+REST+API+%28Alpha%29+Tutorial#JIRARESTAPI%28Alpha%29Tutorial-CAPTCHAs
|
||||
// probably bad password, try again
|
||||
if reason := resp.Header.Get("X-Seraph-Loginreason"); reason == "AUTHENTICATION_DENIED" {
|
||||
log.Warning("Authentication Failed: %s", reason)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
log.Warning("Login failed")
|
||||
} else if resp.StatusCode == 200 {
|
||||
// https://confluence.atlassian.com/display/JIRA043/JIRA+REST+API+%28Alpha%29+Tutorial#JIRARESTAPI%28Alpha%29Tutorial-CAPTCHAs
|
||||
// probably bad password, try again
|
||||
if reason := resp.Header.Get("X-Seraph-Loginreason"); reason == "AUTHENTICATION_DENIED" {
|
||||
log.Warning("Authentication Failed: %s", reason)
|
||||
continue
|
||||
}
|
||||
break
|
||||
} else {
|
||||
log.Warning("Login failed")
|
||||
continue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdLogout will close any active sessions
|
||||
func (c *Cli) CmdLogout() error {
|
||||
uri := fmt.Sprintf("%s/rest/auth/1/session", c.endpoint)
|
||||
req, _ := http.NewRequest("DELETE", uri, nil)
|
||||
if resp, err := c.makeRequest(req); err != nil {
|
||||
resp, err := c.makeRequest(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode == 401 || resp.StatusCode == 204 {
|
||||
// 401 == no active session
|
||||
// 204 == successfully logged out
|
||||
} else {
|
||||
if resp.StatusCode == 401 || resp.StatusCode == 204 {
|
||||
// 401 == no active session
|
||||
// 204 == successfully logged out
|
||||
} else {
|
||||
err := fmt.Errorf("Failed to Logout: %s", err)
|
||||
return err
|
||||
}
|
||||
err := fmt.Errorf("Failed to Logout: %s", err)
|
||||
return err
|
||||
}
|
||||
log.Notice("OK")
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdFields will send data from /rest/api/2/field API to "fields" template
|
||||
func (c *Cli) CmdFields() error {
|
||||
log.Debugf("fields called")
|
||||
uri := fmt.Sprintf("%s/rest/api/2/field", c.endpoint)
|
||||
data, err := responseToJson(c.get(uri))
|
||||
data, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -90,15 +93,17 @@ func (c *Cli) CmdFields() error {
|
||||
return runTemplate(c.getTemplate("fields"), data, nil)
|
||||
}
|
||||
|
||||
// CmdList will query jira and send data to "list" template
|
||||
func (c *Cli) CmdList() error {
|
||||
log.Debugf("list called")
|
||||
if data, err := c.FindIssues(); err != nil {
|
||||
data, err := c.FindIssues()
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
return runTemplate(c.getTemplate("list"), data, nil)
|
||||
}
|
||||
return runTemplate(c.getTemplate("list"), data, nil)
|
||||
}
|
||||
|
||||
// CmdView will get issue data and send to "view" template
|
||||
func (c *Cli) CmdView(issue string) error {
|
||||
log.Debugf("view called")
|
||||
c.Browse(issue)
|
||||
@@ -109,23 +114,23 @@ func (c *Cli) CmdView(issue string) error {
|
||||
return runTemplate(c.getTemplate("view"), data, nil)
|
||||
}
|
||||
|
||||
// CmdEdit will populate "edit" template with issue data and issue "editmeta" data.
|
||||
// Then will parse yaml template and submit data to jira.
|
||||
func (c *Cli) CmdEdit(issue string) error {
|
||||
log.Debugf("edit called")
|
||||
|
||||
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/editmeta", c.endpoint, issue)
|
||||
editmeta, err := responseToJson(c.get(uri))
|
||||
editmeta, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uri = fmt.Sprintf("%s/rest/api/2/issue/%s", c.endpoint, issue)
|
||||
var issueData map[string]interface{}
|
||||
if data, err := responseToJson(c.get(uri)); err != nil {
|
||||
data, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
issueData = data.(map[string]interface{})
|
||||
}
|
||||
|
||||
issueData := data.(map[string]interface{})
|
||||
issueData["meta"] = editmeta.(map[string]interface{})
|
||||
issueData["overrides"] = c.opts
|
||||
|
||||
@@ -150,22 +155,22 @@ func (c *Cli) CmdEdit(issue string) error {
|
||||
fmt.Printf("OK %s %s/browse/%s\n", issueData["key"], c.endpoint, issueData["key"])
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
logBuffer := bytes.NewBuffer(make([]byte, 0))
|
||||
resp.Write(logBuffer)
|
||||
err := fmt.Errorf("Unexpected Response From PUT")
|
||||
log.Errorf("%s:\n%s", err, logBuffer)
|
||||
return err
|
||||
}
|
||||
logBuffer := bytes.NewBuffer(make([]byte, 0))
|
||||
resp.Write(logBuffer)
|
||||
err = fmt.Errorf("Unexpected Response From PUT")
|
||||
log.Errorf("%s:\n%s", err, logBuffer)
|
||||
return err
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// CmdEditMeta will send issue 'edit' metadata to the "editmeta" template
|
||||
func (c *Cli) CmdEditMeta(issue string) error {
|
||||
log.Debugf("editMeta called")
|
||||
c.Browse(issue)
|
||||
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/editmeta", c.endpoint, issue)
|
||||
data, err := responseToJson(c.get(uri))
|
||||
data, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -173,11 +178,12 @@ func (c *Cli) CmdEditMeta(issue string) error {
|
||||
return runTemplate(c.getTemplate("editmeta"), data, nil)
|
||||
}
|
||||
|
||||
// CmdTransitionMeta will send available transition metadata to the "transmeta" template
|
||||
func (c *Cli) CmdTransitionMeta(issue string) error {
|
||||
log.Debugf("tranisionMeta called")
|
||||
c.Browse(issue)
|
||||
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/transitions?expand=transitions.fields", c.endpoint, issue)
|
||||
data, err := responseToJson(c.get(uri))
|
||||
data, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -185,11 +191,12 @@ func (c *Cli) CmdTransitionMeta(issue string) error {
|
||||
return runTemplate(c.getTemplate("transmeta"), data, nil)
|
||||
}
|
||||
|
||||
// CmdIssueTypes will send issue 'create' metadata to the 'issuetypes'
|
||||
func (c *Cli) CmdIssueTypes() error {
|
||||
project := c.opts["project"].(string)
|
||||
log.Debugf("issueTypes called")
|
||||
uri := fmt.Sprintf("%s/rest/api/2/issue/createmeta?projectKeys=%s", c.endpoint, project)
|
||||
data, err := responseToJson(c.get(uri))
|
||||
data, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -200,7 +207,7 @@ func (c *Cli) CmdIssueTypes() error {
|
||||
func (c *Cli) defaultIssueType() string {
|
||||
project := c.opts["project"].(string)
|
||||
uri := fmt.Sprintf("%s/rest/api/2/issue/createmeta?projectKeys=%s", c.endpoint, project)
|
||||
data, _ := responseToJson(c.get(uri))
|
||||
data, _ := responseToJSON(c.get(uri))
|
||||
issueTypeNames := make(map[string]bool)
|
||||
|
||||
if data, ok := data.(map[string]interface{}); ok {
|
||||
@@ -226,6 +233,7 @@ func (c *Cli) defaultIssueType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// CmdCreateMeta sends the 'create' metadata for the given project & issuetype and sends it to the 'createmeta' template
|
||||
func (c *Cli) CmdCreateMeta() error {
|
||||
project := c.opts["project"].(string)
|
||||
issuetype := c.getOptString("issuetype", "")
|
||||
@@ -235,7 +243,7 @@ func (c *Cli) CmdCreateMeta() error {
|
||||
|
||||
log.Debugf("createMeta called")
|
||||
uri := fmt.Sprintf("%s/rest/api/2/issue/createmeta?projectKeys=%s&issuetypeNames=%s&expand=projects.issuetypes.fields", c.endpoint, project, url.QueryEscape(issuetype))
|
||||
data, err := responseToJson(c.get(uri))
|
||||
data, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -254,16 +262,18 @@ func (c *Cli) CmdCreateMeta() error {
|
||||
return runTemplate(c.getTemplate("createmeta"), data, nil)
|
||||
}
|
||||
|
||||
// CmdComponents sends component data for given project and sends to the "components" template
|
||||
func (c *Cli) CmdComponents(project string) error {
|
||||
log.Debugf("Components called")
|
||||
uri := fmt.Sprintf("%s/rest/api/2/project/%s/components", c.endpoint, project)
|
||||
data, err := responseToJson(c.get(uri))
|
||||
data, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return runTemplate(c.getTemplate("components"), data, nil)
|
||||
}
|
||||
|
||||
// ValidTransitions will return a list of valid transitions for given issue.
|
||||
func (c *Cli) ValidTransitions(issue string) (jiradata.Transitions, error) {
|
||||
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/transitions?expand=transitions.fields", c.endpoint, issue)
|
||||
resp, err := c.get(uri)
|
||||
@@ -284,18 +294,21 @@ func (c *Cli) ValidTransitions(issue string) (jiradata.Transitions, error) {
|
||||
return transMeta.Transitions, nil
|
||||
}
|
||||
|
||||
// CmdTransitions sends valid transtions for given issue to the "transitions" template
|
||||
func (c *Cli) CmdTransitions(issue string) error {
|
||||
log.Debugf("Transitions called")
|
||||
// FIXME this should just call ValidTransitions then pass that data to templates
|
||||
c.Browse(issue)
|
||||
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/transitions", c.endpoint, issue)
|
||||
data, err := responseToJson(c.get(uri))
|
||||
data, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return runTemplate(c.getTemplate("transitions"), data, nil)
|
||||
}
|
||||
|
||||
// CmdCreate sends the create-metadata to the "create" template for editing, then
|
||||
// will parse the edited document as YAML and submit the document to jira.
|
||||
func (c *Cli) CmdCreate() error {
|
||||
log.Debugf("create called")
|
||||
project := c.opts["project"].(string)
|
||||
@@ -305,7 +318,7 @@ func (c *Cli) CmdCreate() error {
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("%s/rest/api/2/issue/createmeta?projectKeys=%s&issuetypeNames=%s&expand=projects.issuetypes.fields", c.endpoint, project, url.QueryEscape(issuetype))
|
||||
data, err := responseToJson(c.get(uri))
|
||||
data, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -349,42 +362,43 @@ func (c *Cli) CmdCreate() error {
|
||||
|
||||
if resp.StatusCode == 201 {
|
||||
// response: {"id":"410836","key":"PROJ-238","self":"https://jira/rest/api/2/issue/410836"}
|
||||
if json, err := responseToJson(resp, nil); err != nil {
|
||||
json, err := responseToJSON(resp, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
key := json.(map[string]interface{})["key"].(string)
|
||||
link := fmt.Sprintf("%s/browse/%s", c.endpoint, key)
|
||||
c.Browse(key)
|
||||
c.SaveData(map[string]string{
|
||||
"issue": key,
|
||||
"link": link,
|
||||
})
|
||||
if !c.opts["quiet"].(bool) {
|
||||
fmt.Printf("OK %s %s\n", key, link)
|
||||
}
|
||||
}
|
||||
key := json.(map[string]interface{})["key"].(string)
|
||||
link := fmt.Sprintf("%s/browse/%s", c.endpoint, key)
|
||||
c.Browse(key)
|
||||
c.SaveData(map[string]string{
|
||||
"issue": key,
|
||||
"link": link,
|
||||
})
|
||||
if !c.opts["quiet"].(bool) {
|
||||
fmt.Printf("OK %s %s\n", key, link)
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
logBuffer := bytes.NewBuffer(make([]byte, 0))
|
||||
resp.Write(logBuffer)
|
||||
err := fmt.Errorf("Unexpected Response From POST")
|
||||
log.Errorf("%s:\n%s", err, logBuffer)
|
||||
return err
|
||||
}
|
||||
logBuffer := bytes.NewBuffer(make([]byte, 0))
|
||||
resp.Write(logBuffer)
|
||||
err = fmt.Errorf("Unexpected Response From POST")
|
||||
log.Errorf("%s:\n%s", err, logBuffer)
|
||||
return err
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// CmdIssueLinkTypes will send the issue link type data to the "issuelinktypes" template.
|
||||
func (c *Cli) CmdIssueLinkTypes() error {
|
||||
log.Debugf("Transitions called")
|
||||
uri := fmt.Sprintf("%s/rest/api/2/issueLinkType", c.endpoint)
|
||||
data, err := responseToJson(c.get(uri))
|
||||
data, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return runTemplate(c.getTemplate("issuelinktypes"), data, nil)
|
||||
}
|
||||
|
||||
// CmdBlocks will update the given issue as being "blocked" by the given blocker
|
||||
func (c *Cli) CmdBlocks(blocker string, issue string) error {
|
||||
log.Debugf("blocks called")
|
||||
|
||||
@@ -428,6 +442,8 @@ func (c *Cli) CmdBlocks(blocker string, issue string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdDups will update the given issue as being a duplicate by the given dup issue
|
||||
// and will attempt to resolve the dup issue
|
||||
func (c *Cli) CmdDups(duplicate string, issue string) error {
|
||||
log.Debugf("dups called")
|
||||
|
||||
@@ -471,6 +487,8 @@ func (c *Cli) CmdDups(duplicate string, issue string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdWatch will add the given watcher to the issue (or remove the watcher
|
||||
// given the 'remove' flag)
|
||||
func (c *Cli) CmdWatch(issue string, watcher string, remove bool) error {
|
||||
log.Debugf("watch called: watcher: %q, remove: %n", watcher, remove)
|
||||
|
||||
@@ -521,6 +539,7 @@ func (c *Cli) CmdWatch(issue string, watcher string, remove bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdVote will add or remove a vote on an issue
|
||||
func (c *Cli) CmdVote(issue string, up bool) error {
|
||||
log.Debugf("vote called, with up: %n", up)
|
||||
|
||||
@@ -564,16 +583,17 @@ func (c *Cli) CmdVote(issue string, up bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdTransition will move state of the given issue to the given transtion
|
||||
func (c *Cli) CmdTransition(issue string, trans string) error {
|
||||
log.Debugf("transition called")
|
||||
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/transitions?expand=transitions.fields", c.endpoint, issue)
|
||||
data, err := responseToJson(c.get(uri))
|
||||
data, err := responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
transitions := data.(map[string]interface{})["transitions"].([]interface{})
|
||||
var transId, transName string
|
||||
var transID, transName string
|
||||
var transMeta map[string]interface{}
|
||||
found := make([]string, 0, len(transitions))
|
||||
for _, transition := range transitions {
|
||||
@@ -582,11 +602,11 @@ func (c *Cli) CmdTransition(issue string, trans string) error {
|
||||
found = append(found, name)
|
||||
if strings.Contains(strings.ToLower(name), strings.ToLower(trans)) {
|
||||
transName = name
|
||||
transId = id
|
||||
transID = id
|
||||
transMeta = transition.(map[string]interface{})
|
||||
}
|
||||
}
|
||||
if transId == "" {
|
||||
if transID == "" {
|
||||
err := fmt.Errorf("Invalid Transition '%s', Available: %s", trans, strings.Join(found, ", "))
|
||||
log.Debugf("%s", err)
|
||||
return err
|
||||
@@ -619,12 +639,11 @@ func (c *Cli) CmdTransition(issue string, trans string) error {
|
||||
}
|
||||
|
||||
uri = fmt.Sprintf("%s/rest/api/2/issue/%s", c.endpoint, issue)
|
||||
var issueData map[string]interface{}
|
||||
if data, err := responseToJson(c.get(uri)); err != nil {
|
||||
data, err = responseToJSON(c.get(uri))
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
issueData = data.(map[string]interface{})
|
||||
}
|
||||
issueData := data.(map[string]interface{})
|
||||
issueData["meta"] = transMeta
|
||||
if c.GetOptString("defaultResolution", "") == "" {
|
||||
// .meta.fields.resolution.allowedValues
|
||||
@@ -647,7 +666,7 @@ func (c *Cli) CmdTransition(issue string, trans string) error {
|
||||
issueData["overrides"] = c.opts
|
||||
issueData["transition"] = map[string]interface{}{
|
||||
"name": transName,
|
||||
"id": transId,
|
||||
"id": transID,
|
||||
}
|
||||
return c.editTemplate(
|
||||
c.getTemplate("transition"),
|
||||
@@ -657,6 +676,8 @@ func (c *Cli) CmdTransition(issue string, trans string) error {
|
||||
)
|
||||
}
|
||||
|
||||
// CmdComment will open up editor with "comment" template and submit
|
||||
// YAML output to jira
|
||||
func (c *Cli) CmdComment(issue string) error {
|
||||
log.Debugf("comment called")
|
||||
|
||||
@@ -678,13 +699,12 @@ func (c *Cli) CmdComment(issue string) error {
|
||||
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
logBuffer := bytes.NewBuffer(make([]byte, 0))
|
||||
resp.Write(logBuffer)
|
||||
err := fmt.Errorf("Unexpected Response From POST")
|
||||
log.Errorf("%s:\n%s", err, logBuffer)
|
||||
return err
|
||||
}
|
||||
logBuffer := bytes.NewBuffer(make([]byte, 0))
|
||||
resp.Write(logBuffer)
|
||||
err = fmt.Errorf("Unexpected Response From POST")
|
||||
log.Errorf("%s:\n%s", err, logBuffer)
|
||||
return err
|
||||
}
|
||||
|
||||
if comment, ok := c.opts["comment"]; ok && comment != "" {
|
||||
@@ -695,23 +715,23 @@ func (c *Cli) CmdComment(issue string) error {
|
||||
return err
|
||||
}
|
||||
return handlePost(json)
|
||||
} else {
|
||||
return c.editTemplate(
|
||||
c.getTemplate("comment"),
|
||||
fmt.Sprintf("%s-create-", issue),
|
||||
map[string]interface{}{},
|
||||
handlePost,
|
||||
)
|
||||
}
|
||||
return c.editTemplate(
|
||||
c.getTemplate("comment"),
|
||||
fmt.Sprintf("%s-create-", issue),
|
||||
map[string]interface{}{},
|
||||
handlePost,
|
||||
)
|
||||
}
|
||||
|
||||
// CmdComponent will add a new component to given project
|
||||
func (c *Cli) CmdComponent(action string, project string, name string, desc string, lead string) error {
|
||||
log.Debugf("component called")
|
||||
|
||||
switch action {
|
||||
case "add":
|
||||
default:
|
||||
return errors.New(fmt.Sprintf("CmdComponent: %q is not a valid action", action))
|
||||
return fmt.Errorf("CmdComponent: %q is not a valid action", action)
|
||||
}
|
||||
|
||||
json, err := jsonEncode(map[string]interface{}{
|
||||
@@ -748,6 +768,7 @@ func (c *Cli) CmdComponent(action string, project string, name string, desc stri
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdLabels will add, remove or set labels on a given issue
|
||||
func (c *Cli) CmdLabels(action string, issue string, labels []string) error {
|
||||
log.Debugf("label called")
|
||||
|
||||
@@ -773,23 +794,22 @@ func (c *Cli) CmdLabels(action string, issue string, labels []string) error {
|
||||
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
logBuffer := bytes.NewBuffer(make([]byte, 0))
|
||||
resp.Write(logBuffer)
|
||||
err := fmt.Errorf("Unexpected Response From PUT")
|
||||
log.Errorf("%s:\n%s", err, logBuffer)
|
||||
return err
|
||||
}
|
||||
logBuffer := bytes.NewBuffer(make([]byte, 0))
|
||||
resp.Write(logBuffer)
|
||||
err = fmt.Errorf("Unexpected Response From PUT")
|
||||
log.Errorf("%s:\n%s", err, logBuffer)
|
||||
return err
|
||||
}
|
||||
|
||||
var labels_json string
|
||||
var labelsJSON string
|
||||
var err error
|
||||
if action == "set" {
|
||||
labelsActions := make([]map[string][]string, 1)
|
||||
labelsActions[0] = map[string][]string{
|
||||
"set": labels,
|
||||
}
|
||||
labels_json, err = jsonEncode(map[string]interface{}{
|
||||
labelsJSON, err = jsonEncode(map[string]interface{}{
|
||||
"labels": labelsActions,
|
||||
})
|
||||
} else {
|
||||
@@ -800,18 +820,19 @@ func (c *Cli) CmdLabels(action string, issue string, labels []string) error {
|
||||
}
|
||||
labelsActions[i] = labelActionMap
|
||||
}
|
||||
labels_json, err = jsonEncode(map[string]interface{}{
|
||||
labelsJSON, err = jsonEncode(map[string]interface{}{
|
||||
"labels": labelsActions,
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
json := fmt.Sprintf("{ \"update\": %s }", labels_json)
|
||||
json := fmt.Sprintf("{ \"update\": %s }", labelsJSON)
|
||||
return handlePut(json)
|
||||
|
||||
}
|
||||
|
||||
// CmdAssign will assign the given user to be the owner of the given issue
|
||||
func (c *Cli) CmdAssign(issue string, user string) error {
|
||||
log.Debugf("assign called")
|
||||
|
||||
@@ -847,13 +868,14 @@ func (c *Cli) CmdAssign(issue string, user string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdExportTemplates will export the default templates to the template directory.
|
||||
func (c *Cli) CmdExportTemplates() error {
|
||||
dir := c.opts["directory"].(string)
|
||||
if err := mkdir(dir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for name, template := range all_templates {
|
||||
for name, template := range allTemplates {
|
||||
if wanted, ok := c.opts["template"]; ok && wanted != name {
|
||||
continue
|
||||
}
|
||||
@@ -862,18 +884,19 @@ func (c *Cli) CmdExportTemplates() error {
|
||||
log.Warning("Skipping %s, already exists", templateFile)
|
||||
continue
|
||||
}
|
||||
if fh, err := os.OpenFile(templateFile, os.O_WRONLY|os.O_CREATE, 0644); err != nil {
|
||||
fh, err := os.OpenFile(templateFile, os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to open %s for writing: %s", templateFile, err)
|
||||
return err
|
||||
} else {
|
||||
defer fh.Close()
|
||||
log.Noticef("Creating %s", templateFile)
|
||||
fh.Write([]byte(template))
|
||||
}
|
||||
defer fh.Close()
|
||||
log.Noticef("Creating %s", templateFile)
|
||||
fh.Write([]byte(template))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdRequest will use the given uri to make a request and potentially send provided content.
|
||||
func (c *Cli) CmdRequest(uri, content string) (err error) {
|
||||
log.Debugf("request called")
|
||||
|
||||
@@ -884,11 +907,11 @@ func (c *Cli) CmdRequest(uri, content string) (err error) {
|
||||
method := strings.ToUpper(c.opts["method"].(string))
|
||||
var data interface{}
|
||||
if method == "GET" {
|
||||
data, err = responseToJson(c.get(uri))
|
||||
data, err = responseToJSON(c.get(uri))
|
||||
} else if method == "POST" {
|
||||
data, err = responseToJson(c.post(uri, content))
|
||||
data, err = responseToJSON(c.post(uri, content))
|
||||
} else if method == "PUT" {
|
||||
data, err = responseToJson(c.put(uri, content))
|
||||
data, err = responseToJSON(c.put(uri, content))
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package jiradata
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// This Code is Generated by SlipScheme Project:
|
||||
// https://github.com/coryb/slipscheme
|
||||
//
|
||||
// Generated with command:
|
||||
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// DO NOT EDIT //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// AllowedValues defined from schema:
|
||||
// {
|
||||
// "title": "allowedValues",
|
||||
// "type": "array",
|
||||
// "items": {}
|
||||
// }
|
||||
type AllowedValues []interface{}
|
||||
+70
-4
@@ -4,18 +4,84 @@ package jiradata
|
||||
// This Code is Generated by SlipScheme Project:
|
||||
// https://github.com/coryb/slipscheme
|
||||
//
|
||||
// Generated with command: slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
// Generated with command:
|
||||
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// DO NOT EDIT //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FieldMeta defined from schema:
|
||||
// {
|
||||
// "title": "Field Meta",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "allowedValues": {
|
||||
// "title": "allowedValues",
|
||||
// "type": "array",
|
||||
// "items": {}
|
||||
// },
|
||||
// "autoCompleteUrl": {
|
||||
// "title": "autoCompleteUrl",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "hasDefaultValue": {
|
||||
// "title": "hasDefaultValue",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "key": {
|
||||
// "title": "key",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "operations": {
|
||||
// "title": "operations",
|
||||
// "type": "array",
|
||||
// "items": {
|
||||
// "type": "string"
|
||||
// }
|
||||
// },
|
||||
// "required": {
|
||||
// "title": "required",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "schema": {
|
||||
// "title": "Json Type",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "custom": {
|
||||
// "title": "custom",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "customId": {
|
||||
// "title": "customId",
|
||||
// "type": "integer"
|
||||
// },
|
||||
// "items": {
|
||||
// "title": "items",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "system": {
|
||||
// "title": "system",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "type": {
|
||||
// "title": "type",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
type FieldMeta struct {
|
||||
AllowedValues []interface{} `json:"allowedValues,omitempty" yaml:"allowedValues,omitempty"`
|
||||
AllowedValues AllowedValues `json:"allowedValues,omitempty" yaml:"allowedValues,omitempty"`
|
||||
AutoCompleteURL string `json:"autoCompleteUrl,omitempty" yaml:"autoCompleteUrl,omitempty"`
|
||||
HasDefaultValue bool `json:"hasDefaultValue,omitempty" yaml:"hasDefaultValue,omitempty"`
|
||||
Key string `json:"key,omitempty" yaml:"key,omitempty"`
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Operations []string `json:"operations,omitempty" yaml:"operations,omitempty"`
|
||||
Operations Operations `json:"operations,omitempty" yaml:"operations,omitempty"`
|
||||
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Schema *JsonType `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Schema *JSONType `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
}
|
||||
|
||||
+73
-1
@@ -4,9 +4,81 @@ package jiradata
|
||||
// This Code is Generated by SlipScheme Project:
|
||||
// https://github.com/coryb/slipscheme
|
||||
//
|
||||
// Generated with command: slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
// Generated with command:
|
||||
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// DO NOT EDIT //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FieldMetaMap defined from schema:
|
||||
// {
|
||||
// "title": "fields",
|
||||
// "type": "object",
|
||||
// "patternProperties": {
|
||||
// ".+": {
|
||||
// "title": "Field Meta",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "allowedValues": {
|
||||
// "title": "allowedValues",
|
||||
// "type": "array",
|
||||
// "items": {}
|
||||
// },
|
||||
// "autoCompleteUrl": {
|
||||
// "title": "autoCompleteUrl",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "hasDefaultValue": {
|
||||
// "title": "hasDefaultValue",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "key": {
|
||||
// "title": "key",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "operations": {
|
||||
// "title": "operations",
|
||||
// "type": "array",
|
||||
// "items": {
|
||||
// "type": "string"
|
||||
// }
|
||||
// },
|
||||
// "required": {
|
||||
// "title": "required",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "schema": {
|
||||
// "title": "Json Type",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "custom": {
|
||||
// "title": "custom",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "customId": {
|
||||
// "title": "customId",
|
||||
// "type": "integer"
|
||||
// },
|
||||
// "items": {
|
||||
// "title": "items",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "system": {
|
||||
// "title": "system",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "type": {
|
||||
// "title": "type",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
type FieldMetaMap map[string]*FieldMeta
|
||||
|
||||
+30
-2
@@ -4,12 +4,40 @@ package jiradata
|
||||
// This Code is Generated by SlipScheme Project:
|
||||
// https://github.com/coryb/slipscheme
|
||||
//
|
||||
// Generated with command: slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
// Generated with command:
|
||||
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// DO NOT EDIT //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type JsonType struct {
|
||||
// JSONType defined from schema:
|
||||
// {
|
||||
// "title": "Json Type",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "custom": {
|
||||
// "title": "custom",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "customId": {
|
||||
// "title": "customId",
|
||||
// "type": "integer"
|
||||
// },
|
||||
// "items": {
|
||||
// "title": "items",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "system": {
|
||||
// "title": "system",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "type": {
|
||||
// "title": "type",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
type JSONType struct {
|
||||
Custom string `json:"custom,omitempty" yaml:"custom,omitempty"`
|
||||
CustomID int `json:"customId,omitempty" yaml:"customId,omitempty"`
|
||||
Items string `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package jiradata
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// This Code is Generated by SlipScheme Project:
|
||||
// https://github.com/coryb/slipscheme
|
||||
//
|
||||
// Generated with command:
|
||||
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// DO NOT EDIT //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Operations defined from schema:
|
||||
// {
|
||||
// "title": "operations",
|
||||
// "type": "array",
|
||||
// "items": {
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
type Operations []string
|
||||
+59
-1
@@ -4,11 +4,69 @@ package jiradata
|
||||
// This Code is Generated by SlipScheme Project:
|
||||
// https://github.com/coryb/slipscheme
|
||||
//
|
||||
// Generated with command: slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
// Generated with command:
|
||||
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// DO NOT EDIT //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Status defined from schema:
|
||||
// {
|
||||
// "title": "Status",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "description": {
|
||||
// "title": "description",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "iconUrl": {
|
||||
// "title": "iconUrl",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "id": {
|
||||
// "title": "id",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "self": {
|
||||
// "title": "self",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "statusCategory": {
|
||||
// "title": "Status Category",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "colorName": {
|
||||
// "title": "colorName",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "id": {
|
||||
// "title": "id",
|
||||
// "type": "integer"
|
||||
// },
|
||||
// "key": {
|
||||
// "title": "key",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "self": {
|
||||
// "title": "self",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// "statusColor": {
|
||||
// "title": "statusColor",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
type Status struct {
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
IconURL string `json:"iconUrl,omitempty" yaml:"iconUrl,omitempty"`
|
||||
|
||||
+29
-1
@@ -4,11 +4,39 @@ package jiradata
|
||||
// This Code is Generated by SlipScheme Project:
|
||||
// https://github.com/coryb/slipscheme
|
||||
//
|
||||
// Generated with command: slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
// Generated with command:
|
||||
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// DO NOT EDIT //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// StatusCategory defined from schema:
|
||||
// {
|
||||
// "title": "Status Category",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "colorName": {
|
||||
// "title": "colorName",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "id": {
|
||||
// "title": "id",
|
||||
// "type": "integer"
|
||||
// },
|
||||
// "key": {
|
||||
// "title": "key",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "self": {
|
||||
// "title": "self",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
type StatusCategory struct {
|
||||
ColorName string `json:"colorName,omitempty" yaml:"colorName,omitempty"`
|
||||
ID int `json:"id,omitempty" yaml:"id,omitempty"`
|
||||
|
||||
+151
-1
@@ -4,11 +4,161 @@ package jiradata
|
||||
// This Code is Generated by SlipScheme Project:
|
||||
// https://github.com/coryb/slipscheme
|
||||
//
|
||||
// Generated with command: slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
// Generated with command:
|
||||
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// DO NOT EDIT //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Transition defined from schema:
|
||||
// {
|
||||
// "title": "Transition",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "expand": {
|
||||
// "title": "expand",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "fields": {
|
||||
// "title": "fields",
|
||||
// "type": "object",
|
||||
// "patternProperties": {
|
||||
// ".+": {
|
||||
// "title": "Field Meta",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "allowedValues": {
|
||||
// "title": "allowedValues",
|
||||
// "type": "array",
|
||||
// "items": {}
|
||||
// },
|
||||
// "autoCompleteUrl": {
|
||||
// "title": "autoCompleteUrl",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "hasDefaultValue": {
|
||||
// "title": "hasDefaultValue",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "key": {
|
||||
// "title": "key",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "operations": {
|
||||
// "title": "operations",
|
||||
// "type": "array",
|
||||
// "items": {
|
||||
// "type": "string"
|
||||
// }
|
||||
// },
|
||||
// "required": {
|
||||
// "title": "required",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "schema": {
|
||||
// "title": "Json Type",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "custom": {
|
||||
// "title": "custom",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "customId": {
|
||||
// "title": "customId",
|
||||
// "type": "integer"
|
||||
// },
|
||||
// "items": {
|
||||
// "title": "items",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "system": {
|
||||
// "title": "system",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "type": {
|
||||
// "title": "type",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// "hasScreen": {
|
||||
// "title": "hasScreen",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "id": {
|
||||
// "title": "id",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "to": {
|
||||
// "title": "Status",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "description": {
|
||||
// "title": "description",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "iconUrl": {
|
||||
// "title": "iconUrl",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "id": {
|
||||
// "title": "id",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "self": {
|
||||
// "title": "self",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "statusCategory": {
|
||||
// "title": "Status Category",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "colorName": {
|
||||
// "title": "colorName",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "id": {
|
||||
// "title": "id",
|
||||
// "type": "integer"
|
||||
// },
|
||||
// "key": {
|
||||
// "title": "key",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "self": {
|
||||
// "title": "self",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// "statusColor": {
|
||||
// "title": "statusColor",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
type Transition struct {
|
||||
Expand string `json:"expand,omitempty" yaml:"expand,omitempty"`
|
||||
Fields FieldMetaMap `json:"fields,omitempty" yaml:"fields,omitempty"`
|
||||
|
||||
+155
-1
@@ -4,9 +4,163 @@ package jiradata
|
||||
// This Code is Generated by SlipScheme Project:
|
||||
// https://github.com/coryb/slipscheme
|
||||
//
|
||||
// Generated with command: slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
// Generated with command:
|
||||
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// DO NOT EDIT //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Transitions defined from schema:
|
||||
// {
|
||||
// "title": "transitions",
|
||||
// "type": "array",
|
||||
// "items": {
|
||||
// "title": "Transition",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "expand": {
|
||||
// "title": "expand",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "fields": {
|
||||
// "title": "fields",
|
||||
// "type": "object",
|
||||
// "patternProperties": {
|
||||
// ".+": {
|
||||
// "title": "Field Meta",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "allowedValues": {
|
||||
// "title": "allowedValues",
|
||||
// "type": "array",
|
||||
// "items": {}
|
||||
// },
|
||||
// "autoCompleteUrl": {
|
||||
// "title": "autoCompleteUrl",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "hasDefaultValue": {
|
||||
// "title": "hasDefaultValue",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "key": {
|
||||
// "title": "key",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "operations": {
|
||||
// "title": "operations",
|
||||
// "type": "array",
|
||||
// "items": {
|
||||
// "type": "string"
|
||||
// }
|
||||
// },
|
||||
// "required": {
|
||||
// "title": "required",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "schema": {
|
||||
// "title": "Json Type",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "custom": {
|
||||
// "title": "custom",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "customId": {
|
||||
// "title": "customId",
|
||||
// "type": "integer"
|
||||
// },
|
||||
// "items": {
|
||||
// "title": "items",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "system": {
|
||||
// "title": "system",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "type": {
|
||||
// "title": "type",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// "hasScreen": {
|
||||
// "title": "hasScreen",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "id": {
|
||||
// "title": "id",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "to": {
|
||||
// "title": "Status",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "description": {
|
||||
// "title": "description",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "iconUrl": {
|
||||
// "title": "iconUrl",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "id": {
|
||||
// "title": "id",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "self": {
|
||||
// "title": "self",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "statusCategory": {
|
||||
// "title": "Status Category",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "colorName": {
|
||||
// "title": "colorName",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "id": {
|
||||
// "title": "id",
|
||||
// "type": "integer"
|
||||
// },
|
||||
// "key": {
|
||||
// "title": "key",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "self": {
|
||||
// "title": "self",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// "statusColor": {
|
||||
// "title": "statusColor",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
type Transitions []*Transition
|
||||
|
||||
@@ -4,6 +4,9 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Find will search the transitions for one that matches
|
||||
// the given name. It will return a valid trantion that matches
|
||||
// or nil
|
||||
func (t Transitions) Find(name string) *Transition {
|
||||
name = strings.ToLower(name)
|
||||
for _, trans := range t {
|
||||
|
||||
+166
-1
@@ -4,11 +4,176 @@ package jiradata
|
||||
// This Code is Generated by SlipScheme Project:
|
||||
// https://github.com/coryb/slipscheme
|
||||
//
|
||||
// Generated with command: slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
// Generated with command:
|
||||
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// DO NOT EDIT //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TransitionsMeta defined from schema:
|
||||
// {
|
||||
// "title": "Transitions Meta",
|
||||
// "id": "https://docs.atlassian.com/jira/REST/schema/transitions-meta#",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "expand": {
|
||||
// "title": "expand",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "transitions": {
|
||||
// "title": "transitions",
|
||||
// "type": "array",
|
||||
// "items": {
|
||||
// "title": "Transition",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "expand": {
|
||||
// "title": "expand",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "fields": {
|
||||
// "title": "fields",
|
||||
// "type": "object",
|
||||
// "patternProperties": {
|
||||
// ".+": {
|
||||
// "title": "Field Meta",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "allowedValues": {
|
||||
// "title": "allowedValues",
|
||||
// "type": "array",
|
||||
// "items": {}
|
||||
// },
|
||||
// "autoCompleteUrl": {
|
||||
// "title": "autoCompleteUrl",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "hasDefaultValue": {
|
||||
// "title": "hasDefaultValue",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "key": {
|
||||
// "title": "key",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "operations": {
|
||||
// "title": "operations",
|
||||
// "type": "array",
|
||||
// "items": {
|
||||
// "type": "string"
|
||||
// }
|
||||
// },
|
||||
// "required": {
|
||||
// "title": "required",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "schema": {
|
||||
// "title": "Json Type",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "custom": {
|
||||
// "title": "custom",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "customId": {
|
||||
// "title": "customId",
|
||||
// "type": "integer"
|
||||
// },
|
||||
// "items": {
|
||||
// "title": "items",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "system": {
|
||||
// "title": "system",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "type": {
|
||||
// "title": "type",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// "hasScreen": {
|
||||
// "title": "hasScreen",
|
||||
// "type": "boolean"
|
||||
// },
|
||||
// "id": {
|
||||
// "title": "id",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "to": {
|
||||
// "title": "Status",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "description": {
|
||||
// "title": "description",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "iconUrl": {
|
||||
// "title": "iconUrl",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "id": {
|
||||
// "title": "id",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "self": {
|
||||
// "title": "self",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "statusCategory": {
|
||||
// "title": "Status Category",
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "colorName": {
|
||||
// "title": "colorName",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "id": {
|
||||
// "title": "id",
|
||||
// "type": "integer"
|
||||
// },
|
||||
// "key": {
|
||||
// "title": "key",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "name": {
|
||||
// "title": "name",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "self": {
|
||||
// "title": "self",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// "statusColor": {
|
||||
// "title": "statusColor",
|
||||
// "type": "string"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
type TransitionsMeta struct {
|
||||
Expand string `json:"expand,omitempty" yaml:"expand,omitempty"`
|
||||
Transitions Transitions `json:"transitions,omitempty" yaml:"transitions,omitempty"`
|
||||
|
||||
+4
-4
@@ -3,10 +3,10 @@ eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
|
||||
cd $(dirname $0)
|
||||
jira="../jira --user admin"
|
||||
|
||||
PLAN 15
|
||||
PLAN 14
|
||||
|
||||
# clean out any old containers
|
||||
RUNS sh -c "docker rm -f go-jira-test || true"
|
||||
docker rm -f go-jira-test
|
||||
|
||||
# start newt jira service
|
||||
RUNS docker run --detach --name go-jira-test --publish 8080:8080 go-jira-test:latest
|
||||
@@ -14,8 +14,8 @@ RUNS docker run --detach --name go-jira-test --publish 8080:8080 go-jira-test:la
|
||||
# wait a few seconds for it to bind to port 8080
|
||||
RUNS sleep 10
|
||||
|
||||
# wait for healthchecks to pass, curl will retry 60 times over 1 min waiting
|
||||
RUNS curl -q -L --retry 60 --retry-delay 1 -f -s "http://localhost:8080/rest/api/2/serverInfo?doHealthCheck=1"
|
||||
# wait for healthchecks to pass, curl will retry 60 times over 5 min waiting
|
||||
RUNS curl -q -L --retry 360 --retry-delay 1 -f -s "http://localhost:8080/rest/api/2/serverInfo?doHealthCheck=1"
|
||||
|
||||
# login to jira as admin user
|
||||
echo "admin123" | RUNS $jira login
|
||||
|
||||
+29
-29
@@ -1,37 +1,37 @@
|
||||
package jira
|
||||
|
||||
var all_templates = map[string]string{
|
||||
"debug": default_debug_template,
|
||||
"fields": default_debug_template,
|
||||
"editmeta": default_debug_template,
|
||||
"transmeta": default_debug_template,
|
||||
"createmeta": default_debug_template,
|
||||
"issuelinktypes": default_debug_template,
|
||||
"list": default_list_template,
|
||||
"table": default_table_template,
|
||||
"view": default_view_template,
|
||||
"edit": default_edit_template,
|
||||
"transitions": default_transitions_template,
|
||||
"components": default_components_template,
|
||||
"issuetypes": default_issuetypes_template,
|
||||
"create": default_create_template,
|
||||
"comment": default_comment_template,
|
||||
"transition": default_transition_template,
|
||||
"request": default_debug_template,
|
||||
var allTemplates = map[string]string{
|
||||
"debug": defaultDebugTemplate,
|
||||
"fields": defaultDebugTemplate,
|
||||
"editmeta": defaultDebugTemplate,
|
||||
"transmeta": defaultDebugTemplate,
|
||||
"createmeta": defaultDebugTemplate,
|
||||
"issuelinktypes": defaultDebugTemplate,
|
||||
"list": defaultListTemplate,
|
||||
"table": defaultTableTemplate,
|
||||
"view": defaultViewTemplate,
|
||||
"edit": defaultEditTemplate,
|
||||
"transitions": defaultTransitionsTemplate,
|
||||
"components": defaultComponentsTemplate,
|
||||
"issuetypes": defaultIssuetypesTemplate,
|
||||
"create": defaultCreateTemplate,
|
||||
"comment": defaultCommentTemplate,
|
||||
"transition": defaultTransitionTemplate,
|
||||
"request": defaultDebugTemplate,
|
||||
}
|
||||
|
||||
const default_debug_template = "{{ . | toJson}}\n"
|
||||
const defaultDebugTemplate = "{{ . | toJson}}\n"
|
||||
|
||||
const default_list_template = "{{ range .issues }}{{ .key | append \":\" | printf \"%-12s\"}} {{ .fields.summary }}\n{{ end }}"
|
||||
const defaultListTemplate = "{{ range .issues }}{{ .key | append \":\" | printf \"%-12s\"}} {{ .fields.summary }}\n{{ end }}"
|
||||
|
||||
const default_table_template = `+{{ "-" | rep 16 }}+{{ "-" | rep 57 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
|
||||
const defaultTableTemplate = `+{{ "-" | rep 16 }}+{{ "-" | rep 57 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
|
||||
| {{ "Issue" | printf "%-14s" }} | {{ "Summary" | printf "%-55s" }} | {{ "Priority" | printf "%-12s" }} | {{ "Status" | printf "%-12s" }} | {{ "Age" | printf "%-10s" }} | {{ "Reporter" | printf "%-12s" }} | {{ "Assignee" | printf "%-12s" }} |
|
||||
+{{ "-" | rep 16 }}+{{ "-" | rep 57 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
|
||||
{{ range .issues }}| {{ .key | printf "%-14s"}} | {{ .fields.summary | abbrev 55 | printf "%-55s" }} | {{.fields.priority.name | printf "%-12s" }} | {{.fields.status.name | printf "%-12s" }} | {{.fields.created | age | printf "%-10s" }} | {{if .fields.reporter}}{{ .fields.reporter.name | printf "%-12s"}}{{else}}<unassigned>{{end}} | {{if .fields.assignee }}{{.fields.assignee.name | printf "%-12s" }}{{else}}<unassigned>{{end}} |
|
||||
{{ end }}+{{ "-" | rep 16 }}+{{ "-" | rep 57 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
|
||||
`
|
||||
|
||||
const default_view_template = `issue: {{ .key }}{{if .fields.created}}
|
||||
const defaultViewTemplate = `issue: {{ .key }}{{if .fields.created}}
|
||||
created: {{ .fields.created | age }} ago{{end}}{{if .fields.status}}
|
||||
status: {{ .fields.status.name }}{{end}}
|
||||
summary: {{ .fields.summary }}
|
||||
@@ -54,7 +54,7 @@ comments:
|
||||
{{ or .body "" | indent 4}}
|
||||
{{end}}{{end}}
|
||||
`
|
||||
const default_edit_template = `# issue: {{ .key }}
|
||||
const defaultEditTemplate = `# issue: {{ .key }}
|
||||
update:
|
||||
comment:
|
||||
- add:
|
||||
@@ -82,16 +82,16 @@ fields:
|
||||
# {{ or .body "" | indent 4 | comment}}
|
||||
# {{end}}
|
||||
`
|
||||
const default_transitions_template = `{{ range .transitions }}{{.id }}: {{.name}}
|
||||
const defaultTransitionsTemplate = `{{ range .transitions }}{{.id }}: {{.name}}
|
||||
{{end}}`
|
||||
|
||||
const default_components_template = `{{ range . }}{{.id }}: {{.name}}
|
||||
const defaultComponentsTemplate = `{{ range . }}{{.id }}: {{.name}}
|
||||
{{end}}`
|
||||
|
||||
const default_issuetypes_template = `{{ range .projects }}{{ range .issuetypes }}{{color "+bh"}}{{.name | append ":" | printf "%-13s" }}{{color "reset"}} {{.description}}
|
||||
const defaultIssuetypesTemplate = `{{ range .projects }}{{ range .issuetypes }}{{color "+bh"}}{{.name | append ":" | printf "%-13s" }}{{color "reset"}} {{.description}}
|
||||
{{end}}{{end}}`
|
||||
|
||||
const default_create_template = `fields:
|
||||
const defaultCreateTemplate = `fields:
|
||||
project:
|
||||
key: {{ or .overrides.project "" }}
|
||||
issuetype:
|
||||
@@ -112,11 +112,11 @@ const default_create_template = `fields:
|
||||
- name: {{.}}{{end}}
|
||||
- name:{{end}}`
|
||||
|
||||
const default_comment_template = `body: |~
|
||||
const defaultCommentTemplate = `body: |~
|
||||
{{ or .overrides.comment "" | indent 2 }}
|
||||
`
|
||||
|
||||
const default_transition_template = `update:
|
||||
const defaultTransitionTemplate = `update:
|
||||
comment:
|
||||
- add:
|
||||
body: |~
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/mgutz/ansi"
|
||||
"gopkg.in/coryb/yaml.v2"
|
||||
@@ -26,10 +25,12 @@ func homedir() string {
|
||||
return os.Getenv("HOME")
|
||||
}
|
||||
|
||||
// FindParentPaths will find all available paths from the current path up to the root
|
||||
// that matches the given fileName path
|
||||
func FindParentPaths(fileName string) []string {
|
||||
cwd, _ := os.Getwd()
|
||||
|
||||
paths := make([]string, 0)
|
||||
paths := []string{}
|
||||
|
||||
// special case if homedir is not in current path then check there anyway
|
||||
homedir := homedir()
|
||||
@@ -57,12 +58,14 @@ func FindParentPaths(fileName string) []string {
|
||||
return paths
|
||||
}
|
||||
|
||||
// FindClosestParentPath finds the path that matches the given fileName path that is
|
||||
// closest to the current working directory
|
||||
func FindClosestParentPath(fileName string) (string, error) {
|
||||
paths := FindParentPaths(fileName)
|
||||
if len(paths) > 0 {
|
||||
return paths[len(paths)-1], nil
|
||||
}
|
||||
return "", errors.New(fmt.Sprintf("%s not found in parent directory hierarchy", fileName))
|
||||
return "", fmt.Errorf("%s not found in parent directory hierarchy", fileName)
|
||||
}
|
||||
|
||||
func readFile(file string) string {
|
||||
@@ -92,34 +95,36 @@ func copyFile(src, dst string) (err error) {
|
||||
}
|
||||
|
||||
func fuzzyAge(start string) (string, error) {
|
||||
if t, err := time.Parse("2006-01-02T15:04:05.000-0700", start); err != nil {
|
||||
t, err := time.Parse("2006-01-02T15:04:05.000-0700", start)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
delta := time.Now().Sub(t)
|
||||
if delta.Minutes() < 2 {
|
||||
return "a minute", nil
|
||||
} else if dm := delta.Minutes(); dm < 45 {
|
||||
return fmt.Sprintf("%d minutes", int(dm)), nil
|
||||
} else if dm := delta.Minutes(); dm < 90 {
|
||||
return "an hour", nil
|
||||
} else if dh := delta.Hours(); dh < 24 {
|
||||
return fmt.Sprintf("%d hours", int(dh)), nil
|
||||
} else if dh := delta.Hours(); dh < 48 {
|
||||
return "a day", nil
|
||||
} else {
|
||||
return fmt.Sprintf("%d days", int(delta.Hours()/24)), nil
|
||||
}
|
||||
}
|
||||
delta := time.Now().Sub(t)
|
||||
if delta.Minutes() < 2 {
|
||||
return "a minute", nil
|
||||
} else if dm := delta.Minutes(); dm < 45 {
|
||||
return fmt.Sprintf("%d minutes", int(dm)), nil
|
||||
} else if dm := delta.Minutes(); dm < 90 {
|
||||
return "an hour", nil
|
||||
} else if dh := delta.Hours(); dh < 24 {
|
||||
return fmt.Sprintf("%d hours", int(dh)), nil
|
||||
} else if dh := delta.Hours(); dh < 48 {
|
||||
return "a day", nil
|
||||
}
|
||||
return fmt.Sprintf("%d days", int(delta.Hours()/24)), nil
|
||||
}
|
||||
|
||||
func dateFormat(format string, content string) (string, error) {
|
||||
if t, err := time.Parse("2006-01-02T15:04:05.000-0700", content); err != nil {
|
||||
t, err := time.Parse("2006-01-02T15:04:05.000-0700", content)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
return t.Format(format), nil
|
||||
}
|
||||
return t.Format(format), nil
|
||||
}
|
||||
|
||||
// RunTemplate will run the give templateContent as a golang text/template
|
||||
// and pass the provided data to the template execution. It will write
|
||||
// the output to the provided "out" writer.
|
||||
func RunTemplate(templateContent string, data interface{}, out io.Writer) error {
|
||||
return runTemplate(templateContent, data, out)
|
||||
}
|
||||
@@ -131,11 +136,11 @@ func runTemplate(templateContent string, data interface{}, out io.Writer) error
|
||||
|
||||
funcs := map[string]interface{}{
|
||||
"toJson": func(content interface{}) (string, error) {
|
||||
if bytes, err := json.MarshalIndent(content, "", " "); err != nil {
|
||||
bytes, err := json.MarshalIndent(content, "", " ")
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
return string(bytes), nil
|
||||
}
|
||||
return string(bytes), nil
|
||||
},
|
||||
"append": func(more string, content interface{}) (string, error) {
|
||||
switch value := content.(type) {
|
||||
@@ -144,13 +149,13 @@ func runTemplate(templateContent string, data interface{}, out io.Writer) error
|
||||
case []byte:
|
||||
return string(append(content.([]byte), []byte(more)...)), nil
|
||||
default:
|
||||
return "", errors.New(fmt.Sprintf("Unknown type: %s", value))
|
||||
return "", fmt.Errorf("Unknown type: %s", value)
|
||||
}
|
||||
},
|
||||
"indent": func(spaces int, content string) string {
|
||||
indent := make([]rune, spaces+1, spaces+1)
|
||||
indent[0] = '\n'
|
||||
for i := 1; i < spaces+1; i += 1 {
|
||||
for i := 1; i < spaces+1; i++ {
|
||||
indent[i] = ' '
|
||||
}
|
||||
|
||||
@@ -193,7 +198,7 @@ func runTemplate(templateContent string, data interface{}, out io.Writer) error
|
||||
},
|
||||
"rep": func(count int, content string) string {
|
||||
var buffer bytes.Buffer
|
||||
for i := 0; i < count; i += 1 {
|
||||
for i := 0; i < count; i++ {
|
||||
buffer.WriteString(content)
|
||||
}
|
||||
return buffer.String()
|
||||
@@ -205,19 +210,19 @@ func runTemplate(templateContent string, data interface{}, out io.Writer) error
|
||||
return dateFormat(format, content)
|
||||
},
|
||||
}
|
||||
if tmpl, err := template.New("template").Funcs(funcs).Parse(templateContent); err != nil {
|
||||
tmpl, err := template.New("template").Funcs(funcs).Parse(templateContent)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to parse template: %s", err)
|
||||
return err
|
||||
} else {
|
||||
if err := tmpl.Execute(out, data); err != nil {
|
||||
log.Errorf("Failed to execute template: %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := tmpl.Execute(out, data); err != nil {
|
||||
log.Errorf("Failed to execute template: %s", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func responseToJson(resp *http.Response, err error) (interface{}, error) {
|
||||
func responseToJSON(resp *http.Response, err error) (interface{}, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -366,7 +371,7 @@ func mkdir(dir string) error {
|
||||
log.Errorf("Failed to stat %s: %s", dir, err)
|
||||
return err
|
||||
} else if err == nil && !stat.IsDir() {
|
||||
err := fmt.Errorf("%s exists and is not a directory!", dir)
|
||||
err := fmt.Errorf("%s exists and is not a directory", dir)
|
||||
log.Errorf("%s", err)
|
||||
return err
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user