rewrite checkpoint

This commit is contained in:
Cory Bennett
2017-08-13 18:23:38 -07:00
parent b00021ccbd
commit 36632a52f0
883 changed files with 222856 additions and 2972 deletions
-14
View File
@@ -1,15 +1 @@
bin/
pkg/
src/code.google.com/
src/github.com/docopt/
src/github.com/mgutz/
src/github.com/op/
src/gopkg.in/
jira
jira.exe
schemas/*.json
t/issue.props
t/.jira.d/templates
dist/
src/
t/.maven-cache
+3 -5
View File
@@ -28,8 +28,6 @@ else
BIN ?= $(GOBIN)$(SEP)$(NAME)
endif
export GOPATH=$(CWD)
DIST=$(CWD)$(SEP)dist
GOBIN ?= $(CWD)
@@ -40,16 +38,16 @@ LDFLAGS:=-X jira.VERSION=$(CURVER) -w
# use make DEBUG=1 and you can get a debuggable golang binary
# see https://github.com/mailgun/godebug
ifneq ($(DEBUG),)
GOBUILD=go get -v github.com/mailgun/godebug && ./bin/godebug build
GOBUILD=go get -v github.com/mailgun/godebug &&
else
GOBUILD=go build -v -ldflags "$(LDFLAGS) -s"
endif
build: src/gopkg.in/Netflix-Skunkworks/go-jira.v0
$(GOBUILD) -o '$(BIN)' main/main.go
$(GOBUILD) -o '$(BIN)' cmd/jira/main.go
debug:
$(MAKE) DEBUG=1
go build -v -o '$(BIN)' cmd/jira/main.go
src/%:
mkdir -p $(@D)
-646
View File
@@ -1,646 +0,0 @@
package jira
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/cookiejar"
"net/http/httputil"
"net/url"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"strings"
"time"
"github.com/kballard/go-shellquote"
"gopkg.in/coryb/yaml.v2"
"gopkg.in/op/go-logging.v1"
)
var (
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{}
cookieFile string
ua *http.Client
}
// New creates go-jira client object
func New(opts map[string]interface{}) *Cli {
homedir := homedir()
cookieJar, _ := cookiejar.New(nil)
endpoint, _ := opts["endpoint"].(string)
url, _ := url.Parse(strings.TrimRight(endpoint, "/"))
if project, ok := opts["project"].(string); ok {
opts["project"] = strings.ToUpper(project)
}
var ua *http.Client
if unixProxyPath, ok := opts["unixproxy"].(string); ok {
ua = &http.Client{
Jar: cookieJar,
Transport: UnixProxy(unixProxyPath),
}
} else {
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{},
}
if insecureSkipVerify, ok := opts["insecure"].(bool); ok {
transport.TLSClientConfig.InsecureSkipVerify = insecureSkipVerify
}
ua = &http.Client{
Jar: cookieJar,
Transport: transport,
}
}
cli := &Cli{
endpoint: url,
opts: opts,
cookieFile: filepath.Join(homedir, ".jira.d", "cookies.js"),
ua: ua,
}
cli.ua.Jar.SetCookies(url, cli.loadCookies())
return cli
}
func (c *Cli) saveCookies(resp *http.Response) {
if _, ok := resp.Header["Set-Cookie"]; !ok {
return
}
cookies := resp.Cookies()
for _, cookie := range cookies {
if cookie.Domain == "" {
// if it is host:port then we need to split off port
parts := strings.Split(resp.Request.URL.Host, ":")
host := parts[0]
log.Debugf("Setting DOMAIN to %s for Cookie: %s", host, cookie)
cookie.Domain = host
}
}
// expiry in one week from now
expiry := time.Now().Add(24 * 7 * time.Hour)
for _, cookie := range cookies {
cookie.Expires = expiry
}
if currentCookies := c.loadCookies(); currentCookies != nil {
currentCookiesByName := make(map[string]*http.Cookie)
for _, cookie := range currentCookies {
currentCookiesByName[cookie.Name+cookie.Domain] = cookie
}
for _, cookie := range cookies {
currentCookiesByName[cookie.Name+cookie.Domain] = cookie
}
mergedCookies := make([]*http.Cookie, 0, len(currentCookiesByName))
for _, v := range currentCookiesByName {
mergedCookies = append(mergedCookies, v)
}
jsonWrite(c.cookieFile, mergedCookies)
} else {
mkdir(path.Dir(c.cookieFile))
jsonWrite(c.cookieFile, cookies)
}
}
func (c *Cli) loadCookies() []*http.Cookie {
bytes, err := ioutil.ReadFile(c.cookieFile)
if err != nil && os.IsNotExist(err) {
// dont load cookies if the file does not exist
return nil
}
if err != nil {
log.Errorf("Failed to open %s: %s", c.cookieFile, err)
panic(err)
}
cookies := []*http.Cookie{}
err = json.Unmarshal(bytes, &cookies)
if err != nil {
log.Errorf("Failed to parse json from file %s: %s", c.cookieFile, err)
}
if os.Getenv("LOG_TRACE") != "" && log.IsEnabledFor(logging.DEBUG) {
log.Debugf("Loading Cookies: %s", cookies)
}
return cookies
}
func (c *Cli) post(uri string, content string) (*http.Response, error) {
return c.makeRequestWithContent("POST", uri, content)
}
func (c *Cli) put(uri string, content string) (*http.Response, error) {
return c.makeRequestWithContent("PUT", uri, content)
}
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 {
return nil, 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) (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 {
return nil, 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) (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) {
logBuffer := bytes.NewBuffer(make([]byte, 0))
req.Write(logBuffer)
log.Debugf("%s", logBuffer)
}
if resp, err = c.makeRequest(req); err != nil {
return nil, 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) {
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
if source, ok := c.opts["password-source"]; ok && !strings.HasSuffix(req.URL.Path, "/rest/auth/1/session") {
user, _ := c.opts["user"].(string)
password := c.GetPass(user)
if password == "" {
log.Warning("No password for user %s in %s, please run the 'login' command first", user, source)
} else {
req.SetBasicAuth(user, password)
}
}
// this is actually done in http.send but doing it
// here so we can log it in DumpRequest for debugging
for _, cookie := range c.ua.Jar.Cookies(req.URL) {
req.AddCookie(cookie)
}
if log.IsEnabledFor(logging.DEBUG) {
out, _ := httputil.DumpRequest(req, true)
log.Debugf("Request: %s", out)
}
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
}
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()
})
if _, ok := resp.Header["Set-Cookie"]; ok {
c.saveCookies(resp)
}
if log.IsEnabledFor(logging.DEBUG) {
out, _ := httputil.DumpResponse(resp, true)
log.Debugf("Response: %s", out)
}
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)
}
func getLookedUpTemplate(name string, dflt string) string {
if file, err := FindClosestParentPath(filepath.Join(".jira.d", "templates", name)); err == nil {
return readFile(file)
}
if _, err := os.Stat(fmt.Sprintf("/etc/go-jira/templates/%s", name)); err == nil {
file := fmt.Sprintf("/etc/go-jira/templates/%s", name)
return readFile(file)
}
return dflt
}
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)
}
if t := getLookedUpTemplate(override, allTemplates[override]); t != "" {
return t
}
}
// create-bug etc are special, if we dont find it in the path
// then just return the create template
if strings.HasPrefix(name, "create-") {
return getLookedUpTemplate(name, c.getTemplate("create"))
}
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 {
return "No changes found, aborting"
}
func (c *Cli) editTemplate(template string, tmpFilePrefix string, templateData map[string]interface{}, templateProcessor func(string) error) error {
tmpdir := filepath.Join(homedir(), ".jira.d", "tmp")
if err := mkdir(tmpdir); err != nil {
return err
}
fh, err := ioutil.TempFile(tmpdir, tmpFilePrefix)
if err != nil {
log.Errorf("Failed to make temp file in %s: %s", tmpdir, err)
return err
}
oldFileName := fh.Name()
tmpFileName := fmt.Sprintf("%s.yml", oldFileName)
// close tmpfile so we can rename on windows
fh.Close()
if err := os.Rename(oldFileName, tmpFileName); err != nil {
log.Errorf("Failed to rename %s to %s: %s", oldFileName, tmpFileName, err)
return err
}
fh, err = os.OpenFile(tmpFileName, os.O_RDWR|os.O_EXCL, 0600)
if err != nil {
log.Errorf("Failed to reopen temp file file in %s: %s", tmpFileName, err)
return err
}
defer fh.Close()
defer func() {
os.Remove(tmpFileName)
}()
err = runTemplate(template, templateData, fh)
if err != nil {
return err
}
fh.Close()
editor, ok := c.opts["editor"].(string)
if !ok {
editor = os.Getenv("JIRA_EDITOR")
if editor == "" {
editor = os.Getenv("EDITOR")
if editor == "" {
editor = "vim"
}
}
}
editing := c.getOptBool("edit", true)
tmpFileNameOrig := fmt.Sprintf("%s.orig", tmpFileName)
copyFile(tmpFileName, tmpFileNameOrig)
defer func() {
os.Remove(tmpFileNameOrig)
}()
for true {
if editing {
shell, _ := shellquote.Split(editor)
shell = append(shell, tmpFileName)
log.Debugf("Running: %#v", shell)
cmd := exec.Command(shell[0], shell[1:]...)
cmd.Stdout, cmd.Stderr, cmd.Stdin = os.Stdout, os.Stderr, os.Stdin
if err := cmd.Run(); err != nil {
log.Errorf("Failed to edit template with %s: %s", editor, err)
if promptYN("edit again?", true) {
continue
}
return err
}
diff := exec.Command("diff", "-q", tmpFileNameOrig, tmpFileName)
// if err == nil then diff found no changes
if err := diff.Run(); err == nil {
return NoChangesFound{}
}
}
edited := make(map[string]interface{})
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
}
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
}
var fixed interface{}
if fixed, err = yamlFixup(edited); err != nil {
return err
}
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
// and we will abort now
if val, ok := edited["abort"].(bool); ok && val {
log.Infof("abort flag found in template, quiting")
return fmt.Errorf("abort flag found in template, quiting")
}
if _, ok := templateData["meta"]; ok {
mf := templateData["meta"].(map[string]interface{})["fields"]
if f, ok := edited["fields"].(map[string]interface{}); ok {
for k := range f {
if _, ok := mf.(map[string]interface{})[k]; !ok {
err := fmt.Errorf("Field %s is not editable", k)
log.Errorf("%s", err)
if editing && promptYN("edit again?", true) {
continue
}
return err
}
}
}
}
json, err := jsonEncode(edited)
if err != nil {
return err
}
if err := templateProcessor(json); err != nil {
log.Errorf("%s", err)
if editing && promptYN("edit again?", true) {
continue
}
}
return nil
}
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" {
return exec.Command("open", fmt.Sprintf("%s/browse/%s", c.endpoint, issue)).Run()
} else if runtime.GOOS == "linux" {
return exec.Command("xdg-open", fmt.Sprintf("%s/browse/%s", c.endpoint, issue)).Run()
} else if runtime.GOOS == "windows" {
return exec.Command("cmd", "/c", "start", fmt.Sprintf("%s/browse/%s", c.endpoint, issue)).Run()
}
}
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)
}
return nil
}
// ViewIssueWorkLogs gets the worklog data for the given issue
func (c *Cli) ViewIssueWorkLogs(issue string) (interface{}, error) {
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/worklog", c.endpoint, issue)
data, err := responseToJSON(c.get(uri))
if err != nil {
return nil, err
}
return data, 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))
if err != nil {
return nil, err
}
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")
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
}
qbuff.WriteString(fmt.Sprintf(" AND project = '%s'", project))
if component, ok := c.opts["component"]; ok {
qbuff.WriteString(fmt.Sprintf(" AND component = '%s'", component))
}
if assignee, ok := c.opts["assignee"]; ok {
qbuff.WriteString(fmt.Sprintf(" AND assignee = '%s'", assignee))
}
if issuetype, ok := c.opts["issuetype"]; ok {
qbuff.WriteString(fmt.Sprintf(" AND issuetype = '%s'", issuetype))
}
if watcher, ok := c.opts["watcher"]; ok {
qbuff.WriteString(fmt.Sprintf(" AND watcher = '%s'", watcher))
}
if reporter, ok := c.opts["reporter"]; ok {
qbuff.WriteString(fmt.Sprintf(" AND reporter = '%s'", reporter))
}
if sort, ok := c.opts["sort"]; ok && sort != "" {
qbuff.WriteString(fmt.Sprintf(" ORDER BY %s", sort))
}
query = qbuff.String()
}
fields := []string{"summary"}
if qf, ok := c.opts["queryfields"].(string); ok {
fields = strings.Split(qf, ",")
}
json, err := jsonEncode(map[string]interface{}{
"jql": query,
"startAt": c.opts["start_at"],
"maxResults": c.opts["max_results"],
"fields": fields,
"expand": c.expansions(),
})
if err != nil {
return nil, err
}
uri := fmt.Sprintf("%s/rest/api/2/search", c.endpoint)
var data interface{}
if data, err = responseToJSON(c.post(uri, json)); err != nil {
return nil, err
}
return data, nil
}
// RankOrder type used to specify before/after ranking arguments to RankIssue
type RankOrder int
const (
// RANKBEFORE should be used to rank issue before the target issue
RANKBEFORE RankOrder = iota
// RANKAFTER should be used to rank issue after the target issue
RANKAFTER RankOrder = iota
)
// RankIssue will modify issue to have rank before or after the target issue
func (c *Cli) RankIssue(issue, target string, order RankOrder) error {
type RankRequest struct {
Issues []string `json:"issues"`
Before string `json:"rankBeforeIssue,omitempty"`
After string `json:"rankAfterIssue,omitempty"`
}
req := &RankRequest{
Issues: []string{
issue,
},
}
if order == RANKBEFORE {
req.Before = target
} else {
req.After = target
}
json, err := jsonEncode(req)
if err != nil {
return err
}
uri := fmt.Sprintf("%s/rest/agile/1.0/issue/rank", c.endpoint)
if c.getOptBool("dryrun", false) {
log.Debugf("PUT: %s", json)
log.Debugf("Dryrun mode, skipping PUT")
return nil
}
resp, err := c.put(uri, json)
if err != nil {
return err
}
if resp.StatusCode != 204 {
return fmt.Errorf("failed to modify issue rank: %s", resp.Status)
}
return 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)
}
func (c *Cli) getOptString(optName string, dflt string) string {
if val, ok := c.opts[optName].(string); ok {
return val
}
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)
}
func (c *Cli) getOptBool(optName string, dflt bool) bool {
if val, ok := c.opts[optName].(bool); ok {
return val
}
return dflt
}
// expansions returns a comma-separated list of values for field expansion
func (c *Cli) expansions() []string {
var expansions []string
if x, ok := c.opts["expand"].(string); ok {
expansions = strings.Split(x, ",")
}
return expansions
}
+698
View File
@@ -0,0 +1,698 @@
package main
import (
"fmt"
"os"
"runtime/debug"
"github.com/coryb/oreo"
jira "gopkg.in/Netflix-Skunkworks/go-jira.v1"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
kingpin "gopkg.in/alecthomas/kingpin.v2"
"gopkg.in/op/go-logging.v1"
)
var (
log = logging.MustGetLogger("jira")
defaultFormat = "%{color}%{time:2006-01-02T15:04:05.000Z07:00} %{level:-5s} [%{shortfile}]%{color:reset} %{message}"
)
func handleExit() {
if e := recover(); e != nil {
if exit, ok := e.(jiracli.Exit); ok {
os.Exit(exit.Code)
} else {
fmt.Fprintf(os.Stderr, "%s\n%s", e, debug.Stack())
os.Exit(1)
}
}
}
func main() {
defer handleExit()
logBackend := logging.NewLogBackend(os.Stderr, "", 0)
format := os.Getenv("JIRA_LOG_FORMAT")
if format == "" {
format = defaultFormat
}
logging.SetBackend(
logging.NewBackendFormatter(
logBackend,
logging.MustStringFormatter(format),
),
)
if os.Getenv("JIRA_DEBUG") == "" {
logging.SetLevel(logging.NOTICE, "")
} else {
logging.SetLevel(logging.DEBUG, "")
}
app := kingpin.New("jira", "Jira Command Line Interface")
app.Command("version", "Prints version").PreAction(func(*kingpin.ParseContext) error {
fmt.Println(jira.VERSION)
panic(jiracli.Exit{Code: 0})
})
app.Flag("verbose", "Increase verbosity for debugging").Short('v').PreAction(func(_ *kingpin.ParseContext) error {
logging.SetLevel(logging.GetLevel("")+1, "")
if logging.GetLevel("") > logging.DEBUG {
oreo.TraceRequestBody = true
oreo.TraceResponseBody = true
}
return nil
}).Counter()
cli := jiracli.New(".jira.d")
registry := []jiracli.CommandRegistry{
jiracli.CommandRegistry{
Command: "login",
Entry: cli.CmdLoginRegistry(),
},
jiracli.CommandRegistry{
Command: "logout",
Entry: cli.CmdLogoutRegistry(),
},
jiracli.CommandRegistry{
Command: "list",
Aliases: []string{"ls"},
Entry: cli.CmdListRegistry(),
},
jiracli.CommandRegistry{
Command: "view",
Entry: cli.CmdViewRegistry(),
},
jiracli.CommandRegistry{
Command: "create",
Entry: cli.CmdCreateRegistry(),
},
jiracli.CommandRegistry{
Command: "edit",
Entry: cli.CmdEditRegistry(),
},
jiracli.CommandRegistry{
Command: "worklog list",
Entry: cli.CmdWorklogListRegistry(),
Default: true,
},
jiracli.CommandRegistry{
Command: "worklog add",
Entry: cli.CmdWorklogAddRegistry(),
},
jiracli.CommandRegistry{
Command: "fields",
Entry: cli.CmdFieldsRegistry(),
},
jiracli.CommandRegistry{
Command: "createmeta",
Entry: cli.CmdCreateMetaRegistry(),
},
jiracli.CommandRegistry{
Command: "editmeta",
Entry: cli.CmdEditMetaRegistry(),
},
jiracli.CommandRegistry{
Command: "subtask",
Entry: cli.CmdSubtaskRegistry(),
},
jiracli.CommandRegistry{
Command: "dup",
Entry: cli.CmdDupRegistry(),
},
jiracli.CommandRegistry{
Command: "transition",
Aliases: []string{"trans"},
Entry: cli.CmdTransitionRegistry(""),
},
jiracli.CommandRegistry{
Command: "transitions",
Entry: cli.CmdTransitionsRegistry("transitions"),
},
jiracli.CommandRegistry{
Command: "transmeta",
Entry: cli.CmdTransitionsRegistry("debug"),
},
jiracli.CommandRegistry{
Command: "close",
Entry: cli.CmdTransitionRegistry("close"),
},
jiracli.CommandRegistry{
Command: "acknowledge",
Aliases: []string{"ack"},
Entry: cli.CmdTransitionRegistry("acknowledge"),
},
jiracli.CommandRegistry{
Command: "reopen",
Entry: cli.CmdTransitionRegistry("reopen"),
},
jiracli.CommandRegistry{
Command: "resolve",
Entry: cli.CmdTransitionRegistry("resolve"),
},
jiracli.CommandRegistry{
Command: "start",
Entry: cli.CmdTransitionRegistry("start"),
},
jiracli.CommandRegistry{
Command: "stop",
Entry: cli.CmdTransitionRegistry("stop"),
},
jiracli.CommandRegistry{
Command: "todo",
Entry: cli.CmdTransitionRegistry("To Do"),
},
jiracli.CommandRegistry{
Command: "backlog",
Entry: cli.CmdTransitionRegistry("Backlog"),
},
jiracli.CommandRegistry{
Command: "done",
Entry: cli.CmdTransitionRegistry("Done"),
},
jiracli.CommandRegistry{
Command: "in-progress",
Aliases: []string{"prog", "progress"},
Entry: cli.CmdTransitionRegistry("Progress"),
},
}
cli.Register(app, registry)
app.Terminate(func(status int) {
for _, arg := range os.Args {
if arg == "-h" || arg == "--help" || len(os.Args) == 1 {
panic(jiracli.Exit{Code: 0})
}
}
panic(jiracli.Exit{Code: 1})
})
_, err := app.Parse(os.Args[1:])
if err != nil {
log.Fatalf("%s", err)
}
// user := os.Getenv("USER")
// home := os.Getenv("HOME")
// defaultQueryFields := "summary,created,updated,priority,status,reporter,assignee"
// defaultSort := "priority asc, key"
// defaultMaxResults := 500
// usage := func(ok bool) {
// printer := fmt.Printf
// if !ok {
// printer = func(format string, args ...interface{}) (int, error) {
// return fmt.Fprintf(os.Stderr, format, args...)
// }
// defer func() {
// os.Exit(1)
// }()
// } else {
// defer func() {
// os.Exit(0)
// }()
// }
// output := fmt.Sprintf(`
// Usage:
// jira BLOCKER blocks ISSUE
// jira issuelink OUTWARDISSUE ISSUELINKTYPE INWARDISSUE
// jira vote ISSUE [--down]
// jira rank ISSUE (after|before) ISSUE
// jira watch ISSUE [-w WATCHER] [--remove]
// jira (trans|transition) TRANSITION ISSUE [--noedit] <Edit Options>
// jira comment ISSUE [--noedit] <Edit Options>
// jira (set,add,remove) labels ISSUE [LABEL] ...
// jira take ISSUE
// jira (assign|give) ISSUE [ASSIGNEE|--default]
// jira unassign ISSUE
// jira issuelinktypes
// jira transmeta ISSUE
// jira add component [-p PROJECT] NAME DESCRIPTION LEAD
// jira components [-p PROJECT]
// jira issuetypes [-p PROJECT]
// jira createmeta [-p PROJECT] [-i ISSUETYPE]
// jira transitions ISSUE
// jira export-templates [-d DIR] [-t template]
// jira (b|browse) ISSUE
// jira request [-M METHOD] URI [DATA]
// jira ISSUE
// General Options:
// -b --browse Open your browser to the Jira issue
// -e --endpoint=URI URI to use for jira
// -k --insecure disable TLS certificate verification
// -h --help Show this usage
// -t --template=FILE Template file to use for output/editing
// -u --user=USER Username to use for authenticaion (default: %s)
// -v --verbose Increase output logging
// --unixproxy=PATH Path for a unix-socket proxy (eg., --unixproxy /tmp/proxy.sock)
// --version Print version
// Query Options:
// -a --assignee=USER Username assigned the issue
// -c --component=COMPONENT Component to Search for
// -f --queryfields=FIELDS Fields that are used in "list" template: (default: %s)
// -i --issuetype=ISSUETYPE The Issue Type
// -l --limit=VAL Maximum number of results to return in query (default: %d)
// --start=START Start parameter for pagination
// -p --project=PROJECT Project to Search for
// -q --query=JQL Jira Query Language expression for the search
// -r --reporter=USER Reporter to search for
// -s --sort=ORDER For list operations, sort issues (default: %s)
// -w --watcher=USER Watcher to add to issue (default: %s)
// or Watcher to search for
// Edit Options:
// -m --comment=COMMENT Comment message for transition
// -o --override=KEY=VAL Set custom key/value pairs
// Create Options:
// -i --issuetype=ISSUETYPE Jira Issue Type (default: Bug)
// -m --comment=COMMENT Comment message for transition
// -o --override=KEY=VAL Set custom key/value pairs
// Worklog Options:
// -T --time-spent=TIMESPENT Time spent working on issue
// -m --comment=COMMENT Comment message for worklog
// Command Options:
// -d --directory=DIR Directory to export templates to (default: %s)
// `, user, defaultQueryFields, defaultMaxResults, defaultSort, user, fmt.Sprintf("%s/.jira.d/templates", home))
// printer(output)
// }
// jiraCommands := map[string]string{
// "blocks": "blocks",
// "issuelink": "issuelink",
// "watch": "watch",
// "comment": "comment",
// "label": "labels",
// "labels": "labels",
// "component": "component",
// "components": "components",
// "take": "take",
// "assign": "assign",
// "give": "assign",
// "fields": "fields",
// "issuelinktypes": "issuelinktypes",
// "transmeta": "transmeta",
// "editmeta": "editmeta",
// "issuetypes": "issuetypes",
// "createmeta": "createmeta",
// "transitions": "transitions",
// "export-templates": "export-templates",
// "browse": "browse",
// "req": "request",
// "request": "request",
// "vote": "vote",
// "rank": "rank",
// "unassign": "unassign",
// }
// defaults := map[string]interface{}{
// "user": user,
// "queryfields": defaultQueryFields,
// "directory": fmt.Sprintf("%s/.jira.d/templates", home),
// "sort": defaultSort,
// "max_results": defaultMaxResults,
// "method": "GET",
// "quiet": false,
// }
// opts := make(map[string]interface{})
// setopt := func(name string, value interface{}) {
// opts[name] = value
// }
// op := optigo.NewDirectAssignParser(map[string]interface{}{
// "h|help": usage,
// "version": func() {
// fmt.Println(fmt.Sprintf("version: %s", jira.VERSION))
// os.Exit(0)
// },
// "v|verbose+": func() {
// logging.SetLevel(logging.GetLevel("")+1, "")
// },
// "dryrun": setopt,
// "b|browse": setopt,
// "editor=s": setopt,
// "u|user=s": setopt,
// "endpoint=s": setopt,
// "k|insecure": setopt,
// "t|template=s": setopt,
// "q|query=s": setopt,
// "p|project=s": setopt,
// "c|component=s": setopt,
// "a|assignee=s": setopt,
// "i|issuetype=s": setopt,
// "w|watcher=s": setopt,
// "remove": setopt,
// "r|reporter=s": setopt,
// "f|queryfields=s": setopt,
// "x|expand=s": setopt,
// "s|sort=s": setopt,
// "l|limit|max_results=i": setopt,
// "start|start_at=i": setopt,
// "o|override=s%": &opts,
// "noedit": setopt,
// "edit": setopt,
// "m|comment=s": setopt,
// "d|dir|directory=s": setopt,
// "M|method=s": setopt,
// "S|saveFile=s": setopt,
// "T|time-spent=s": setopt,
// "Q|quiet": setopt,
// "unixproxy": setopt,
// "down": setopt,
// "default": setopt,
// })
// if err := op.ProcessAll(os.Args[1:]); err != nil {
// log.Errorf("%s", err)
// usage(false)
// }
// args := op.Args
// var command string
// if len(args) > 0 {
// if alias, ok := jiraCommands[args[0]]; ok {
// command = alias
// args = args[1:]
// } else if len(args) > 1 {
// // look at second arg for "dups" and "blocks" commands
// // also for 'set/add/remove' actions like 'labels'
// if alias, ok := jiraCommands[args[1]]; ok {
// command = alias
// args = append(args[:1], args[2:]...)
// }
// }
// }
// if command == "" && len(args) > 0 {
// command = args[0]
// args = args[1:]
// }
// os.Setenv("JIRA_OPERATION", command)
// loadConfigs(opts)
// // check to see if it was set in the configs:
// if value, ok := opts["command"].(string); ok {
// command = value
// } else if _, ok := jiraCommands[command]; !ok || command == "" {
// if command != "" {
// args = append([]string{command}, args...)
// }
// command = "view"
// }
// // apply defaults
// for k, v := range defaults {
// if _, ok := opts[k]; !ok {
// log.Debugf("Setting %q to %#v from defaults", k, v)
// opts[k] = v
// }
// }
// log.Debugf("opts: %v", opts)
// log.Debugf("args: %v", args)
// if _, ok := opts["endpoint"]; !ok {
// log.Errorf("endpoint option required. Either use --endpoint or set a endpoint option in your ~/.jira.d/config.yml file")
// os.Exit(1)
// }
// c := jira.New(opts)
// log.Debugf("opts: %s", opts)
// setEditing := func(dflt bool) {
// log.Debugf("Default Editing: %t", dflt)
// if dflt {
// if val, ok := opts["noedit"].(bool); ok && val {
// log.Debugf("Setting edit = false")
// opts["edit"] = false
// } else {
// log.Debugf("Setting edit = true")
// opts["edit"] = true
// }
// } else {
// if _, ok := opts["edit"].(bool); !ok {
// log.Debugf("Setting edit = %t", dflt)
// opts["edit"] = dflt
// }
// }
// }
// requireArgs := func(count int) {
// if len(args) < count {
// log.Errorf("Not enough arguments. %d required, %d provided", count, len(args))
// usage(false)
// }
// }
// var err error
// switch command {
// case "issuelink":
// requireArgs(3)
// err = c.CmdIssueLink(args[0], args[1], args[2])
// case "login":
// err = c.CmdLogin()
// case "logout":
// err = c.CmdLogout()
// case "fields":
// err = c.CmdFields()
// case "list":
// err = c.CmdList()
// case "edit":
// setEditing(true)
// if len(args) > 0 {
// err = c.CmdEdit(args[0])
// } else {
// var data interface{}
// if data, err = c.FindIssues(); err == nil {
// issues := data.(map[string]interface{})["issues"].([]interface{})
// for _, issue := range issues {
// if err = c.CmdEdit(issue.(map[string]interface{})["key"].(string)); err != nil {
// switch err.(type) {
// case jira.NoChangesFound:
// log.Warning("No Changes found: %s", err)
// err = nil
// continue
// }
// break
// }
// }
// }
// }
// case "editmeta":
// requireArgs(1)
// err = c.CmdEditMeta(args[0])
// case "transmeta":
// requireArgs(1)
// err = c.CmdTransitionMeta(args[0])
// case "issuelinktypes":
// err = c.CmdIssueLinkTypes()
// case "issuetypes":
// err = c.CmdIssueTypes()
// case "createmeta":
// err = c.CmdCreateMeta()
// case "create":
// setEditing(true)
// err = c.CmdCreate()
// case "subtask":
// setEditing(true)
// err = c.CmdSubtask(args[0])
// case "transitions":
// requireArgs(1)
// err = c.CmdTransitions(args[0])
// case "blocks":
// requireArgs(2)
// err = c.CmdBlocks(args[0], args[1])
// case "dups":
// setEditing(true)
// requireArgs(2)
// if err = c.CmdDups(args[0], args[1]); err == nil {
// opts["resolution"] = "Duplicate"
// trans, err := c.ValidTransitions(args[0])
// if err == nil {
// if trans.Find("close") != nil {
// err = c.CmdTransition(args[0], "close")
// } else if trans.Find("done") != nil {
// // for now just assume if there is no "close", then
// // there is a "done" state
// err = c.CmdTransition(args[0], "done")
// } else if trans.Find("start") != nil {
// err = c.CmdTransition(args[0], "start")
// if err == nil {
// err = c.CmdTransition(args[0], "stop")
// }
// }
// }
// }
// case "watch":
// requireArgs(1)
// watcher := c.GetOptString("watcher", opts["user"].(string))
// remove := c.GetOptBool("remove", false)
// err = c.CmdWatch(args[0], watcher, remove)
// case "transition":
// requireArgs(2)
// setEditing(true)
// err = c.CmdTransition(args[1], args[0])
// case "comment":
// requireArgs(1)
// setEditing(true)
// err = c.CmdComment(args[0])
// case "labels":
// requireArgs(2)
// action := args[0]
// issue := args[1]
// labels := args[2:]
// err = c.CmdLabels(action, issue, labels)
// case "component":
// requireArgs(2)
// action := args[0]
// project := opts["project"].(string)
// name := args[1]
// var lead string
// var description string
// if len(args) > 2 {
// description = args[2]
// }
// if len(args) > 3 {
// lead = args[2]
// }
// err = c.CmdComponent(action, project, name, description, lead)
// case "components":
// project := opts["project"].(string)
// err = c.CmdComponents(project)
// case "take":
// requireArgs(1)
// err = c.CmdAssign(args[0], opts["user"].(string))
// case "browse":
// requireArgs(1)
// opts["browse"] = true
// err = c.Browse(args[0])
// case "export-templates":
// err = c.CmdExportTemplates()
// case "assign":
// requireArgs(1)
// assignee := ""
// if len(args) > 1 {
// assignee = args[1]
// }
// err = c.CmdAssign(args[0], assignee)
// case "unassign":
// requireArgs(1)
// err = c.CmdUnassign(args[0])
// case "view":
// requireArgs(1)
// err = c.CmdView(args[0])
// case "worklog":
// if len(args) > 0 && args[0] == "add" {
// setEditing(true)
// requireArgs(2)
// err = c.CmdWorklog(args[0], args[1])
// } else {
// requireArgs(1)
// err = c.CmdWorklogs(args[0])
// }
// case "vote":
// requireArgs(1)
// if val, ok := opts["down"]; ok {
// err = c.CmdVote(args[0], !val.(bool))
// } else {
// err = c.CmdVote(args[0], true)
// }
// case "rank":
// requireArgs(3)
// if args[1] == "after" {
// err = c.CmdRankAfter(args[0], args[2])
// } else {
// err = c.CmdRankBefore(args[0], args[2])
// }
// case "request":
// requireArgs(1)
// data := ""
// if len(args) > 1 {
// data = args[1]
// }
// err = c.CmdRequest(args[0], data)
// default:
// log.Errorf("Unknown command %s", command)
// os.Exit(1)
// }
// if err != nil {
// log.Errorf("%s", err)
// os.Exit(1)
// }
// os.Exit(0)
}
// func parseYaml(file string, opts map[string]interface{}) {
// if fh, err := ioutil.ReadFile(file); err == nil {
// log.Debugf("Found Config file: %s", file)
// if err := yaml.Unmarshal(fh, &opts); err != nil {
// log.Errorf("Unable to parse %s: %s", file, err)
// }
// }
// }
// func populateEnv(opts map[string]interface{}) {
// for k, v := range opts {
// envName := fmt.Sprintf("JIRA_%s", strings.ToUpper(k))
// var val string
// switch t := v.(type) {
// case string:
// val = t
// case int, int8, int16, int32, int64:
// val = fmt.Sprintf("%d", t)
// case float32, float64:
// val = fmt.Sprintf("%f", t)
// case bool:
// val = fmt.Sprintf("%t", t)
// default:
// val = fmt.Sprintf("%v", t)
// }
// os.Setenv(envName, val)
// }
// }
// func loadConfigs(opts map[string]interface{}) {
// populateEnv(opts)
// paths := jira.FindParentPaths(".jira.d/config.yml")
// // prepend
// paths = append(paths, "/etc/go-jira.yml")
// // iterate paths in reverse
// for i := 0; i < len(paths); i++ {
// file := paths[i]
// if stat, err := os.Stat(file); err == nil {
// tmp := make(map[string]interface{})
// // check to see if config file is exectuable
// if stat.Mode()&0111 == 0 {
// parseYaml(file, tmp)
// } else {
// log.Debugf("Found Executable Config file: %s", file)
// // it is executable, so run it and try to parse the output
// cmd := exec.Command(file)
// stdout := bytes.NewBufferString("")
// cmd.Stdout = stdout
// cmd.Stderr = bytes.NewBufferString("")
// if err := cmd.Run(); err != nil {
// log.Errorf("%s is exectuable, but it failed to execute: %s\n%s", file, err, cmd.Stderr)
// os.Exit(1)
// }
// yaml.Unmarshal(stdout.Bytes(), &tmp)
// }
// for k, v := range tmp {
// if _, ok := opts[k]; !ok {
// log.Debugf("Setting %q to %#v from %s", k, v, file)
// opts[k] = v
// }
// }
// populateEnv(opts)
// }
// }
// }
-1138
View File
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
package jira
import (
"fmt"
"net/http"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
)
func responseError(resp *http.Response) error {
results := &jiradata.ErrorCollection{}
if err := readJSON(resp.Body, results); err != nil {
return err
}
if len(results.ErrorMessages) == 0 && len(results.Errors) == 0 {
return fmt.Errorf(resp.Status)
}
return results
}
+22
View File
@@ -0,0 +1,22 @@
package jira
import (
"fmt"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
)
// https://docs.atlassian.com/jira/REST/cloud/#api/2/field-getFields
func (j *Jira) GetFields() ([]jiradata.Field, error) {
uri := fmt.Sprintf("%s/rest/api/2/field", j.Endpoint)
resp, err := j.UA.GetJSON(uri)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
results := []jiradata.Field{}
return results, readJSON(resp.Body, &results)
}
return nil, responseError(resp)
}
Generated
+69
View File
@@ -0,0 +1,69 @@
hash: 8ca06c1ec629a3203f7d4289f69fd4e88672d2e66a12110ba4e1ac9b0edb5888
updated: 2017-07-30T20:24:36.662438626-07:00
imports:
- name: github.com/AlecAivazis/survey
version: 73fd4d7829877a72e03dbb42f84ed383fbbc5fa0
subpackages:
- core
- terminal
- name: github.com/alecthomas/template
version: a0175ee3bccc567396460bf5acd36800cb10c49c
subpackages:
- parse
- name: github.com/alecthomas/units
version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a
- name: github.com/cheekybits/genny
version: 9127e812e1e9e501ce899a18121d316ecb52e4ba
subpackages:
- generic
- name: github.com/coryb/figtree
version: 924d400f931992b528015d92be87a73e6e3a66c3
- name: github.com/coryb/oreo
version: e3bbbcdf1c7eac4e992018bc452230c02d9632c2
- name: github.com/fatih/camelcase
version: f6a740d52f961c60348ebb109adde9f4635d7540
- name: github.com/guelfey/go.dbus
version: f6a3a2366cc39b8479cadc499d3c735fb10fbdda
- name: github.com/jinzhu/copier
version: 8bfca8a02a0ce12119cdc4974143c834ca589257
- name: github.com/kballard/go-shellquote
version: d8ec1a69a250a17bb0e419c386eac1f3711dc142
- name: github.com/kr/pretty
version: cfb55aafdaf3ec08f0db22699ab822c50091b1c4
- name: github.com/kr/text
version: 7cafcd837844e784b526369c9bce262804aebc60
- name: github.com/mattn/go-isatty
version: 57fdcb988a5c543893cc61bce354a6e24ab70022
- name: github.com/mgutz/ansi
version: c286dcecd19ff979eeb73ea444e479b903f2cfcb
- name: github.com/pkg/errors
version: 645ef00459ed84a119197bfb8d8205042c6df63d
- name: github.com/sethgrid/pester
version: 8053687f99650573b28fb75cddf3f295082704d7
- name: github.com/theckman/go-flock
version: 6de226b0d5f040ed85b88c82c381709b98277f3d
- name: github.com/tmc/keyring
version: 39227cc0349f1b69956c23aa1f679eefd17ebae0
- name: golang.org/x/sys
version: e24f485414aeafb646f6fca458b0bf869c0880a1
subpackages:
- unix
- name: gopkg.in/alecthomas/kingpin.v2
version: 1087e65c9441605df944fb12c33f0fe7072d18ca
- name: gopkg.in/coryb/yaml.v2
version: fb7cb9628c6e3bdd76c29fb91798d51a09832470
- name: gopkg.in/op/go-logging.v1
version: b2cb9fa56473e98db8caba80237377e83fe44db5
testImports:
- 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
+23
View File
@@ -0,0 +1,23 @@
package: gopkg.in/Netflix-Skunkworks/go-jira.v1
import:
- package: github.com/coryb/figtree
- package: github.com/coryb/oreo
- package: github.com/mgutz/ansi
- package: github.com/pkg/errors
version: ^0.8.0
- package: github.com/sethgrid/pester
- package: github.com/theckman/go-flock
- package: gopkg.in/alecthomas/kingpin.v2
version: ^2.2.4
- package: gopkg.in/op/go-logging.v1
version: ^1.0.0
- package: github.com/AlecAivazis/survey
version: ^1.2.4
- package: github.com/tmc/keyring
- package: github.com/kballard/go-shellquote
- package: github.com/jinzhu/copier
testImport:
- package: github.com/stretchr/testify
version: ^1.1.4
subpackages:
- assert
+13
View File
@@ -0,0 +1,13 @@
package jira
import (
"io"
"net/http"
)
type HttpClient interface {
Delete(url string) (*http.Response, error)
GetJSON(url string) (*http.Response, error)
Post(url, bodyType string, body io.Reader) (*http.Response, error)
Put(url, bodyType string, body io.Reader) (*http.Response, error)
}
+297
View File
@@ -0,0 +1,297 @@
package jira
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
)
type IssueQueryProvider interface {
ProvideIssueQueryString() string
}
type IssueOptions struct {
Fields []string `json:"fields,omitempty" yaml:"fields,omitempty"`
Expand []string `json:"expand,omitempty" yaml:"expand,omitempty"`
Properties []string `json:"properties,omitempty" yaml:"properties,omitempty"`
FieldsByKeys bool `json:"fieldsByKeys,omitempty" yaml:"fieldsByKeys,omitempty"`
UpdateHistory bool `json:"updateHistory,omitempty" yaml:"updateHistory,omitempty"`
}
func (o *IssueOptions) ProvideIssueQueryString() string {
params := []string{}
if len(o.Fields) > 0 {
params = append(params, "fields="+strings.Join(o.Fields, ","))
}
if len(o.Expand) > 0 {
params = append(params, "expand="+strings.Join(o.Expand, ","))
}
if len(o.Properties) > 0 {
params = append(params, "properties="+strings.Join(o.Properties, ","))
}
if o.FieldsByKeys {
params = append(params, "fieldsByKeys=true")
}
if o.UpdateHistory {
params = append(params, "updateHistory=true")
}
if len(params) > 0 {
return "?" + strings.Join(params, "&")
}
return ""
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-getIssue
func (j *Jira) GetIssue(issue string, iqg IssueQueryProvider) (*jiradata.Issue, error) {
query := ""
if iqg != nil {
query = iqg.ProvideIssueQueryString()
}
uri := fmt.Sprintf("%s/rest/api/2/issue/%s%s", j.Endpoint, issue, query)
resp, err := j.UA.GetJSON(uri)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
results := &jiradata.Issue{}
return results, readJSON(resp.Body, results)
}
return nil, responseError(resp)
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/worklog-getIssueWorklog
func (j *Jira) GetIssueWorklog(issue string) (*jiradata.Worklogs, error) {
startAt := 0
total := 1
maxResults := 100
worklogs := jiradata.Worklogs{}
for startAt < total {
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/worklog?startAt=%d&maxResults=%d", j.Endpoint, issue, startAt, maxResults)
resp, err := j.UA.GetJSON(uri)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
results := &jiradata.WorklogWithPagination{}
err := readJSON(resp.Body, results)
if err != nil {
return nil, err
}
startAt = startAt + maxResults
total = results.Total
for _, worklog := range results.Worklogs {
worklogs = append(worklogs, worklog)
}
} else {
return nil, responseError(resp)
}
}
return &worklogs, nil
}
type WorklogProvider interface {
ProvideWorklog() *jiradata.Worklog
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/worklog-addWorklog
func (j *Jira) AddIssueWorklog(issue string, wp WorklogProvider) (*jiradata.Worklog, error) {
req := wp.ProvideWorklog()
encoded, err := json.Marshal(req)
if err != nil {
return nil, err
}
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/worklog", j.Endpoint, issue)
resp, err := j.UA.Post(uri, "application/json", bytes.NewBuffer(encoded))
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 201 {
results := &jiradata.Worklog{}
return results, readJSON(resp.Body, results)
}
return nil, responseError(resp)
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-getEditIssueMeta
func (j *Jira) GetIssueEditMeta(issue string) (*jiradata.EditMeta, error) {
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/editmeta", j.Endpoint, issue)
resp, err := j.UA.GetJSON(uri)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
results := &jiradata.EditMeta{}
return results, readJSON(resp.Body, results)
}
return nil, responseError(resp)
}
type IssueUpdateProvider interface {
ProvideIssueUpdate() *jiradata.IssueUpdate
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-editIssue
func (j *Jira) EditIssue(issue string, iup IssueUpdateProvider) error {
req := iup.ProvideIssueUpdate()
encoded, err := json.Marshal(req)
if err != nil {
return err
}
uri := fmt.Sprintf("%s/rest/api/2/issue/%s", j.Endpoint, issue)
resp, err := j.UA.Put(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/REST/cloud/#api/2/issue-createIssue
func (j *Jira) CreateIssue(iup IssueUpdateProvider) (*jiradata.IssueCreateResponse, error) {
req := iup.ProvideIssueUpdate()
encoded, err := json.Marshal(req)
if err != nil {
return nil, err
}
uri := fmt.Sprintf("%s/rest/api/2/issue", j.Endpoint)
resp, err := j.UA.Post(uri, "application/json", bytes.NewBuffer(encoded))
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 201 {
results := &jiradata.IssueCreateResponse{}
return results, readJSON(resp.Body, results)
}
return nil, responseError(resp)
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-getCreateIssueMeta
func (j *Jira) GetIssueCreateMetaProject(projectKey string) (*jiradata.CreateMetaProject, error) {
uri := fmt.Sprintf("%s/rest/api/2/issue/createmeta?projectKeys=%s&expand=projects.issuetypes.fields", j.Endpoint, projectKey)
resp, err := j.UA.GetJSON(uri)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
results := &jiradata.CreateMeta{}
err = readJSON(resp.Body, results)
if err != nil {
return nil, err
}
for _, project := range results.Projects {
if project.Key == projectKey {
return project, nil
}
}
return nil, fmt.Errorf("Project %s not found", projectKey)
}
return nil, responseError(resp)
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-getCreateIssueMeta
func (j *Jira) GetIssueCreateMetaIssueType(projectKey, issueTypeName string) (*jiradata.CreateMetaIssueType, error) {
uri := fmt.Sprintf("%s/rest/api/2/issue/createmeta?projectKeys=%s&issuetypeNames=%s&expand=projects.issuetypes.fields", j.Endpoint, projectKey, issueTypeName)
resp, err := j.UA.GetJSON(uri)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
results := &jiradata.CreateMeta{}
err = readJSON(resp.Body, results)
if err != nil {
return nil, err
}
for _, project := range results.Projects {
if project.Key == projectKey {
for _, issueType := range project.Issuetypes {
if issueType.Name == issueTypeName {
return issueType, nil
}
}
}
}
return nil, fmt.Errorf("Project %s and IssueType %s not found", projectKey, issueTypeName)
}
return nil, responseError(resp)
}
type LinkIssueProvider interface {
ProvideLinkIssueRequest() *jiradata.LinkIssueRequest
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issueLink-linkIssues
func (j *Jira) LinkIssues(lip LinkIssueProvider) error {
req := lip.ProvideLinkIssueRequest()
encoded, err := json.Marshal(req)
if err != nil {
return err
}
uri := fmt.Sprintf("%s/rest/api/2/issueLink", j.Endpoint)
resp, err := j.UA.Post(uri, "application/json", bytes.NewBuffer(encoded))
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode == 201 {
return nil
}
return responseError(resp)
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-getTransitions
func (j *Jira) GetIssueTransitions(issue string) (*jiradata.TransitionsMeta, error) {
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/transitions?expand=transitions.fields", j.Endpoint, issue)
resp, err := j.UA.GetJSON(uri)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
results := &jiradata.TransitionsMeta{}
return results, readJSON(resp.Body, results)
}
return nil, responseError(resp)
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-doTransition
func (j *Jira) TransitionIssue(issue string, iup IssueUpdateProvider) error {
req := iup.ProvideIssueUpdate()
encoded, err := json.Marshal(req)
if err != nil {
return err
}
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/transitions", j.Endpoint, issue)
resp, err := j.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)
}
+22
View File
@@ -0,0 +1,22 @@
package jira
import (
"github.com/coryb/oreo"
logging "gopkg.in/op/go-logging.v1"
)
var log = logging.MustGetLogger("jira")
const VERSION = "1.0.0"
type Jira struct {
Endpoint string `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
UA HttpClient `json:"-" yaml:"-"`
}
func NewJira(endpoint string) *Jira {
return &Jira{
Endpoint: endpoint,
UA: oreo.New(),
}
}
+69
View File
@@ -0,0 +1,69 @@
package jiracli
import (
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type BlockOptions struct {
GlobalOptions
jiradata.LinkIssueRequest
Blocker string
Issue string
}
func (jc *JiraCli) CmdBlockRegistry() *CommandRegistryEntry {
opts := BlockOptions{
GlobalOptions: GlobalOptions{
Template: "edit",
},
}
return &CommandRegistryEntry{
"Mark issues as blocker",
func() error {
return jc.CmdBlock(&opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdBlockUsage(cmd, &opts)
},
}
}
func (jc *JiraCli) CmdBlockUsage(cmd *kingpin.CmdClause, opts *BlockOptions) error {
if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil {
return err
}
jc.EditorUsage(cmd, &opts.GlobalOptions)
jc.TemplateUsage(cmd, &opts.GlobalOptions)
cmd.Flag("comment", "Comment message when marking issue as blocker").Short('m').PreAction(func(ctx *kingpin.ParseContext) error {
opts.Comment = &jiradata.Comment{
Body: flagValue(ctx, "comment"),
}
return nil
}).String()
cmd.Arg("BLOCKER", "blocker issue").Required().StringVar(&opts.Blocker)
cmd.Arg("ISSUE", "issue that is blocked").Required().StringVar(&opts.Issue)
return nil
}
// CmdBlock will update the given issue as being a duplicate by the given dup issue
// and will attempt to resolve the dup issue
func (jc *JiraCli) CmdBlock(opts *BlockOptions) error {
opts.Type = &jiradata.IssueLinkType{
// FIXME is this consitent across multiple jira installs?
Name: "Blocks",
}
opts.InwardIssue = &jiradata.IssueRef{
Key: opts.Issue,
}
opts.OutwardIssue = &jiradata.IssueRef{
Key: opts.Blocker,
}
return jc.LinkIssues(&opts.LinkIssueRequest)
// FIXME implement browse
return nil
}
+638
View File
@@ -0,0 +1,638 @@
package jiracli
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"reflect"
"strings"
"github.com/AlecAivazis/survey"
"github.com/coryb/figtree"
"github.com/coryb/oreo"
"github.com/jinzhu/copier"
shellquote "github.com/kballard/go-shellquote"
jira "gopkg.in/Netflix-Skunkworks/go-jira.v1"
kingpin "gopkg.in/alecthomas/kingpin.v2"
yaml "gopkg.in/coryb/yaml.v2"
logging "gopkg.in/op/go-logging.v1"
)
var log = logging.MustGetLogger("jira")
type JiraCli struct {
jira.Jira `yaml:",inline"`
ConfigDir string
oreoAgent *oreo.Client
}
func New(configDir string) *JiraCli {
agent := oreo.New().WithCookieFile(filepath.Join(homedir(), configDir, "cookies.js"))
return &JiraCli{
ConfigDir: configDir,
Jira: jira.Jira{
UA: agent,
},
oreoAgent: agent,
}
}
type Exit struct {
Code int
}
type GlobalOptions struct {
Browse string `json:"browse,omitempty" yaml:"browse,omitempty"`
Editor string `json:"editor,omitempty" yaml:"editor,omitempty"`
SkipEditing bool `json:"noedit,omitempty" yaml:"noedit,omitempty"`
PasswordSource string `json:"password-source,omitempty" yaml:"password-source,omitempty"`
Template string `json:"template,omitempty" yaml:"template,omitempty"`
User string `json:"user,omitempty", yaml:"user,omitempty"`
}
func (jc *JiraCli) GlobalUsage(cmd *kingpin.CmdClause, opts *GlobalOptions) error {
jc.LoadConfigs(cmd, opts)
cmd.PreAction(func(_ *kingpin.ParseContext) error {
fig := figtree.NewFigTree()
fig.EnvPrefix = "JIRA"
// populate JiraCli fields if defined in configs (ie for Endpoint)
if err := fig.LoadAllConfigs(path.Join(jc.ConfigDir, "config.yml"), jc); err != nil {
return err
}
if opts.User == "" {
opts.User = os.Getenv("USER")
}
return nil
})
cmd.Flag("endpoint", "URI to use for Jira").Short('e').StringVar(&jc.Endpoint)
cmd.Flag("user", "Login mame used for authentication with Jira service").Short('u').StringVar(&opts.User)
return nil
}
func (jc *JiraCli) LoadConfigs(cmd *kingpin.CmdClause, opts interface{}) {
cmd.PreAction(func(_ *kingpin.ParseContext) error {
fig := figtree.NewFigTree()
fig.EnvPrefix = "JIRA"
// load command specific configs first
if err := fig.LoadAllConfigs(path.Join(jc.ConfigDir, strings.Join(strings.Fields(cmd.FullCommand()), "_")+".yml"), opts); err != nil {
return err
}
// then load generic configs if not already populated above
return fig.LoadAllConfigs(path.Join(jc.ConfigDir, "config.yml"), opts)
})
}
func (jc *JiraCli) EditorUsage(cmd *kingpin.CmdClause, opts *GlobalOptions) {
cmd.Flag("editor", "Editor to use").StringVar(&opts.Editor)
}
func (jc *JiraCli) TemplateUsage(cmd *kingpin.CmdClause, opts *GlobalOptions) {
cmd.Flag("template", "Template to use for output").Short('t').StringVar(&opts.Template)
}
func (o *GlobalOptions) editFile(fileName string) (changes bool, err error) {
var editor string
for _, ed := range []string{o.Editor, os.Getenv("JIRA_EDITOR"), os.Getenv("EDITOR"), "vim"} {
if ed != "" {
editor = ed
break
}
}
if o.SkipEditing {
return false, nil
}
tmpFileNameOrig := fmt.Sprintf("%s.orig", fileName)
if err := copyFile(fileName, tmpFileNameOrig); err != nil {
return false, err
}
defer func() {
os.Remove(tmpFileNameOrig)
}()
shell, _ := shellquote.Split(editor)
shell = append(shell, fileName)
log.Debugf("Running: %#v", shell)
cmd := exec.Command(shell[0], shell[1:]...)
cmd.Stdout, cmd.Stderr, cmd.Stdin = os.Stdout, os.Stderr, os.Stdin
if err := cmd.Run(); err != nil {
return false, err
}
// now we just need to diff the files to see if there are any changes
var oldHandle, newHandle *os.File
var oldStat, newStat os.FileInfo
if oldHandle, err = os.Open(tmpFileNameOrig); err == nil {
if newHandle, err = os.Open(fileName); err == nil {
if oldStat, err = oldHandle.Stat(); err == nil {
if newStat, err = newHandle.Stat(); err == nil {
// different sizes, so must have changes
if oldStat.Size() != newStat.Size() {
return true, err
}
oldBuf, newBuf := make([]byte, 1024), make([]byte, 1024)
var oldCount, newCount int
// loop though 1024 bytes at a time comparing the buffers for changes
for err != io.EOF {
oldCount, _ = oldHandle.Read(oldBuf)
newCount, err = newHandle.Read(newBuf)
if oldCount != newCount {
return true, nil
}
if bytes.Compare(oldBuf[:oldCount], newBuf[:newCount]) != 0 {
return true, nil
}
}
return false, nil
}
}
}
}
return false, err
}
func (jc *JiraCli) editLoop(opts *GlobalOptions, input interface{}, output interface{}, submit func() error) error {
tmpFile, err := jc.tmpTemplate(opts.Template, input)
if err != nil {
return err
}
confirm := func(msg string) (answer bool) {
survey.AskOne(
&survey.Confirm{Message: msg, Default: true},
&answer,
nil,
)
return
}
// we need to copy the original output so that we can restore
// it on retries in case we try to populate bogus fields that
// are rejected by the jira service.
dup := reflect.New(reflect.ValueOf(output).Elem().Type())
err = copier.Copy(dup.Interface(), output)
if err != nil {
return err
}
for {
if !opts.SkipEditing {
changes, err := opts.editFile(tmpFile)
if err != nil {
log.Error(err.Error())
if confirm("Editor reported an error, edit again?") {
continue
}
panic(Exit{Code: 1})
}
if !changes {
if !confirm("No changes detected, submit anyway?") {
panic(Exit{Code: 1})
}
}
}
// parse template
data, err := ioutil.ReadFile(tmpFile)
if err != nil {
return 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()
// restore output incase of retry loop
err = copier.Copy(output, dup.Interface())
if err != nil {
return err
}
// HACK HACK HACK we want to trim out all the yaml garbage that is not
// poplulated, like empty arrays, string values with only a newline,
// etc. We need to do this because jira will reject json documents
// with empty arrays, or empty strings typically. So here we process
// the data to a raw interface{} then we fixup the yaml parsed
// inferface, then we serialize to a new yaml document ... then is
// parsed as the original document to populate the output struct. Phew.
var raw interface{}
if err := yaml.Unmarshal(data, &raw); err != nil {
log.Error(err.Error())
if confirm("Invalid YAML syntax, edit again?") {
continue
}
panic(Exit{Code: 1})
}
yamlFixup(&raw)
fixedYAML, err := yaml.Marshal(&raw)
if err != nil {
log.Error(err.Error())
if confirm("Invalid YAML syntax, edit again?") {
continue
}
panic(Exit{Code: 1})
}
if err := yaml.Unmarshal(fixedYAML, output); err != nil {
log.Error(err.Error())
if confirm("Invalid YAML syntax, edit again?") {
continue
}
panic(Exit{Code: 1})
}
// submit template
if err := submit(); err != nil {
log.Error(err.Error())
if confirm("Jira reported an error, edit again?") {
continue
}
panic(Exit{Code: 1})
}
break
}
return nil
}
// // New creates go-jira client object
// func New(opts map[string]interface{}) *Cli {
// homedir := homedir()
// cookieJar, _ := cookiejar.New(nil)
// endpoint, _ := opts["endpoint"].(string)
// url, _ := url.Parse(strings.TrimRight(endpoint, "/"))
// if project, ok := opts["project"].(string); ok {
// opts["project"] = strings.ToUpper(project)
// }
// var ua *http.Client
// if unixProxyPath, ok := opts["unixproxy"].(string); ok {
// ua = &http.Client{
// Jar: cookieJar,
// Transport: UnixProxy(unixProxyPath),
// }
// } else {
// transport := &http.Transport{
// Proxy: http.ProxyFromEnvironment,
// TLSClientConfig: &tls.Config{},
// }
// if insecureSkipVerify, ok := opts["insecure"].(bool); ok {
// transport.TLSClientConfig.InsecureSkipVerify = insecureSkipVerify
// }
// ua = &http.Client{
// Jar: cookieJar,
// Transport: transport,
// }
// }
// cli := &Cli{
// endpoint: url,
// opts: opts,
// cookieFile: filepath.Join(homedir, ".jira.d", "cookies.js"),
// ua: ua,
// }
// cli.ua.Jar.SetCookies(url, cli.loadCookies())
// return cli
// }
// // NoChangesFound is an error returned from when editing templates
// // and no modifications were made while editing
// type NoChangesFound struct{}
// func (f NoChangesFound) Error() string {
// return "No changes found, aborting"
// }
// func (c *Cli) editTemplate(template string, tmpFilePrefix string, templateData map[string]interface{}, templateProcessor func(string) error) error {
// tmpdir := filepath.Join(homedir(), ".jira.d", "tmp")
// if err := mkdir(tmpdir); err != nil {
// return err
// }
// fh, err := ioutil.TempFile(tmpdir, tmpFilePrefix)
// if err != nil {
// log.Errorf("Failed to make temp file in %s: %s", tmpdir, err)
// return err
// }
// oldFileName := fh.Name()
// tmpFileName := fmt.Sprintf("%s.yml", oldFileName)
// // close tmpfile so we can rename on windows
// fh.Close()
// if err := os.Rename(oldFileName, tmpFileName); err != nil {
// log.Errorf("Failed to rename %s to %s: %s", oldFileName, tmpFileName, err)
// return err
// }
// fh, err = os.OpenFile(tmpFileName, os.O_RDWR|os.O_EXCL, 0600)
// if err != nil {
// log.Errorf("Failed to reopen temp file file in %s: %s", tmpFileName, err)
// return err
// }
// defer fh.Close()
// defer func() {
// os.Remove(tmpFileName)
// }()
// err = runTemplate(template, templateData, fh)
// if err != nil {
// return err
// }
// fh.Close()
// editor, ok := c.opts["editor"].(string)
// if !ok {
// editor = os.Getenv("JIRA_EDITOR")
// if editor == "" {
// editor = os.Getenv("EDITOR")
// if editor == "" {
// editor = "vim"
// }
// }
// }
// editing := c.getOptBool("edit", true)
// tmpFileNameOrig := fmt.Sprintf("%s.orig", tmpFileName)
// copyFile(tmpFileName, tmpFileNameOrig)
// defer func() {
// os.Remove(tmpFileNameOrig)
// }()
// for true {
// if editing {
// shell, _ := shellquote.Split(editor)
// shell = append(shell, tmpFileName)
// log.Debugf("Running: %#v", shell)
// cmd := exec.Command(shell[0], shell[1:]...)
// cmd.Stdout, cmd.Stderr, cmd.Stdin = os.Stdout, os.Stderr, os.Stdin
// if err := cmd.Run(); err != nil {
// log.Errorf("Failed to edit template with %s: %s", editor, err)
// if promptYN("edit again?", true) {
// continue
// }
// return err
// }
// diff := exec.Command("diff", "-q", tmpFileNameOrig, tmpFileName)
// // if err == nil then diff found no changes
// if err := diff.Run(); err == nil {
// return NoChangesFound{}
// }
// }
// edited := make(map[string]interface{})
// 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
// }
// 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
// }
// var fixed interface{}
// if fixed, err = yamlFixup(edited); err != nil {
// return err
// }
// 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
// // and we will abort now
// if val, ok := edited["abort"].(bool); ok && val {
// log.Infof("abort flag found in template, quiting")
// return fmt.Errorf("abort flag found in template, quiting")
// }
// if _, ok := templateData["meta"]; ok {
// mf := templateData["meta"].(map[string]interface{})["fields"]
// if f, ok := edited["fields"].(map[string]interface{}); ok {
// for k := range f {
// if _, ok := mf.(map[string]interface{})[k]; !ok {
// err := fmt.Errorf("Field %s is not editable", k)
// log.Errorf("%s", err)
// if editing && promptYN("edit again?", true) {
// continue
// }
// return err
// }
// }
// }
// }
// json, err := jsonEncode(edited)
// if err != nil {
// return err
// }
// if err := templateProcessor(json); err != nil {
// log.Errorf("%s", err)
// if editing && promptYN("edit again?", true) {
// continue
// }
// }
// return nil
// }
// 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" {
// return exec.Command("open", fmt.Sprintf("%s/browse/%s", c.endpoint, issue)).Run()
// } else if runtime.GOOS == "linux" {
// return exec.Command("xdg-open", fmt.Sprintf("%s/browse/%s", c.endpoint, issue)).Run()
// } else if runtime.GOOS == "windows" {
// return exec.Command("cmd", "/c", "start", fmt.Sprintf("%s/browse/%s", c.endpoint, issue)).Run()
// }
// }
// 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)
// }
// return 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")
// 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
// }
// qbuff.WriteString(fmt.Sprintf(" AND project = '%s'", project))
// if component, ok := c.opts["component"]; ok {
// qbuff.WriteString(fmt.Sprintf(" AND component = '%s'", component))
// }
// if assignee, ok := c.opts["assignee"]; ok {
// qbuff.WriteString(fmt.Sprintf(" AND assignee = '%s'", assignee))
// }
// if issuetype, ok := c.opts["issuetype"]; ok {
// qbuff.WriteString(fmt.Sprintf(" AND issuetype = '%s'", issuetype))
// }
// if watcher, ok := c.opts["watcher"]; ok {
// qbuff.WriteString(fmt.Sprintf(" AND watcher = '%s'", watcher))
// }
// if reporter, ok := c.opts["reporter"]; ok {
// qbuff.WriteString(fmt.Sprintf(" AND reporter = '%s'", reporter))
// }
// if sort, ok := c.opts["sort"]; ok && sort != "" {
// qbuff.WriteString(fmt.Sprintf(" ORDER BY %s", sort))
// }
// query = qbuff.String()
// }
// fields := []string{"summary"}
// if qf, ok := c.opts["queryfields"].(string); ok {
// fields = strings.Split(qf, ",")
// }
// json, err := jsonEncode(map[string]interface{}{
// "jql": query,
// "startAt": c.opts["start_at"],
// "maxResults": c.opts["max_results"],
// "fields": fields,
// "expand": c.expansions(),
// })
// if err != nil {
// return nil, err
// }
// uri := fmt.Sprintf("%s/rest/api/2/search", c.endpoint)
// var data interface{}
// if data, err = responseToJSON(c.post(uri, json)); err != nil {
// return nil, err
// }
// return data, nil
// }
// // RankOrder type used to specify before/after ranking arguments to RankIssue
// type RankOrder int
// const (
// // RANKBEFORE should be used to rank issue before the target issue
// RANKBEFORE RankOrder = iota
// // RANKAFTER should be used to rank issue after the target issue
// RANKAFTER RankOrder = iota
// )
// // RankIssue will modify issue to have rank before or after the target issue
// func (c *Cli) RankIssue(issue, target string, order RankOrder) error {
// type RankRequest struct {
// Issues []string `json:"issues"`
// Before string `json:"rankBeforeIssue,omitempty"`
// After string `json:"rankAfterIssue,omitempty"`
// }
// req := &RankRequest{
// Issues: []string{
// issue,
// },
// }
// if order == RANKBEFORE {
// req.Before = target
// } else {
// req.After = target
// }
// json, err := jsonEncode(req)
// if err != nil {
// return err
// }
// uri := fmt.Sprintf("%s/rest/agile/1.0/issue/rank", c.endpoint)
// if c.getOptBool("dryrun", false) {
// log.Debugf("PUT: %s", json)
// log.Debugf("Dryrun mode, skipping PUT")
// return nil
// }
// resp, err := c.put(uri, json)
// if err != nil {
// return err
// }
// if resp.StatusCode != 204 {
// return fmt.Errorf("failed to modify issue rank: %s", resp.Status)
// }
// return 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)
// }
// func (c *Cli) getOptString(optName string, dflt string) string {
// if val, ok := c.opts[optName].(string); ok {
// return val
// }
// 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)
// }
// func (c *Cli) getOptBool(optName string, dflt bool) bool {
// if val, ok := c.opts[optName].(bool); ok {
// return val
// }
// return dflt
// }
// // expansions returns a comma-separated list of values for field expansion
// func (c *Cli) expansions() []string {
// var expansions []string
// if x, ok := c.opts["expand"].(string); ok {
// expansions = strings.Split(x, ",")
// }
// return expansions
// }
+737
View File
@@ -0,0 +1,737 @@
package jiracli
import (
"strings"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type CommandRegistryEntry struct {
Help string
ExecuteFunc func() error
UsageFunc func(*kingpin.CmdClause) error
}
type CommandRegistry struct {
Command string
Aliases []string
Entry *CommandRegistryEntry
Default bool
}
// either kingpin.Application or kingpin.CmdClause fit this interface
type kingpinAppOrCommand interface {
Command(string, string) *kingpin.CmdClause
GetCommand(string) *kingpin.CmdClause
}
// func NewCommand(app kingpinAppOrCommand, name string, entry *CommandRegistryEntry) *kingpin.CmdClause {
// returnapp.Command(name, entry.Help)
// }
func (jc *JiraCli) Register(app *kingpin.Application, reg []CommandRegistry) {
for _, command := range reg {
copy := command
commandFields := strings.Fields(copy.Command)
var appOrCmd kingpinAppOrCommand = app
if len(commandFields) > 1 {
for _, name := range commandFields[0 : len(commandFields)-1] {
tmp := appOrCmd.GetCommand(name)
if tmp == nil {
tmp = appOrCmd.Command(name, "")
}
appOrCmd = tmp
}
}
cmd := appOrCmd.Command(commandFields[len(commandFields)-1], copy.Entry.Help)
for _, alias := range copy.Aliases {
cmd = cmd.Alias(alias)
}
if copy.Default {
cmd = cmd.Default()
}
if copy.Entry.UsageFunc != nil {
copy.Entry.UsageFunc(cmd)
}
cmd.Action(
func(_ *kingpin.ParseContext) error {
return copy.Entry.ExecuteFunc()
},
)
}
}
// // 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))
// if err != nil {
// return err
// }
// 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))
// if err != nil {
// return err
// }
// return runTemplate(c.getTemplate("issuetypes"), data, nil)
// }
// 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))
// issueTypeNames := make(map[string]bool)
// if data, ok := data.(map[string]interface{}); ok {
// if projects, ok := data["projects"].([]interface{}); ok {
// for _, project := range projects {
// if project, ok := project.(map[string]interface{}); ok {
// if issuetypes, ok := project["issuetypes"].([]interface{}); ok {
// if len(issuetypes) > 0 {
// for _, issuetype := range issuetypes {
// issueTypeNames[issuetype.(map[string]interface{})["name"].(string)] = true
// }
// }
// }
// }
// }
// }
// }
// if _, ok := issueTypeNames["Bug"]; ok {
// return "Bug"
// } else if _, ok := issueTypeNames["Task"]; ok {
// return "Task"
// }
// return ""
// }
// // 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))
// 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)
// if err != nil {
// return nil, err
// }
// transMeta := &jiradata.TransitionsMeta{}
// content, err := ioutil.ReadAll(resp.Body)
// if err != nil {
// return nil, err
// }
// err = json.Unmarshal(content, transMeta)
// if err != nil {
// return nil, err
// }
// 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))
// if err != nil {
// return err
// }
// return runTemplate(c.getTemplate("transitions"), data, nil)
// }
// // 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))
// if err != nil {
// return err
// }
// return runTemplate(c.getTemplate("issuelinktypes"), data, nil)
// }
// // CmdIssueLink is a generic function for adding a link type to an issue
// func (c *Cli) CmdIssueLink(inwardIssue string, issueLinkTypeName string, outwardIssue string) error {
// log.Debugf("issuelink called")
// json, err := jsonEncode(map[string]interface{}{
// "type": map[string]string{
// "name": issueLinkTypeName,
// },
// "inwardIssue": map[string]string{
// "key": inwardIssue,
// },
// "outwardIssue": map[string]string{
// "key": outwardIssue,
// },
// })
// if err != nil {
// return err
// }
// uri := fmt.Sprintf("%s/rest/api/2/issueLink", c.endpoint)
// if c.getOptBool("dryrun", false) {
// log.Debugf("POST: %s", json)
// log.Debugf("Dryrun mode, skipping POST")
// return nil
// }
// resp, err := c.post(uri, json)
// if err != nil {
// return err
// }
// if resp.StatusCode == 201 {
// c.Browse(inwardIssue)
// if !c.GetOptBool("quiet", false) {
// fmt.Printf("OK %s %s/browse/%s\n", inwardIssue, c.endpoint, inwardIssue)
// }
// } 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
// }
// 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")
// json, err := jsonEncode(map[string]interface{}{
// "type": map[string]string{
// "name": "Duplicate", // TODO This is probably not constant across Jira installs
// },
// "inwardIssue": map[string]string{
// "key": duplicate,
// },
// "outwardIssue": map[string]string{
// "key": issue,
// },
// })
// if err != nil {
// return err
// }
// uri := fmt.Sprintf("%s/rest/api/2/issueLink", c.endpoint)
// if c.getOptBool("dryrun", false) {
// log.Debugf("POST: %s", json)
// log.Debugf("Dryrun mode, skipping POST")
// return nil
// }
// resp, err := c.post(uri, json)
// if err != nil {
// return err
// }
// if resp.StatusCode == 201 {
// c.Browse(issue)
// if !c.GetOptBool("quiet", false) {
// fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
// }
// } 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
// }
// 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)
// var uri string
// json, err := jsonEncode(watcher)
// if err != nil {
// return err
// }
// if c.getOptBool("dryrun", false) {
// if !remove {
// log.Debugf("POST: %s", json)
// log.Debugf("Dryrun mode, skipping POST")
// } else {
// log.Debugf("DELETE: %s", watcher)
// log.Debugf("Dryrun mode, skipping POST")
// }
// return nil
// }
// var resp *http.Response
// if !remove {
// uri = fmt.Sprintf("%s/rest/api/2/issue/%s/watchers", c.endpoint, issue)
// resp, err = c.post(uri, json)
// } else {
// uri = fmt.Sprintf("%s/rest/api/2/issue/%s/watchers?username=%s", c.endpoint, issue, watcher)
// resp, err = c.delete(uri)
// }
// if err != nil {
// return err
// }
// if resp.StatusCode == 204 {
// c.Browse(issue)
// if !c.GetOptBool("quiet", false) {
// fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
// }
// } else {
// logBuffer := bytes.NewBuffer(make([]byte, 0))
// resp.Write(logBuffer)
// if !remove {
// err = fmt.Errorf("Unexpected Response From POST")
// } else {
// err = fmt.Errorf("Unexpected Response From DELETE")
// }
// log.Errorf("%s:\n%s", err, logBuffer)
// return err
// }
// 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)
// uri := fmt.Sprintf("%s/rest/api/2/issue/%s/votes", c.endpoint, issue)
// if c.getOptBool("dryrun", false) {
// if up {
// log.Debugf("POST: %s", "")
// log.Debugf("Dryrun mode, skipping POST")
// } else {
// log.Debugf("DELETE: %s", "")
// log.Debugf("Dryrun mode, skipping DELETE")
// }
// return nil
// }
// var resp *http.Response
// var err error
// if up {
// resp, err = c.post(uri, "")
// } else {
// resp, err = c.delete(uri)
// }
// if err != nil {
// return err
// }
// if resp.StatusCode == 204 {
// c.Browse(issue)
// if !c.GetOptBool("quiet", false) {
// fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
// }
// } else {
// logBuffer := bytes.NewBuffer(make([]byte, 0))
// resp.Write(logBuffer)
// if up {
// err = fmt.Errorf("Unexpected Response From POST")
// } else {
// err = fmt.Errorf("Unexpected Response From DELETE")
// }
// log.Errorf("%s:\n%s", err, logBuffer)
// return err
// }
// return nil
// }
// // CmdRankAfter rank issue after target issue
// func (c *Cli) CmdRankAfter(issue, after string) error {
// err := c.RankIssue(issue, after, RANKAFTER)
// if err != nil {
// return nil
// }
// if !c.GetOptBool("quiet", false) {
// fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
// }
// return nil
// }
// // CmdRankBefore rank issue before target issue
// func (c *Cli) CmdRankBefore(issue, before string) error {
// err := c.RankIssue(issue, before, RANKBEFORE)
// if err != nil {
// return nil
// }
// if !c.GetOptBool("quiet", false) {
// fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
// }
// 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))
// if err != nil {
// return err
// }
// transitions := data.(map[string]interface{})["transitions"].([]interface{})
// var transID, transName string
// var transMeta map[string]interface{}
// found := make([]string, 0, len(transitions))
// for _, transition := range transitions {
// name := transition.(map[string]interface{})["name"].(string)
// id := transition.(map[string]interface{})["id"].(string)
// found = append(found, name)
// if strings.Contains(strings.ToLower(name), strings.ToLower(trans)) {
// transName = name
// transID = id
// transMeta = transition.(map[string]interface{})
// if strings.ToLower(name) == strings.ToLower(trans) {
// break
// }
// }
// }
// if transID == "" {
// err := fmt.Errorf("Invalid Transition '%s', Available: %s", trans, strings.Join(found, ", "))
// log.Debugf("%s", err)
// return err
// }
// handlePost := func(json string) error {
// uri = fmt.Sprintf("%s/rest/api/2/issue/%s/transitions", c.endpoint, issue)
// if c.getOptBool("dryrun", false) {
// log.Debugf("POST: %s", json)
// log.Debugf("Dryrun mode, skipping POST")
// return nil
// }
// resp, err := c.post(uri, json)
// if err != nil {
// return err
// }
// if resp.StatusCode == 204 {
// c.Browse(issue)
// if !c.GetOptBool("quiet", false) {
// fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
// }
// } 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
// }
// return nil
// }
// uri = fmt.Sprintf("%s/rest/api/2/issue/%s", c.endpoint, issue)
// data, err = responseToJSON(c.get(uri))
// if err != nil {
// return err
// }
// issueData := data.(map[string]interface{})
// issueData["meta"] = transMeta
// if c.GetOptString("defaultResolution", "") == "" {
// // .meta.fields.resolution.allowedValues
// if fields, ok := transMeta["fields"].(map[string]interface{}); ok {
// if resolution, ok := fields["resolution"].(map[string]interface{}); ok {
// if allowedValues, ok := resolution["allowedValues"].([]interface{}); ok {
// for _, allowedValueRaw := range allowedValues {
// if allowedValues, ok := allowedValueRaw.(map[string]interface{}); ok {
// if allowedValues["name"] == "Fixed" {
// c.opts["defaultResolution"] = "Fixed"
// } else if allowedValues["name"] == "Done" {
// c.opts["defaultResolution"] = "Done"
// }
// }
// }
// }
// }
// }
// }
// issueData["overrides"] = c.opts
// issueData["transition"] = map[string]interface{}{
// "name": transName,
// "id": transID,
// }
// return c.editTemplate(
// c.getTemplate("transition"),
// fmt.Sprintf("%s-trans-%s-", issue, trans),
// issueData,
// handlePost,
// )
// }
// // 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")
// handlePost := func(json string) error {
// uri := fmt.Sprintf("%s/rest/api/2/issue/%s/comment", c.endpoint, issue)
// if c.getOptBool("dryrun", false) {
// log.Debugf("POST: %s", json)
// log.Debugf("Dryrun mode, skipping POST")
// return nil
// }
// resp, err := c.post(uri, json)
// if err != nil {
// return err
// }
// if resp.StatusCode == 201 {
// c.Browse(issue)
// if !c.GetOptBool("quiet", false) {
// fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
// }
// return nil
// }
// 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 != "" {
// json, err := jsonEncode(map[string]interface{}{
// "body": comment,
// })
// if err != nil {
// return err
// }
// return handlePost(json)
// }
// 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 fmt.Errorf("CmdComponent: %q is not a valid action", action)
// }
// json, err := jsonEncode(map[string]interface{}{
// "name": name,
// "description": desc,
// "leadUserName": lead,
// "project": project,
// })
// if err != nil {
// return err
// }
// uri := fmt.Sprintf("%s/rest/api/2/component", c.endpoint)
// if c.getOptBool("dryrun", false) {
// log.Debugf("POST: %s", json)
// log.Debugf("Dryrun mode, skipping POST")
// return nil
// }
// resp, err := c.post(uri, json)
// if err != nil {
// return err
// }
// if resp.StatusCode == 201 {
// if !c.GetOptBool("quiet", false) {
// fmt.Printf("OK %s %s\n", project, name)
// }
// } 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
// }
// 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")
// if action != "add" && action != "remove" && action != "set" {
// return fmt.Errorf("action must be 'add', 'set' or 'remove': %q is invalid", action)
// }
// handlePut := func(json string) error {
// uri := fmt.Sprintf("%s/rest/api/2/issue/%s", c.endpoint, issue)
// if c.getOptBool("dryrun", false) {
// log.Debugf("PUT: %s", json)
// log.Debugf("Dryrun mode, skipping POST")
// return nil
// }
// resp, err := c.put(uri, json)
// if err != nil {
// return err
// }
// if resp.StatusCode == 204 {
// c.Browse(issue)
// if !c.GetOptBool("quiet", false) {
// fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
// }
// return nil
// }
// 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 labelsJSON string
// var err error
// if action == "set" {
// labelsActions := make([]map[string][]string, 1)
// labelsActions[0] = map[string][]string{
// "set": labels,
// }
// labelsJSON, err = jsonEncode(map[string]interface{}{
// "labels": labelsActions,
// })
// } else {
// labelsActions := make([]map[string]string, len(labels))
// for i, label := range labels {
// labelActionMap := map[string]string{
// action: label,
// }
// labelsActions[i] = labelActionMap
// }
// labelsJSON, err = jsonEncode(map[string]interface{}{
// "labels": labelsActions,
// })
// }
// if err != nil {
// return err
// }
// 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")
// var userVal interface{} = user
// // https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-assign
// // If the name is "-1" automatic assignee is used. A null name will remove the assignee.
// if user == "" {
// userVal = nil
// }
// if c.GetOptBool("default", false) {
// userVal = "-1"
// }
// json, err := jsonEncode(map[string]interface{}{
// "name": userVal,
// })
// if err != nil {
// return err
// }
// uri := fmt.Sprintf("%s/rest/api/2/issue/%s/assignee", c.endpoint, issue)
// if c.getOptBool("dryrun", false) {
// log.Debugf("PUT: %s", json)
// log.Debugf("Dryrun mode, skipping PUT")
// return nil
// }
// resp, err := c.put(uri, json)
// if err != nil {
// return err
// }
// if resp.StatusCode == 204 {
// c.Browse(issue)
// if !c.GetOptBool("quiet", false) {
// fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
// }
// } 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
// }
// return nil
// }
// func (c *Cli) CmdUnassign(issue string) error {
// return c.CmdAssign(issue, "")
// }
// // 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 allTemplates {
// if wanted, ok := c.opts["template"]; ok && wanted != name {
// continue
// }
// templateFile := fmt.Sprintf("%s/%s", dir, name)
// if _, err := os.Stat(templateFile); err == nil {
// log.Warning("Skipping %s, already exists", templateFile)
// continue
// }
// 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
// }
// 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")
// if !strings.HasPrefix(uri, "http") {
// uri = fmt.Sprintf("%s%s", c.endpoint, uri)
// }
// method := strings.ToUpper(c.opts["method"].(string))
// var data interface{}
// if method == "GET" {
// data, err = responseToJSON(c.get(uri))
// } else if method == "POST" {
// data, err = responseToJSON(c.post(uri, content))
// } else if method == "PUT" {
// data, err = responseToJSON(c.put(uri, content))
// }
// if err != nil {
// return err
// }
// return runTemplate(c.getTemplate("request"), data, nil)
// }
+125
View File
@@ -0,0 +1,125 @@
package jiracli
import (
"fmt"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type CreateOptions struct {
GlobalOptions
jiradata.IssueUpdate
Project string
IssueType string
Overrides map[string]string
}
func (jc *JiraCli) CmdCreateRegistry() *CommandRegistryEntry {
opts := CreateOptions{
GlobalOptions: GlobalOptions{
Template: "create",
},
Overrides: map[string]string{},
}
return &CommandRegistryEntry{
"Create issue",
func() error {
return jc.CmdCreate(&opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdCreateUsage(cmd, &opts)
},
}
}
func (jc *JiraCli) CmdCreateUsage(cmd *kingpin.CmdClause, opts *CreateOptions) error {
if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil {
return err
}
jc.EditorUsage(cmd, &opts.GlobalOptions)
jc.TemplateUsage(cmd, &opts.GlobalOptions)
cmd.Flag("noedit", "Disable opening the editor").BoolVar(&opts.SkipEditing)
cmd.Flag("project", "project to create issue in").Short('p').StringVar(&opts.Project)
cmd.Flag("issuetype", "issuetype in to create").Short('i').StringVar(&opts.IssueType)
cmd.Flag("comment", "Comment message for issue").Short('m').PreAction(func(ctx *kingpin.ParseContext) error {
opts.Overrides["comment"] = flagValue(ctx, "comment")
return nil
}).String()
cmd.Flag("override", "Set issue property").Short('o').StringMapVar(&opts.Overrides)
return 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 (jc *JiraCli) CmdCreate(opts *CreateOptions) error {
type templateInput struct {
Meta *jiradata.CreateMetaIssueType `yaml:"meta" json:"meta"`
Overrides map[string]string `yaml:"overrides" json:"overrides"`
}
if err := jc.defaultIssueType(&opts.Project, &opts.IssueType); err != nil {
return err
}
createMeta, err := jc.GetIssueCreateMetaIssueType(opts.Project, opts.IssueType)
if err != nil {
return err
}
issueUpdate := jiradata.IssueUpdate{}
input := templateInput{
Meta: createMeta,
Overrides: opts.Overrides,
}
input.Overrides["project"] = opts.Project
input.Overrides["issuetype"] = opts.IssueType
input.Overrides["user"] = opts.User
var issueResp *jiradata.IssueCreateResponse
err = jc.editLoop(&opts.GlobalOptions, &input, &issueUpdate, func() error {
issueResp, err = jc.CreateIssue(&issueUpdate)
return err
})
if err != nil {
return err
}
link := fmt.Sprintf("%s/browse/%s", jc.Endpoint, issueResp.Key)
fmt.Printf("OK %s %s\n", issueResp.Key, link)
// FIXME implement browse
return nil
}
func (jc *JiraCli) defaultIssueType(project, issuetype *string) error {
if project == nil || *project == "" {
return fmt.Errorf("Project undefined, please use --project argument or set the `project` config property")
}
if issuetype != nil && *issuetype != "" {
return nil
}
projectMeta, err := jc.GetIssueCreateMetaProject(*project)
if err != nil {
return err
}
issueTypes := map[string]bool{}
for _, issuetype := range projectMeta.Issuetypes {
issueTypes[issuetype.Name] = true
}
// prefer "Bug" type
if _, ok := issueTypes["Bug"]; ok {
*issuetype = "Bug"
return nil
}
// next best default it "Task"
if _, ok := issueTypes["Task"]; ok {
*issuetype = "Task"
return nil
}
return fmt.Errorf("Unable to find default issueType of Bug or Task, please set --issuetype argument or set the `issuetype` config property")
}
+49
View File
@@ -0,0 +1,49 @@
package jiracli
import kingpin "gopkg.in/alecthomas/kingpin.v2"
type CreateMetaOptions struct {
GlobalOptions
Project string `yaml:"project,omitempty" json:"project,omitempty"`
IssueType string `yaml:"issuetype,omitempty" json:"issuetype,omitempty"`
}
func (jc *JiraCli) CmdCreateMetaRegistry() *CommandRegistryEntry {
opts := CreateMetaOptions{
GlobalOptions: GlobalOptions{
Template: "createmeta",
},
}
return &CommandRegistryEntry{
"View 'create' metadata",
func() error {
return jc.CmdCreateMeta(&opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdCreateMetaUsage(cmd, &opts)
},
}
}
func (jc *JiraCli) CmdCreateMetaUsage(cmd *kingpin.CmdClause, opts *CreateMetaOptions) error {
if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil {
return err
}
jc.TemplateUsage(cmd, &opts.GlobalOptions)
cmd.Flag("project", "project to fetch create metadata").Short('p').StringVar(&opts.Project)
cmd.Flag("issuetype", "issuetype in project to fetch create metadata").Short('i').StringVar(&opts.IssueType)
return nil
}
// Create will get issue create metadata and send to "createmeta" template
func (jc *JiraCli) CmdCreateMeta(opts *CreateMetaOptions) error {
if err := jc.defaultIssueType(&opts.Project, &opts.IssueType); err != nil {
return err
}
createMeta, err := jc.GetIssueCreateMetaIssueType(opts.Project, opts.IssueType)
if err != nil {
return err
}
return jc.runTemplate(opts.Template, createMeta, nil)
}
+71
View File
@@ -0,0 +1,71 @@
package jiracli
import (
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type DupOptions struct {
GlobalOptions
jiradata.LinkIssueRequest
Duplicate string
Issue string
}
func (jc *JiraCli) CmdDupRegistry() *CommandRegistryEntry {
opts := DupOptions{
GlobalOptions: GlobalOptions{
Template: "edit",
},
}
return &CommandRegistryEntry{
"Mark issues as duplicate",
func() error {
return jc.CmdDup(&opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdDupUsage(cmd, &opts)
},
}
}
func (jc *JiraCli) CmdDupUsage(cmd *kingpin.CmdClause, opts *DupOptions) error {
if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil {
return err
}
jc.EditorUsage(cmd, &opts.GlobalOptions)
jc.TemplateUsage(cmd, &opts.GlobalOptions)
cmd.Flag("comment", "Comment message when marking issue as duplicate").Short('m').PreAction(func(ctx *kingpin.ParseContext) error {
opts.Comment = &jiradata.Comment{
Body: flagValue(ctx, "comment"),
}
return nil
}).String()
cmd.Arg("DUPLICATE", "duplicate issue to mark closed").Required().StringVar(&opts.Duplicate)
cmd.Arg("ISSUE", "duplicate issue to leave open").Required().StringVar(&opts.Issue)
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 (jc *JiraCli) CmdDup(opts *DupOptions) error {
opts.Type = &jiradata.IssueLinkType{
// FIXME is this consitent across multiple jira installs?
Name: "Duplicate",
}
opts.InwardIssue = &jiradata.IssueRef{
Key: opts.Duplicate,
}
opts.OutwardIssue = &jiradata.IssueRef{
Key: opts.Issue,
}
return jc.LinkIssues(&opts.LinkIssueRequest)
// FIXME need to close/done/start&stop dup issue
// FIXME implement browse
return nil
}
+117
View File
@@ -0,0 +1,117 @@
package jiracli
import (
"fmt"
jira "gopkg.in/Netflix-Skunkworks/go-jira.v1"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type EditOptions struct {
GlobalOptions
jiradata.IssueUpdate
jira.SearchOptions
Overrides map[string]string
}
func (jc *JiraCli) CmdEditRegistry() *CommandRegistryEntry {
issue := ""
opts := EditOptions{
GlobalOptions: GlobalOptions{
Template: "edit",
},
Overrides: map[string]string{},
}
return &CommandRegistryEntry{
"Edit issue details",
func() error {
return jc.CmdEdit(issue, &opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdEditUsage(cmd, &issue, &opts)
},
}
}
func (jc *JiraCli) CmdEditUsage(cmd *kingpin.CmdClause, issue *string, opts *EditOptions) error {
if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil {
return err
}
jc.EditorUsage(cmd, &opts.GlobalOptions)
jc.TemplateUsage(cmd, &opts.GlobalOptions)
cmd.Flag("noedit", "Disable opening the editor").BoolVar(&opts.SkipEditing)
// cmd.Flag("assignee", "User assigned the issue").Short('a').StringVar(&opts.Assignee)
// cmd.Flag("component", "Component to search for").Short('c').StringVar(&opts.Component)
// 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').Default("500").IntVar(&opts.MaxResults)
// cmd.Flag("project", "Project to search for").Short('p').StringVar(&opts.Project)
cmd.Flag("query", "Jira Query Language (JQL) expression for the search to edit multiple issues").Short('q').StringVar(&opts.Query)
// cmd.Flag("reporter", "Reporter to search for").Short('r').StringVar(&opts.Reporter)
// cmd.Flag("sort", "Sort order to return").Short('s').Default("priority asc, key").StringVar(&opts.Sort)
// cmd.Flag("watcher", "Watcher to search for").Short('w').StringVar(&opts.Watcher)
cmd.Flag("comment", "Comment message for issue").Short('m').PreAction(func(ctx *kingpin.ParseContext) error {
opts.Overrides["comment"] = flagValue(ctx, "comment")
return nil
}).String()
cmd.Flag("override", "Set issue property").Short('o').StringMapVar(&opts.Overrides)
cmd.Arg("ISSUE", "issue id to edit").StringVar(issue)
return nil
}
// Edit will get issue data and send to "edit" template
func (jc *JiraCli) CmdEdit(issue string, opts *EditOptions) error {
type templateInput struct {
*jiradata.Issue `yaml:",inline"`
Meta *jiradata.EditMeta `yaml:"meta" json:"meta"`
Overrides map[string]string `yaml:"overrides" json:"overrides"`
}
if issue != "" {
issueData, err := jc.GetIssue(issue, nil)
if err != nil {
return err
}
editMeta, err := jc.GetIssueEditMeta(issue)
if err != nil {
return err
}
issueUpdate := jiradata.IssueUpdate{}
input := templateInput{
Issue: issueData,
Meta: editMeta,
Overrides: opts.Overrides,
}
return jc.editLoop(&opts.GlobalOptions, &input, &issueUpdate, func() error {
return jc.EditIssue(issue, &issueUpdate)
})
// FIXME implement browse
}
results, err := jc.Search(opts)
if err != nil {
return err
}
for _, issueData := range results.Issues {
editMeta, err := jc.GetIssueEditMeta(issueData.Key)
if err != nil {
return err
}
issueUpdate := jiradata.IssueUpdate{}
input := templateInput{
Issue: issueData,
Meta: editMeta,
}
err = jc.editLoop(&opts.GlobalOptions, &input, &issueUpdate, func() error {
return jc.EditIssue(issueData.Key, &issueUpdate)
})
if err != nil {
return err
}
link := fmt.Sprintf("%s/browse/%s", jc.Endpoint, issueData.Key)
fmt.Printf("OK %s %s\n", issueData.Key, link)
// FIXME implement browse
}
return nil
}
+38
View File
@@ -0,0 +1,38 @@
package jiracli
import kingpin "gopkg.in/alecthomas/kingpin.v2"
func (jc *JiraCli) CmdEditMetaRegistry() *CommandRegistryEntry {
issue := ""
opts := GlobalOptions{
Template: "editmeta",
}
return &CommandRegistryEntry{
"View 'edit' metadata",
func() error {
return jc.CmdEditMeta(issue, &opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdEditMetaUsage(cmd, &issue, &opts)
},
}
}
func (jc *JiraCli) CmdEditMetaUsage(cmd *kingpin.CmdClause, issue *string, opts *GlobalOptions) error {
if err := jc.GlobalUsage(cmd, opts); err != nil {
return err
}
jc.TemplateUsage(cmd, opts)
cmd.Arg("ISSUE", "edit metadata for issue id").Required().StringVar(issue)
return nil
}
// EditMeta will get issue edit metadata and send to "editmeta" template
func (jc *JiraCli) CmdEditMeta(issue string, opts *GlobalOptions) error {
editMeta, err := jc.GetIssueEditMeta(issue)
if err != nil {
return err
}
return jc.runTemplate(opts.Template, editMeta, nil)
}
+29
View File
@@ -0,0 +1,29 @@
package jiracli
import kingpin "gopkg.in/alecthomas/kingpin.v2"
func (jc *JiraCli) CmdFieldsRegistry() *CommandRegistryEntry {
opts := GlobalOptions{
Template: "fields",
}
return &CommandRegistryEntry{
"Prints all fields, both System and Custom",
func() error {
return jc.CmdFields(&opts)
},
func(cmd *kingpin.CmdClause) error {
err := jc.GlobalUsage(cmd, &opts)
jc.TemplateUsage(cmd, &opts)
return err
},
}
}
// Fields will send data from /rest/api/2/field API to "fields" template
func (jc *JiraCli) CmdFields(opts *GlobalOptions) error {
data, err := jc.GetFields()
if err != nil {
return err
}
return jc.runTemplate(opts.Template, data, nil)
}
+1 -1
View File
@@ -1,6 +1,6 @@
// +build !windows
package jira
package jiracli
import "github.com/tmc/keyring"
@@ -1,4 +1,4 @@
package jira
package jiracli
import "fmt"
+59
View File
@@ -0,0 +1,59 @@
package jiracli
import (
jira "gopkg.in/Netflix-Skunkworks/go-jira.v1"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type ListOptions struct {
GlobalOptions `yaml:",inline" figtree:",inline"`
jira.SearchOptions `yaml:",inline" figtree:",inline"`
}
func (jc *JiraCli) CmdListRegistry() *CommandRegistryEntry {
opts := ListOptions{
GlobalOptions: GlobalOptions{
Template: "list",
},
}
return &CommandRegistryEntry{
"Prints list of issues for given search criteria",
func() error {
return jc.CmdList(&opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdListUsage(cmd, &opts)
},
}
}
func (jc *JiraCli) CmdListUsage(cmd *kingpin.CmdClause, opts *ListOptions) error {
jc.LoadConfigs(cmd, opts)
if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil {
return err
}
jc.TemplateUsage(cmd, &opts.GlobalOptions)
cmd.Flag("assignee", "User assigned the issue").Short('a').StringVar(&opts.Assignee)
cmd.Flag("component", "Component to search for").Short('c').StringVar(&opts.Component)
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').Default("500").IntVar(&opts.MaxResults)
cmd.Flag("project", "Project to search for").Short('p').StringVar(&opts.Project)
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').Default(
"assignee,created,priority,reporter,status,summary,updated",
).StringVar(&opts.QueryFields)
cmd.Flag("reporter", "Reporter to search for").Short('r').StringVar(&opts.Reporter)
cmd.Flag("sort", "Sort order to return").Short('s').Default("priority asc, key").StringVar(&opts.Sort)
cmd.Flag("watcher", "Watcher to search for").Short('w').StringVar(&opts.Watcher)
return nil
}
// List will query jira and send data to "list" template
func (jc *JiraCli) CmdList(opts *ListOptions) error {
data, err := jc.Search(opts)
if err != nil {
return err
}
return jc.runTemplate(opts.Template, data, nil)
}
+106
View File
@@ -0,0 +1,106 @@
package jiracli
import (
"fmt"
"net/http"
"github.com/mgutz/ansi"
jira "gopkg.in/Netflix-Skunkworks/go-jira.v1"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
func (jc *JiraCli) CmdLoginRegistry() *CommandRegistryEntry {
opts := GlobalOptions{}
return &CommandRegistryEntry{
"Attempt to login into jira server",
func() error {
return jc.CmdLogin(&opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.GlobalUsage(cmd, &opts)
},
}
}
func authCallback(req *http.Request, resp *http.Response) (*http.Response, error) {
if resp.StatusCode == 403 {
defer resp.Body.Close()
// X-Authentication-Denied-Reason: CAPTCHA_CHALLENGE; login-url=https://jira/login.jsp
if reason := resp.Header.Get("X-Authentication-Denied-Reason"); reason != "" {
return resp, fmt.Errorf("Authenticaion Failed: " + reason)
}
return resp, fmt.Errorf("Authenticaion Failed: Unkown Reason")
} else if resp.StatusCode == 200 {
if reason := resp.Header.Get("X-Seraph-Loginreason"); reason == "AUTHENTICATION_DENIED" {
defer resp.Body.Close()
return resp, fmt.Errorf("Authentication Failed: " + reason)
}
}
return resp, nil
}
// CmdLogin will attempt to login into jira server
func (jc *JiraCli) CmdLogin(opts *GlobalOptions) error {
defer func(h jira.HttpClient) {
log.Debugf("Client: %#v", h)
jc.UA = h
}(jc.UA)
if session, err := jc.GetSession(); err != nil {
jc.UA = jc.oreoAgent.WithoutRedirect().WithRetries(0).WithPostCallback(authCallback)
// No active session so try to create a new one
_, err := jc.NewSession(opts)
if err != nil {
// reset password on failed session
opts.SetPass("")
return err
}
fmt.Println(ansi.Color("OK", "green"), "New session for", opts.User)
} else {
fmt.Println(ansi.Color("OK", "green"), "Found session for", session.Name)
}
return nil
}
// uri := fmt.Sprintf("%s/rest/auth/1/session", c.endpoint)
// for {
// req, _ := http.NewRequest("GET", uri, nil)
// user, _ := c.opts["user"].(string)
// passwd := c.GetPass(user)
// req.SetBasicAuth(user, passwd)
// resp, err := c.makeRequest(req)
// if err != nil {
// return err
// }
// 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
// }
// if _, ok := c.opts["password-source"]; ok {
// return c.SetPass(user, passwd)
// }
// break
// } else {
// log.Warning("Login failed")
// continue
// }
// }
// return nil
// }
+33
View File
@@ -0,0 +1,33 @@
package jiracli
import (
"fmt"
"github.com/mgutz/ansi"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
func (jc *JiraCli) CmdLogoutRegistry() *CommandRegistryEntry {
opts := GlobalOptions{}
return &CommandRegistryEntry{
"Deactivate sesssion with Jira server",
func() error {
return jc.CmdLogout(&opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.GlobalUsage(cmd, &opts)
},
}
}
// CmdLogout will attempt to terminate an active Jira session
func (jc *JiraCli) CmdLogout(opts *GlobalOptions) error {
jc.UA = jc.oreoAgent.WithoutRedirect().WithRetries(0)
err := jc.DeleteSession()
if err == nil {
fmt.Println(ansi.Color("OK", "green"), "Terminated session for", opts.User)
} else {
fmt.Printf("%s Failed to terminate session for %s: %s", ansi.Color("ERROR", "red"), opts.User, err)
}
return nil
}
+91
View File
@@ -0,0 +1,91 @@
package jiracli
import (
"bytes"
"fmt"
"os/exec"
"strings"
"github.com/AlecAivazis/survey"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
)
func (o *GlobalOptions) ProvideAuthParams() *jiradata.AuthParams {
return &jiradata.AuthParams{
Username: o.User,
Password: o.GetPass(),
}
}
func (o *GlobalOptions) GetPass() string {
passwd := ""
if o.PasswordSource != "" {
if o.PasswordSource == "keyring" {
var err error
passwd, err = keyringGet(o.User)
if err != nil {
panic(err)
}
} else if o.PasswordSource == "pass" {
if bin, err := exec.LookPath("pass"); err == nil {
buf := bytes.NewBufferString("")
cmd := exec.Command(bin, fmt.Sprintf("GoJira/%s", o.User))
cmd.Stdout = buf
cmd.Stderr = buf
if err := cmd.Run(); err == nil {
passwd = strings.TrimSpace(buf.String())
}
}
} else {
log.Warningf("Unknown password-source: %s", o.PasswordSource)
}
}
if passwd != "" {
return passwd
}
survey.AskOne(
&survey.Password{
Message: fmt.Sprintf("Jira Password [%s]: ", o.User),
},
&passwd,
nil,
)
o.SetPass(passwd)
return passwd
}
func (o *GlobalOptions) SetPass(passwd string) error {
if o.PasswordSource == "keyring" {
// save password in keychain so that it can be used for subsequent http requests
err := keyringSet(o.User, passwd)
if err != nil {
log.Errorf("Failed to set password in keyring: %s", err)
return err
}
} else if o.PasswordSource == "pass" {
if bin, err := exec.LookPath("pass"); err == nil {
log.Debugf("using %s", bin)
passName := fmt.Sprintf("GoJira/%s", o.User)
if passwd != "" {
in := bytes.NewBufferString(fmt.Sprintf("%s\n%s\n", passwd, passwd))
out := bytes.NewBufferString("")
cmd := exec.Command(bin, "insert", "--force", passName)
cmd.Stdin = in
cmd.Stdout = out
cmd.Stderr = out
if err := cmd.Run(); err != nil {
return fmt.Errorf("Failed to insert password: %s", out.String())
}
} else {
// clear the `pass` entry on empty password
if err := exec.Command(bin, "rm", "--force", passName).Run(); err != nil {
return fmt.Errorf("Failed to clear password for %s", passName)
}
}
}
} else if o.PasswordSource != "" {
return fmt.Errorf("Unknown password-source: %s", o.PasswordSource)
}
return nil
}
+109
View File
@@ -0,0 +1,109 @@
package jiracli
import (
"fmt"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type SubtaskOptions struct {
GlobalOptions
jiradata.IssueUpdate
Project string
IssueType string
Overrides map[string]string
Issue string
}
func (jc *JiraCli) CmdSubtaskRegistry() *CommandRegistryEntry {
opts := SubtaskOptions{
GlobalOptions: GlobalOptions{
Template: "subtask",
},
IssueType: "Sub-task",
Overrides: map[string]string{},
}
return &CommandRegistryEntry{
"Subtask issue",
func() error {
return jc.CmdSubtask(&opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdSubtaskUsage(cmd, &opts)
},
}
}
func (jc *JiraCli) CmdSubtaskUsage(cmd *kingpin.CmdClause, opts *SubtaskOptions) error {
if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil {
return err
}
jc.EditorUsage(cmd, &opts.GlobalOptions)
jc.TemplateUsage(cmd, &opts.GlobalOptions)
cmd.Flag("noedit", "Disable opening the editor").BoolVar(&opts.SkipEditing)
cmd.Flag("project", "project to subtask issue in").Short('p').StringVar(&opts.Project)
cmd.Flag("comment", "Comment message for issue").Short('m').PreAction(func(ctx *kingpin.ParseContext) error {
opts.Overrides["comment"] = flagValue(ctx, "comment")
return nil
}).String()
cmd.Flag("override", "Set issue property").Short('o').StringMapVar(&opts.Overrides)
cmd.Arg("ISSUE", "Parent issue for subtask").StringVar(&opts.Issue)
return nil
}
// CmdSubtask sends the subtask-metadata to the "subtask" template for editing, then
// will parse the edited document as YAML and submit the document to jira.
func (jc *JiraCli) CmdSubtask(opts *SubtaskOptions) error {
type templateInput struct {
Meta *jiradata.CreateMetaIssueType `yaml:"meta" json:"meta"`
Overrides map[string]string `yaml:"overrides" json:"overrides"`
Parent *jiradata.Issue `yaml:"parent" json:"parent"`
}
parent, err := jc.GetIssue(opts.Issue, nil)
if err != nil {
return err
}
if project, ok := parent.Fields["project"].(map[string]interface{}); ok {
if key, ok := project["key"].(string); ok {
opts.Project = key
} else {
return fmt.Errorf("Failed to find Project Key in parent issue")
}
} else {
return fmt.Errorf("Failed to find Project field in parent issue")
}
createMeta, err := jc.GetIssueCreateMetaIssueType(opts.Project, opts.IssueType)
if err != nil {
return err
}
issueUpdate := jiradata.IssueUpdate{}
input := templateInput{
Meta: createMeta,
Overrides: opts.Overrides,
Parent: parent,
}
input.Overrides["project"] = opts.Project
input.Overrides["issuetype"] = opts.IssueType
input.Overrides["user"] = opts.User
var issueResp *jiradata.IssueCreateResponse
err = jc.editLoop(&opts.GlobalOptions, &input, &issueUpdate, func() error {
issueResp, err = jc.CreateIssue(&issueUpdate)
return err
})
if err != nil {
return err
}
link := fmt.Sprintf("%s/browse/%s", jc.Endpoint, issueResp.Key)
fmt.Printf("OK %s %s\n", issueResp.Key, link)
// FIXME implement browse
return nil
}
+190 -6
View File
@@ -1,4 +1,181 @@
package jira
package jiracli
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"strings"
"text/template"
yaml "gopkg.in/coryb/yaml.v2"
"github.com/mgutz/ansi"
)
func findTemplate(name string) ([]byte, error) {
if file, err := findClosestParentPath(filepath.Join(".jira.d", "templates", name)); err == nil {
b, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}
return b, nil
}
return nil, nil
}
func (jc *JiraCli) getTemplate(name string) (string, error) {
if _, err := os.Stat(name); err == nil {
b, err := ioutil.ReadFile(name)
if err != nil {
return "", err
}
return string(b), nil
}
b, err := findTemplate(name)
if err != nil {
return "", err
} else if b != nil {
return string(b), nil
}
if s, ok := allTemplates[name]; ok {
return s, nil
}
return "", fmt.Errorf("No Template found for %q", name)
}
func (jc *JiraCli) tmpTemplate(templateName string, data interface{}) (string, error) {
tmpFile, err := jc.tmpYml(templateName)
if err != nil {
return "", err
}
defer tmpFile.Close()
return tmpFile.Name(), jc.runTemplate(templateName, data, tmpFile)
}
func (jc *JiraCli) runTemplate(templateName string, data interface{}, out io.Writer) error {
templateContent, err := jc.getTemplate(templateName)
if err != nil {
return err
}
if out == nil {
out = os.Stdout
}
funcs := map[string]interface{}{
"toJson": func(content interface{}) (string, error) {
bytes, err := json.MarshalIndent(content, "", " ")
if err != nil {
return "", err
}
return string(bytes), nil
},
"append": func(more string, content interface{}) (string, error) {
switch value := content.(type) {
case string:
return string(append([]byte(content.(string)), []byte(more)...)), nil
case []byte:
return string(append(content.([]byte), []byte(more)...)), nil
default:
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++ {
indent[i] = ' '
}
lineSeps := []rune{'\n', '\u0085', '\u2028', '\u2029'}
for _, sep := range lineSeps {
indent[0] = sep
content = strings.Replace(content, string(sep), string(indent), -1)
}
return content
},
"comment": func(content string) string {
lineSeps := []rune{'\n', '\u0085', '\u2028', '\u2029'}
for _, sep := range lineSeps {
content = strings.Replace(content, string(sep), string([]rune{sep, '#', ' '}), -1)
}
return content
},
"color": func(color string) string {
return ansi.ColorCode(color)
},
"split": func(sep string, content string) []string {
return strings.Split(content, sep)
},
"join": func(sep string, content []interface{}) string {
vals := make([]string, len(content))
for i, v := range content {
vals[i] = v.(string)
}
return strings.Join(vals, sep)
},
"abbrev": func(max int, content string) string {
if len(content) > max {
var buffer bytes.Buffer
buffer.WriteString(content[:max-3])
buffer.WriteString("...")
return buffer.String()
}
return content
},
"rep": func(count int, content string) string {
var buffer bytes.Buffer
for i := 0; i < count; i++ {
buffer.WriteString(content)
}
return buffer.String()
},
"age": func(content string) (string, error) {
return fuzzyAge(content)
},
"dateFormat": func(format string, content string) (string, error) {
return dateFormat(format, content)
},
}
// HACK HACK HACK: convert data formats to json for backwards compatibilty with templates
var rawData interface{}
if jsonData, err := json.Marshal(data); 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
}
}
// rawData, err = yamlFixup(rawData)
// if err != nil {
// return err
// }
tmpl, err := template.New("template").Funcs(funcs).Parse(templateContent)
if err != nil {
return err
}
if err := tmpl.Execute(out, rawData); err != nil {
return err
}
return nil
}
var allTemplates = map[string]string{
"debug": defaultDebugTemplate,
@@ -90,19 +267,24 @@ update:
{{ or .overrides.comment "" | indent 10 }}
fields:
summary: {{ or .overrides.summary .fields.summary }}
{{- if and .meta.fields.components .meta.fields.components.allowedValues }}
components: # Values: {{ range .meta.fields.components.allowedValues }}{{.name}}, {{end}}{{if .overrides.components }}{{ range (split "," .overrides.components)}}
- name: {{.}}{{end}}{{else}}{{ range .fields.components }}
- name: {{ .name }}{{end}}{{end}}
- name: {{ .name }}{{end}}{{end}}{{end}}
{{- if .meta.fields.assignee}}
assignee:
name: {{ if .overrides.assignee }}{{.overrides.assignee}}{{else}}{{if .fields.assignee }}{{ .fields.assignee.name }}{{end}}{{end}}
name: {{ if .overrides.assignee }}{{.overrides.assignee}}{{else}}{{if .fields.assignee }}{{ .fields.assignee.name }}{{end}}{{end}}{{end}}
{{- if .meta.fields.reporter}}
reporter:
name: {{ if .overrides.reporter }}{{ .overrides.reporter }}{{else if .fields.reporter}}{{ .fields.reporter.name }}{{end}}
name: {{ if .overrides.reporter }}{{ .overrides.reporter }}{{else if .fields.reporter}}{{ .fields.reporter.name }}{{end}}{{end}}
{{- if .meta.fields.customfield_10110}}
# watchers
customfield_10110: {{ range .fields.customfield_10110 }}
- name: {{ .name }}{{end}}{{if .overrides.watcher}}
- name: {{ .overrides.watcher}}{{end}}
- name: {{ .overrides.watcher}}{{end}}{{end}}
{{- if .meta.fields.priority }}
priority: # Values: {{ range .meta.fields.priority.allowedValues }}{{.name}}, {{end}}
name: {{ or .overrides.priority .fields.priority.name }}
name: {{ or .overrides.priority .fields.priority.name }}{{end}}
description: |~
{{ or .overrides.description (or .fields.description "") | indent 4 }}
# comments:
@@ -170,11 +352,13 @@ const defaultCommentTemplate = `body: |~
`
const defaultTransitionTemplate = `{{/* transition template */ -}}
{{- if .meta.fields.comment }}
update:
comment:
- add:
body: |~
{{ or .overrides.comment "" | indent 10 }}
{{- end -}}
fields:
{{- if .meta.fields.assignee}}
assignee:
+130
View File
@@ -0,0 +1,130 @@
package jiracli
import (
"fmt"
"strings"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type TransitionOptions struct {
GlobalOptions
Overrides map[string]string
Transition string
Issue string
Resolution string
}
func (jc *JiraCli) CmdTransitionRegistry(transition string) *CommandRegistryEntry {
opts := TransitionOptions{
GlobalOptions: GlobalOptions{
Template: "transition",
},
Transition: transition,
Overrides: map[string]string{},
}
help := "Transition issue to given state"
if transition == "" {
help = fmt.Sprintf("Transition issue to %s state", transition)
}
return &CommandRegistryEntry{
help,
func() error {
return jc.CmdTransition(&opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdTransitionUsage(cmd, &opts)
},
}
}
func (jc *JiraCli) CmdTransitionUsage(cmd *kingpin.CmdClause, opts *TransitionOptions) error {
if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil {
return err
}
jc.TemplateUsage(cmd, &opts.GlobalOptions)
cmd.Flag("comment", "Comment message for issue").Short('m').PreAction(func(ctx *kingpin.ParseContext) error {
opts.Overrides["comment"] = flagValue(ctx, "comment")
return nil
}).String()
cmd.Flag("override", "Set issue property").Short('o').StringMapVar(&opts.Overrides)
if opts.Transition == "" {
cmd.Arg("TRANSITION", "State to transition issue to").Required().StringVar(&opts.Transition)
}
cmd.Arg("ISSUE", "issue to transition").Required().StringVar(&opts.Issue)
return nil
}
// CmdTransition will move state of the given issue to the given transtion
func (jc *JiraCli) CmdTransition(opts *TransitionOptions) error {
issueData, err := jc.GetIssue(opts.Issue, nil)
if err != nil {
return err
}
meta, err := jc.GetIssueTransitions(opts.Issue)
if err != nil {
return err
}
transMeta := meta.Transitions.Find(opts.Transition)
if transMeta == nil {
possible := []string{}
for _, trans := range meta.Transitions {
possible = append(possible, trans.Name)
}
if status, ok := issueData.Fields["status"].(map[string]interface{}); ok {
if name, ok := status["name"].(string); ok {
return fmt.Errorf("Invalid Transition %q from %q, Available: %s", opts.Transition, name, strings.Join(possible, ", "))
}
}
return fmt.Errorf("No valid transition found matching %s", opts.Transition)
}
// need to default the Resolution, usually Fixed works but sometime need Done
if opts.Resolution == "" {
if resField, ok := transMeta.Fields["resolution"]; ok {
for _, allowedValueRaw := range resField.AllowedValues {
if allowedValue, ok := allowedValueRaw.(map[string]interface{}); ok {
if allowedValue["name"] == "Fixed" {
opts.Resolution = "Fixed"
} else if allowedValue["name"] == "Done" {
opts.Resolution = "Done"
}
}
}
}
}
opts.Overrides["resolution"] = opts.Resolution
type templateInput struct {
*jiradata.Issue `yaml:",inline"`
// Yes, Meta and Transition are redundant, but this is for backwards compatibility
// with old templates
Meta *jiradata.Transition `yaml:"meta,omitempty" json:"meta,omitemtpy"`
Transition *jiradata.Transition `yaml:"transition,omitempty" json:"transition,omitempty"`
Overrides map[string]string `yaml:"overrides,omitempty" json:"overrides,omitempty"`
}
issueUpdate := jiradata.IssueUpdate{}
input := templateInput{
Issue: issueData,
Meta: transMeta,
Transition: transMeta,
Overrides: opts.Overrides,
}
err = jc.editLoop(&opts.GlobalOptions, &input, &issueUpdate, func() error {
return jc.TransitionIssue(opts.Issue, &issueUpdate)
})
if err != nil {
return err
}
link := fmt.Sprintf("%s/browse/%s", jc.Endpoint, issueData.Key)
fmt.Printf("OK %s %s\n", issueData.Key, link)
// FIXME implement browse
return nil
}
+44
View File
@@ -0,0 +1,44 @@
package jiracli
import kingpin "gopkg.in/alecthomas/kingpin.v2"
type TransitionsOptions struct {
GlobalOptions
Issue string
}
func (jc *JiraCli) CmdTransitionsRegistry(defaultTemplate string) *CommandRegistryEntry {
opts := TransitionsOptions{
GlobalOptions: GlobalOptions{
Template: defaultTemplate,
},
}
return &CommandRegistryEntry{
"List valid issue transitions",
func() error {
return jc.CmdTransitions(&opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdTransitionsUsage(cmd, &opts)
},
}
}
func (jc *JiraCli) CmdTransitionsUsage(cmd *kingpin.CmdClause, opts *TransitionsOptions) error {
if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil {
return err
}
jc.TemplateUsage(cmd, &opts.GlobalOptions)
cmd.Arg("ISSUE", "issue to list valid transitions").Required().StringVar(&opts.Issue)
return nil
}
// Transitions will get issue edit metadata and send to "editmeta" template
func (jc *JiraCli) CmdTransitions(opts *TransitionsOptions) error {
editMeta, err := jc.GetIssueTransitions(opts.Issue)
if err != nil {
return err
}
return jc.runTemplate(opts.Template, editMeta, nil)
}
+3 -3
View File
@@ -1,4 +1,4 @@
package jira
package jiracli
import (
"fmt"
@@ -9,7 +9,7 @@ import (
)
type Transport struct {
shadow http.Transport
shadow *http.Transport
}
func NewUnixProxyTransport(path string) *Transport {
@@ -17,7 +17,7 @@ func NewUnixProxyTransport(path string) *Transport {
return net.Dial("unix", path)
}
shadow := http.Transport{
shadow := &http.Transport{
Dial: dial,
DialTLS: dial,
DisableKeepAlives: true,
+303
View File
@@ -0,0 +1,303 @@
package jiracli
import (
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"time"
kingpin "gopkg.in/alecthomas/kingpin.v2"
"github.com/coryb/figtree"
)
func homedir() string {
if runtime.GOOS == "windows" {
return os.Getenv("USERPROFILE")
}
return os.Getenv("HOME")
}
func findClosestParentPath(fileName string) (string, error) {
paths := figtree.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))
}
func (jc *JiraCli) tmpYml(tmpFilePrefix string) (*os.File, error) {
tmpdir := filepath.Join(homedir(), jc.ConfigDir, "tmp")
if err := os.MkdirAll(tmpdir, 0755); err != nil {
return nil, err
}
fh, err := ioutil.TempFile(tmpdir, tmpFilePrefix)
if err != nil {
return nil, err
}
// now we need to rename the file since we dont control the file extensions
// ... it has to be `.yml` so that vim/emacs etc know what edit mode to apply
// for easier editing
oldFileName := fh.Name()
newFileName := oldFileName + ".yml"
// close tmpfile so we can rename on windows
fh.Close()
if err := os.Rename(oldFileName, newFileName); err != nil {
return nil, err
}
return os.OpenFile(newFileName, os.O_RDWR|os.O_EXCL, 0600)
}
func flagValue(ctx *kingpin.ParseContext, name string) string {
for _, elem := range ctx.Elements {
if flag, ok := elem.Clause.(*kingpin.FlagClause); ok {
if flag.Model().Name == name {
return *elem.Value
}
}
}
return ""
}
// func readFile(file string) string {
// var bytes []byte
// var err error
// log.Debugf("readFile: reading %q", file)
// if bytes, err = ioutil.ReadFile(file); err != nil {
// log.Errorf("Failed to read file %s: %s", file, err)
// os.Exit(1)
// }
// return string(bytes)
// }
func copyFile(src, dst string) (err error) {
var s, d *os.File
if s, err = os.Open(src); err == nil {
defer s.Close()
if d, err = os.Create(dst); err == nil {
if _, err = io.Copy(d, s); err != nil {
d.Close()
return
}
return d.Close()
}
}
return
}
func fuzzyAge(start string) (string, error) {
t, err := time.Parse("2006-01-02T15:04:05.000-0700", start)
if err != nil {
return "", err
}
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) {
t, err := time.Parse("2006-01-02T15:04:05.000-0700", content)
if err != nil {
return "", err
}
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)
// }
// func responseToJSON(resp *http.Response, err error) (interface{}, error) {
// if err != nil {
// return nil, err
// }
// data := jsonDecode(resp.Body)
// if resp.StatusCode == 400 {
// if val, ok := data.(map[string]interface{})["errorMessages"]; ok {
// for _, errMsg := range val.([]interface{}) {
// log.Errorf("%s", errMsg)
// }
// }
// }
// return data, nil
// }
// func jsonDecode(io io.Reader) interface{} {
// content, err := ioutil.ReadAll(io)
// var data interface{}
// err = json.Unmarshal(content, &data)
// if err != nil {
// log.Errorf("JSON Parse Error: %s from %s", err, content)
// }
// return data
// }
// func jsonEncode(data interface{}) (string, error) {
// buffer := bytes.NewBuffer(make([]byte, 0))
// enc := json.NewEncoder(buffer)
// err := enc.Encode(data)
// if err != nil {
// log.Errorf("Failed to encode data %s: %s", data, err)
// return "", err
// }
// return buffer.String(), nil
// }
// func jsonWrite(file string, data interface{}) {
// fh, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
// defer fh.Close()
// if err != nil {
// log.Errorf("Failed to open %s: %s", file, err)
// os.Exit(1)
// }
// enc := json.NewEncoder(fh)
// enc.Encode(data)
// }
// func yamlWrite(file string, data interface{}) {
// fh, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
// defer fh.Close()
// if err != nil {
// log.Errorf("Failed to open %s: %s", file, err)
// os.Exit(1)
// }
// if out, err := yaml.Marshal(data); err != nil {
// log.Errorf("Failed to marshal yaml %v: %s", data, err)
// os.Exit(1)
// } else {
// fh.Write(out)
// }
// }
// func promptYN(prompt string, yes bool) bool {
// reader := bufio.NewReader(os.Stdin)
// if !yes {
// prompt = fmt.Sprintf("%s [y/N]: ", prompt)
// } else {
// prompt = fmt.Sprintf("%s [Y/n]: ", prompt)
// }
// fmt.Printf("%s", prompt)
// text, _ := reader.ReadString('\n')
// ans := strings.ToLower(strings.TrimRight(text, "\n"))
// if ans == "" {
// return yes
// }
// if strings.HasPrefix(ans, "y") {
// return true
// }
// return false
// }
// this is a HACK to make yaml parsed documents to be serializable
// to json, so prevent this:
// json: unsupported type: map[interface {}]interface {}
// Also we want to clean up common input errors for the edit
// templates, like dangling "\n"
func yamlFixup(data interface{}) (interface{}, error) {
switch d := data.(type) {
case map[interface{}]interface{}:
// need to copy this map into a string map so json can encode it
copy := make(map[string]interface{})
for key, val := range d {
switch k := key.(type) {
case string:
if fixed, err := yamlFixup(val); err != nil {
return nil, err
} else if fixed != nil {
copy[k] = fixed
}
default:
err := fmt.Errorf("YAML: key %s is type '%T', require 'string'", key, k)
log.Errorf("%s", err)
return nil, err
}
}
if len(copy) == 0 {
return nil, nil
}
return copy, nil
case map[string]interface{}:
copy := make(map[string]interface{})
for k, v := range d {
if fixed, err := yamlFixup(v); err != nil {
return nil, err
} else if fixed != nil {
copy[k] = fixed
}
}
if len(copy) == 0 {
return nil, nil
}
return copy, nil
case []interface{}:
copy := make([]interface{}, 0, len(d))
for _, val := range d {
if fixed, err := yamlFixup(val); err != nil {
return nil, err
} else if fixed != nil {
copy = append(copy, fixed)
}
}
if len(copy) == 0 {
return nil, nil
}
return copy, nil
case *interface{}:
if fixed, err := yamlFixup(*d); err != nil {
return nil, err
} else if fixed != nil {
*d = fixed
}
return d, nil
case string:
if d == "" || d == "\n" {
return nil, nil
}
return d, nil
default:
return d, nil
}
}
// func mkdir(dir string) error {
// if stat, err := os.Stat(dir); err != nil && !os.IsNotExist(err) {
// 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)
// log.Errorf("%s", err)
// return err
// } else {
// // dir does not exist, so try to create it
// if err := os.MkdirAll(dir, 0755); err != nil {
// log.Errorf("Failed to mkdir -p %s: %s", dir, err)
// return err
// }
// }
// return nil
// }
+51
View File
@@ -0,0 +1,51 @@
package jiracli
import (
jira "gopkg.in/Netflix-Skunkworks/go-jira.v1"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type ViewOptions struct {
GlobalOptions
jira.IssueOptions
}
func (jc *JiraCli) CmdViewRegistry() *CommandRegistryEntry {
issue := ""
opts := ViewOptions{
GlobalOptions: GlobalOptions{
Template: "view",
},
}
return &CommandRegistryEntry{
"Prints issue details",
func() error {
return jc.CmdView(issue, &opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdViewUsage(cmd, &issue, &opts)
},
}
}
func (jc *JiraCli) CmdViewUsage(cmd *kingpin.CmdClause, issue *string, opts *ViewOptions) error {
if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil {
return err
}
jc.TemplateUsage(cmd, &opts.GlobalOptions)
cmd.Flag("expand", "field to expand for the issue").StringsVar(&opts.Expand)
cmd.Flag("field", "field to return for the issue").StringsVar(&opts.Fields)
cmd.Flag("property", "property to return for issue").StringsVar(&opts.Properties)
cmd.Arg("ISSUE", "issue id to view").Required().StringVar(issue)
return nil
}
// View will get issue data and send to "view" template
func (jc *JiraCli) CmdView(issue string, opts *ViewOptions) error {
data, err := jc.GetIssue(issue, opts)
if err != nil {
return err
}
return jc.runTemplate(opts.Template, data, nil)
}
+52
View File
@@ -0,0 +1,52 @@
package jiracli
import (
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type WorklogAddOptions struct {
GlobalOptions
jiradata.Worklog
}
func (jc *JiraCli) CmdWorklogAddRegistry() *CommandRegistryEntry {
issue := ""
opts := WorklogAddOptions{
GlobalOptions: GlobalOptions{
Template: "worklog",
},
}
return &CommandRegistryEntry{
"Add a worklog to an issue",
func() error {
return jc.CmdWorklogAdd(issue, &opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdWorklogAddUsage(cmd, &issue, &opts)
},
}
}
func (jc *JiraCli) CmdWorklogAddUsage(cmd *kingpin.CmdClause, issue *string, opts *WorklogAddOptions) error {
if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil {
return err
}
jc.EditorUsage(cmd, &opts.GlobalOptions)
jc.TemplateUsage(cmd, &opts.GlobalOptions)
cmd.Flag("noedit", "Disable opening the editor").BoolVar(&opts.SkipEditing)
cmd.Flag("comment", "Comment message for worklog").Short('m').StringVar(&opts.Comment)
cmd.Flag("time-spent", "Time spent working on issue").Short('T').StringVar(&opts.TimeSpent)
cmd.Arg("ISSUE", "issue id to fetch worklogs").Required().StringVar(issue)
return nil
}
// CmdWorklogAdd will attempt to add (action=add) a worklog to the given issue.
// It will spawn the editor (unless --noedit isused) and post edited YAML
// content as JSON to the worklog endpoint
func (jc *JiraCli) CmdWorklogAdd(issue string, opts *WorklogAddOptions) error {
return jc.editLoop(&opts.GlobalOptions, &opts.Worklog, &opts.Worklog, func() error {
_, err := jc.AddIssueWorklog(issue, opts)
return err
})
}
+37
View File
@@ -0,0 +1,37 @@
package jiracli
import kingpin "gopkg.in/alecthomas/kingpin.v2"
func (jc *JiraCli) CmdWorklogListRegistry() *CommandRegistryEntry {
issue := ""
opts := GlobalOptions{
Template: "worklogs",
}
return &CommandRegistryEntry{
"Prints the worklog data for given issue",
func() error {
return jc.CmdWorklogList(issue, &opts)
},
func(cmd *kingpin.CmdClause) error {
return jc.CmdWorklogListUsage(cmd, &issue, &opts)
},
}
}
func (jc *JiraCli) CmdWorklogListUsage(cmd *kingpin.CmdClause, issue *string, opts *GlobalOptions) error {
if err := jc.GlobalUsage(cmd, opts); err != nil {
return err
}
jc.TemplateUsage(cmd, opts)
cmd.Arg("ISSUE", "issue id to fetch worklogs").Required().StringVar(issue)
return nil
}
// // CmdWorklogList will get worklog data for given issue and sent to the "worklogs" template
func (jc *JiraCli) CmdWorklogList(issue string, opts *GlobalOptions) error {
data, err := jc.GetIssueWorklog(issue)
if err != nil {
return err
}
return jc.runTemplate(opts.Template, data, nil)
}
+781
View File
@@ -0,0 +1,781 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// SearchResults defined from schema:
// {
// "title": "Search Results",
// "id": "https://docs.atlassian.com/jira/REST/schema/search-results#",
// "type": "object",
// "definitions": {
// "field-meta": {
// "title": "Field Meta",
// "type": "object",
// "properties": {
// "allowedValues": {
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "type": "string"
// },
// "defaultValue": {},
// "hasDefaultValue": {
// "type": "boolean"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "operations": {
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "required": {
// "type": "boolean"
// },
// "schema": {
// "$ref": "#/definitions/json-type"
// }
// }
// },
// "history-metadata-participant": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "json-type": {
// "title": "Json Type",
// "type": "object",
// "properties": {
// "custom": {
// "type": "string"
// },
// "customId": {
// "type": "integer"
// },
// "items": {
// "type": "string"
// },
// "system": {
// "type": "string"
// },
// "type": {
// "type": "string"
// }
// }
// },
// "link-group": {
// "title": "Link Group",
// "type": "object",
// "properties": {
// "groups": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/link-group"
// }
// },
// "header": {
// "$ref": "#/definitions/simple-link"
// },
// "id": {
// "type": "string"
// },
// "links": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/simple-link"
// }
// },
// "styleClass": {
// "type": "string"
// },
// "weight": {
// "type": "integer"
// }
// }
// },
// "simple-link": {
// "title": "Simple Link",
// "type": "object",
// "properties": {
// "href": {
// "type": "string"
// },
// "iconClass": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "label": {
// "type": "string"
// },
// "styleClass": {
// "type": "string"
// },
// "title": {
// "type": "string"
// },
// "weight": {
// "type": "integer"
// }
// }
// }
// },
// "properties": {
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "issues": {
// "title": "issues",
// "type": "array",
// "items": {
// "title": "Issue",
// "type": "object",
// "properties": {
// "changelog": {
// "title": "Changelog",
// "type": "object",
// "properties": {
// "histories": {
// "title": "histories",
// "type": "array",
// "items": {
// "title": "Change History",
// "type": "object",
// "properties": {
// "author": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "title": "accountId",
// "type": "string"
// },
// "active": {
// "title": "active",
// "type": "boolean"
// },
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "title": "displayName",
// "type": "string"
// },
// "emailAddress": {
// "title": "emailAddress",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "timeZone": {
// "title": "timeZone",
// "type": "string"
// }
// }
// },
// "created": {
// "title": "created",
// "type": "string"
// },
// "historyMetadata": {
// "title": "History Metadata",
// "type": "object",
// "properties": {
// "activityDescription": {
// "title": "activityDescription",
// "type": "string"
// },
// "activityDescriptionKey": {
// "title": "activityDescriptionKey",
// "type": "string"
// },
// "actor": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "cause": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "descriptionKey": {
// "title": "descriptionKey",
// "type": "string"
// },
// "emailDescription": {
// "title": "emailDescription",
// "type": "string"
// },
// "emailDescriptionKey": {
// "title": "emailDescriptionKey",
// "type": "string"
// },
// "extraData": {
// "title": "extraData",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "generator": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "type": {
// "title": "type",
// "type": "string"
// }
// }
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "items": {
// "title": "items",
// "type": "array",
// "items": {
// "title": "Change Item",
// "type": "object",
// "properties": {
// "field": {
// "title": "field",
// "type": "string"
// },
// "fieldId": {
// "title": "fieldId",
// "type": "string"
// },
// "fieldtype": {
// "title": "fieldtype",
// "type": "string"
// },
// "from": {
// "title": "from",
// "type": "string"
// },
// "fromString": {
// "title": "fromString",
// "type": "string"
// },
// "to": {
// "title": "to",
// "type": "string"
// },
// "toString": {
// "title": "toString",
// "type": "string"
// }
// }
// }
// }
// }
// }
// },
// "maxResults": {
// "title": "maxResults",
// "type": "integer"
// },
// "startAt": {
// "title": "startAt",
// "type": "integer"
// },
// "total": {
// "title": "total",
// "type": "integer"
// }
// }
// },
// "editmeta": {
// "title": "Edit Meta",
// "type": "object",
// "properties": {
// "fields": {
// "title": "fields",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Field Meta",
// "type": "object",
// "properties": {
// "allowedValues": {
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "type": "string"
// },
// "defaultValue": {},
// "hasDefaultValue": {
// "type": "boolean"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "operations": {
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "required": {
// "type": "boolean"
// },
// "schema": {
// "$ref": "#/definitions/json-type"
// }
// }
// }
// }
// }
// }
// },
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "fields": {
// "title": "fields",
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// },
// "fieldsToInclude": {
// "title": "Included Fields",
// "type": "object"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "names": {
// "title": "names",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "operations": {
// "title": "Opsbar",
// "type": "object",
// "properties": {
// "linkGroups": {
// "title": "linkGroups",
// "type": "array",
// "items": {
// "title": "Link Group",
// "type": "object",
// "properties": {
// "groups": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/link-group"
// }
// },
// "header": {
// "$ref": "#/definitions/simple-link"
// },
// "id": {
// "type": "string"
// },
// "links": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/simple-link"
// }
// },
// "styleClass": {
// "type": "string"
// },
// "weight": {
// "type": "integer"
// }
// }
// }
// }
// }
// },
// "properties": {
// "title": "Properties",
// "type": "object",
// "properties": {
// "properties": {
// "title": "properties",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// }
// }
// },
// "renderedFields": {
// "title": "renderedFields",
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// },
// "schema": {
// "title": "schema",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Json Type",
// "type": "object",
// "properties": {
// "custom": {
// "type": "string"
// },
// "customId": {
// "type": "integer"
// },
// "items": {
// "type": "string"
// },
// "system": {
// "type": "string"
// },
// "type": {
// "type": "string"
// }
// }
// }
// }
// },
// "self": {
// "title": "self",
// "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": {
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "type": "string"
// },
// "defaultValue": {},
// "hasDefaultValue": {
// "type": "boolean"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "operations": {
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "required": {
// "type": "boolean"
// },
// "schema": {
// "$ref": "#/definitions/json-type"
// }
// }
// }
// }
// },
// "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"
// }
// }
// }
// }
// }
// },
// "versionedRepresentations": {
// "title": "versionedRepresentations",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// }
// }
// }
// }
// }
// },
// "maxResults": {
// "title": "maxResults",
// "type": "integer"
// },
// "names": {
// "title": "names",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "schema": {
// "title": "schema",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Json Type",
// "type": "object",
// "properties": {
// "custom": {
// "type": "string"
// },
// "customId": {
// "type": "integer"
// },
// "items": {
// "type": "string"
// },
// "system": {
// "type": "string"
// },
// "type": {
// "type": "string"
// }
// }
// }
// }
// },
// "startAt": {
// "title": "startAt",
// "type": "integer"
// },
// "total": {
// "title": "total",
// "type": "integer"
// },
I// "warningMessages": {
// "title": "warningMessages",
// "type": "array",
// "items": {
// "type": "string"
// }
// }
// }
// }
type SearchResults struct {
Expand string `json:"expand,omitempty" yaml:"expand,omitempty"`
Issues Issues `json:"issues,omitempty" yaml:"issues,omitempty"`
MaxResults int `json:"maxResults,omitempty" yaml:"maxResults,omitempty"`
Names map[string]string `json:"names,omitempty" yaml:"names,omitempty"`
Schema JSONTypeMap `json:"schema,omitempty" yaml:"schema,omitempty"`
StartAt int `json:"startAt,omitempty" yaml:"startAt,omitempty"`
Total int `json:"total,omitempty" yaml:"total,omitempty"`
WarningMessages WarningMessages `json:"warningMessages,omitempty" yaml:"warningMessages,omitempty"`
}
+1
View File
@@ -0,0 +1 @@
cbennett@lgml-cbennett.corp.netflix.com.24999
@@ -5,7 +5,7 @@ package jiradata
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
+32
View File
@@ -0,0 +1,32 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir data schemas/AuthParams.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// AuthParams defined from schema:
// {
// "title": "Auth Params",
// "id": "https://docs.atlassian.com/jira/REST/schema/auth-params#",
// "type": "object",
// "properties": {
// "password": {
// "title": "password",
// "type": "string"
// },
// "username": {
// "title": "username",
// "type": "string"
// }
// }
// }
type AuthParams struct {
Password string `json:"password,omitempty" yaml:"password,omitempty"`
Username string `json:"username,omitempty" yaml:"username,omitempty"`
}
+60
View File
@@ -0,0 +1,60 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir data schemas/AuthSuccess.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// AuthSuccess defined from schema:
// {
// "title": "Auth Success",
// "id": "https://docs.atlassian.com/jira/REST/schema/auth-success#",
// "type": "object",
// "properties": {
// "loginInfo": {
// "title": "Login Info",
// "type": "object",
// "properties": {
// "failedLoginCount": {
// "title": "failedLoginCount",
// "type": "integer"
// },
// "lastFailedLoginTime": {
// "title": "lastFailedLoginTime",
// "type": "string"
// },
// "loginCount": {
// "title": "loginCount",
// "type": "integer"
// },
// "previousLoginTime": {
// "title": "previousLoginTime",
// "type": "string"
// }
// }
// },
// "session": {
// "title": "Session Info",
// "type": "object",
// "properties": {
// "name": {
// "title": "name",
// "type": "string"
// },
// "value": {
// "title": "value",
// "type": "string"
// }
// }
// }
// }
// }
type AuthSuccess struct {
LoginInfo *LoginInfo `json:"loginInfo,omitempty" yaml:"loginInfo,omitempty"`
Session *SessionInfo `json:"session,omitempty" yaml:"session,omitempty"`
}
+234
View File
@@ -0,0 +1,234 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// ChangeHistory defined from schema:
// {
// "title": "Change History",
// "type": "object",
// "properties": {
// "author": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "title": "accountId",
// "type": "string"
// },
// "active": {
// "title": "active",
// "type": "boolean"
// },
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "title": "displayName",
// "type": "string"
// },
// "emailAddress": {
// "title": "emailAddress",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "timeZone": {
// "title": "timeZone",
// "type": "string"
// }
// }
// },
// "created": {
// "title": "created",
// "type": "string"
// },
// "historyMetadata": {
// "title": "History Metadata",
// "type": "object",
// "properties": {
// "activityDescription": {
// "title": "activityDescription",
// "type": "string"
// },
// "activityDescriptionKey": {
// "title": "activityDescriptionKey",
// "type": "string"
// },
// "actor": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "cause": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "descriptionKey": {
// "title": "descriptionKey",
// "type": "string"
// },
// "emailDescription": {
// "title": "emailDescription",
// "type": "string"
// },
// "emailDescriptionKey": {
// "title": "emailDescriptionKey",
// "type": "string"
// },
// "extraData": {
// "title": "extraData",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "generator": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "type": {
// "title": "type",
// "type": "string"
// }
// }
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "items": {
// "title": "items",
// "type": "array",
// "items": {
// "title": "Change Item",
// "type": "object",
// "properties": {
// "field": {
// "title": "field",
// "type": "string"
// },
// "fieldId": {
// "title": "fieldId",
// "type": "string"
// },
// "fieldtype": {
// "title": "fieldtype",
// "type": "string"
// },
// "from": {
// "title": "from",
// "type": "string"
// },
// "fromString": {
// "title": "fromString",
// "type": "string"
// },
// "to": {
// "title": "to",
// "type": "string"
// },
// "toString": {
// "title": "toString",
// "type": "string"
// }
// }
// }
// }
// }
// }
type ChangeHistory struct {
Author *User `json:"author,omitempty" yaml:"author,omitempty"`
Created string `json:"created,omitempty" yaml:"created,omitempty"`
HistoryMetadata *HistoryMetadata `json:"historyMetadata,omitempty" yaml:"historyMetadata,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Items Items `json:"items,omitempty" yaml:"items,omitempty"`
}
+56
View File
@@ -0,0 +1,56 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// ChangeItem defined from schema:
// {
// "title": "Change Item",
// "type": "object",
// "properties": {
// "field": {
// "title": "field",
// "type": "string"
// },
// "fieldId": {
// "title": "fieldId",
// "type": "string"
// },
// "fieldtype": {
// "title": "fieldtype",
// "type": "string"
// },
// "from": {
// "title": "from",
// "type": "string"
// },
// "fromString": {
// "title": "fromString",
// "type": "string"
// },
// "to": {
// "title": "to",
// "type": "string"
// },
// "toString": {
// "title": "toString",
// "type": "string"
// }
// }
// }
type ChangeItem struct {
Field string `json:"field,omitempty" yaml:"field,omitempty"`
FieldID string `json:"fieldId,omitempty" yaml:"fieldId,omitempty"`
Fieldtype string `json:"fieldtype,omitempty" yaml:"fieldtype,omitempty"`
From string `json:"from,omitempty" yaml:"from,omitempty"`
FromString string `json:"fromString,omitempty" yaml:"fromString,omitempty"`
To string `json:"to,omitempty" yaml:"to,omitempty"`
ToString string `json:"toString,omitempty" yaml:"toString,omitempty"`
}
+255
View File
@@ -0,0 +1,255 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Changelog defined from schema:
// {
// "title": "Changelog",
// "type": "object",
// "properties": {
// "histories": {
// "title": "histories",
// "type": "array",
// "items": {
// "title": "Change History",
// "type": "object",
// "properties": {
// "author": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "title": "accountId",
// "type": "string"
// },
// "active": {
// "title": "active",
// "type": "boolean"
// },
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "title": "displayName",
// "type": "string"
// },
// "emailAddress": {
// "title": "emailAddress",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "timeZone": {
// "title": "timeZone",
// "type": "string"
// }
// }
// },
// "created": {
// "title": "created",
// "type": "string"
// },
// "historyMetadata": {
// "title": "History Metadata",
// "type": "object",
// "properties": {
// "activityDescription": {
// "title": "activityDescription",
// "type": "string"
// },
// "activityDescriptionKey": {
// "title": "activityDescriptionKey",
// "type": "string"
// },
// "actor": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "cause": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "descriptionKey": {
// "title": "descriptionKey",
// "type": "string"
// },
// "emailDescription": {
// "title": "emailDescription",
// "type": "string"
// },
// "emailDescriptionKey": {
// "title": "emailDescriptionKey",
// "type": "string"
// },
// "extraData": {
// "title": "extraData",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "generator": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "type": {
// "title": "type",
// "type": "string"
// }
// }
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "items": {
// "title": "items",
// "type": "array",
// "items": {
// "title": "Change Item",
// "type": "object",
// "properties": {
// "field": {
// "title": "field",
// "type": "string"
// },
// "fieldId": {
// "title": "fieldId",
// "type": "string"
// },
// "fieldtype": {
// "title": "fieldtype",
// "type": "string"
// },
// "from": {
// "title": "from",
// "type": "string"
// },
// "fromString": {
// "title": "fromString",
// "type": "string"
// },
// "to": {
// "title": "to",
// "type": "string"
// },
// "toString": {
// "title": "toString",
// "type": "string"
// }
// }
// }
// }
// }
// }
// },
// "maxResults": {
// "title": "maxResults",
// "type": "integer"
// },
// "startAt": {
// "title": "startAt",
// "type": "integer"
// },
// "total": {
// "title": "total",
// "type": "integer"
// }
// }
// }
type Changelog struct {
Histories Histories `json:"histories,omitempty" yaml:"histories,omitempty"`
MaxResults int `json:"maxResults,omitempty" yaml:"maxResults,omitempty"`
StartAt int `json:"startAt,omitempty" yaml:"startAt,omitempty"`
Total int `json:"total,omitempty" yaml:"total,omitempty"`
}
+21
View File
@@ -0,0 +1,21 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir data schemas/Field.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// ClauseNames defined from schema:
// {
// "title": "clauseNames",
// "type": "array",
// "items": {
// "type": "string"
// }
// }
type ClauseNames []string
+151
View File
@@ -0,0 +1,151 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/LinkIssueRequest.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Comment defined from schema:
// {
// "title": "Comment",
// "type": "object",
// "properties": {
// "author": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "type": "string"
// },
// "active": {
// "type": "boolean"
// },
// "avatarUrls": {
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "type": "string"
// },
// "emailAddress": {
// "type": "string"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "timeZone": {
// "type": "string"
// }
// }
// },
// "body": {
// "title": "body",
// "type": "string"
// },
// "created": {
// "title": "created",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "properties": {
// "title": "properties",
// "type": "array",
// "items": {
// "title": "Entity Property",
// "type": "object",
// "properties": {
// "key": {
// "title": "key",
// "type": "string"
// },
// "value": {
// "title": "value"
// }
// }
// }
// },
// "renderedBody": {
// "title": "renderedBody",
// "type": "string"
// },
// "updateAuthor": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "type": "string"
// },
// "active": {
// "type": "boolean"
// },
// "avatarUrls": {
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "type": "string"
// },
// "emailAddress": {
// "type": "string"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "timeZone": {
// "type": "string"
// }
// }
// },
// "updated": {
// "title": "updated",
// "type": "string"
// },
// "visibility": {
// "title": "Visibility",
// "type": "object",
// "properties": {
// "type": {
// "title": "type",
// "type": "string"
// },
// "value": {
// "title": "value",
// "type": "string"
// }
// }
// }
// }
// }
type Comment struct {
Author *User `json:"author,omitempty" yaml:"author,omitempty"`
Body string `json:"body,omitempty" yaml:"body,omitempty"`
Created string `json:"created,omitempty" yaml:"created,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Properties Properties `json:"properties,omitempty" yaml:"properties,omitempty"`
RenderedBody string `json:"renderedBody,omitempty" yaml:"renderedBody,omitempty"`
UpdateAuthor *User `json:"updateAuthor,omitempty" yaml:"updateAuthor,omitempty"`
Updated string `json:"updated,omitempty" yaml:"updated,omitempty"`
Visibility *Visibility `json:"visibility,omitempty" yaml:"visibility,omitempty"`
}
+224
View File
@@ -0,0 +1,224 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/Project.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Component defined from schema:
// {
// "title": "Component",
// "type": "object",
// "properties": {
// "assignee": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "type": "string"
// },
// "active": {
// "type": "boolean"
// },
// "applicationRoles": {
// "$ref": "#/definitions/simple-list-wrapper"
// },
// "avatarUrls": {
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "type": "string"
// },
// "emailAddress": {
// "type": "string"
// },
// "expand": {
// "type": "string"
// },
// "groups": {
// "$ref": "#/definitions/simple-list-wrapper"
// },
// "key": {
// "type": "string"
// },
// "locale": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// },
// "timeZone": {
// "type": "string"
// }
// }
// },
// "assigneeType": {
// "title": "assigneeType",
// "type": "string"
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "isAssigneeTypeValid": {
// "title": "isAssigneeTypeValid",
// "type": "boolean"
// },
// "lead": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "type": "string"
// },
// "active": {
// "type": "boolean"
// },
// "applicationRoles": {
// "$ref": "#/definitions/simple-list-wrapper"
// },
// "avatarUrls": {
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "type": "string"
// },
// "emailAddress": {
// "type": "string"
// },
// "expand": {
// "type": "string"
// },
// "groups": {
// "$ref": "#/definitions/simple-list-wrapper"
// },
// "key": {
// "type": "string"
// },
// "locale": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// },
// "timeZone": {
// "type": "string"
// }
// }
// },
// "leadUserName": {
// "title": "leadUserName",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "project": {
// "title": "project",
// "type": "string"
// },
// "projectId": {
// "title": "projectId",
// "type": "integer"
// },
// "realAssignee": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "type": "string"
// },
// "active": {
// "type": "boolean"
// },
// "applicationRoles": {
// "$ref": "#/definitions/simple-list-wrapper"
// },
// "avatarUrls": {
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "type": "string"
// },
// "emailAddress": {
// "type": "string"
// },
// "expand": {
// "type": "string"
// },
// "groups": {
// "$ref": "#/definitions/simple-list-wrapper"
// },
// "key": {
// "type": "string"
// },
// "locale": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// },
// "timeZone": {
// "type": "string"
// }
// }
// },
// "realAssigneeType": {
// "title": "realAssigneeType",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// }
type Component struct {
Assignee *User `json:"assignee,omitempty" yaml:"assignee,omitempty"`
AssigneeType string `json:"assigneeType,omitempty" yaml:"assigneeType,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
IsAssigneeTypeValid bool `json:"isAssigneeTypeValid,omitempty" yaml:"isAssigneeTypeValid,omitempty"`
Lead *User `json:"lead,omitempty" yaml:"lead,omitempty"`
LeadUserName string `json:"leadUserName,omitempty" yaml:"leadUserName,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Project string `json:"project,omitempty" yaml:"project,omitempty"`
ProjectID int `json:"projectId,omitempty" yaml:"projectId,omitempty"`
RealAssignee *User `json:"realAssignee,omitempty" yaml:"realAssignee,omitempty"`
RealAssigneeType string `json:"realAssigneeType,omitempty" yaml:"realAssigneeType,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
}
+214
View File
@@ -0,0 +1,214 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/Project.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Components defined from schema:
// {
// "title": "components",
// "type": "array",
// "items": {
// "title": "Component",
// "type": "object",
// "properties": {
// "assignee": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "type": "string"
// },
// "active": {
// "type": "boolean"
// },
// "applicationRoles": {
// "$ref": "#/definitions/simple-list-wrapper"
// },
// "avatarUrls": {
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "type": "string"
// },
// "emailAddress": {
// "type": "string"
// },
// "expand": {
// "type": "string"
// },
// "groups": {
// "$ref": "#/definitions/simple-list-wrapper"
// },
// "key": {
// "type": "string"
// },
// "locale": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// },
// "timeZone": {
// "type": "string"
// }
// }
// },
// "assigneeType": {
// "title": "assigneeType",
// "type": "string"
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "isAssigneeTypeValid": {
// "title": "isAssigneeTypeValid",
// "type": "boolean"
// },
// "lead": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "type": "string"
// },
// "active": {
// "type": "boolean"
// },
// "applicationRoles": {
// "$ref": "#/definitions/simple-list-wrapper"
// },
// "avatarUrls": {
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "type": "string"
// },
// "emailAddress": {
// "type": "string"
// },
// "expand": {
// "type": "string"
// },
// "groups": {
// "$ref": "#/definitions/simple-list-wrapper"
// },
// "key": {
// "type": "string"
// },
// "locale": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// },
// "timeZone": {
// "type": "string"
// }
// }
// },
// "leadUserName": {
// "title": "leadUserName",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "project": {
// "title": "project",
// "type": "string"
// },
// "projectId": {
// "title": "projectId",
// "type": "integer"
// },
// "realAssignee": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "type": "string"
// },
// "active": {
// "type": "boolean"
// },
// "applicationRoles": {
// "$ref": "#/definitions/simple-list-wrapper"
// },
// "avatarUrls": {
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "type": "string"
// },
// "emailAddress": {
// "type": "string"
// },
// "expand": {
// "type": "string"
// },
// "groups": {
// "$ref": "#/definitions/simple-list-wrapper"
// },
// "key": {
// "type": "string"
// },
// "locale": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// },
// "timeZone": {
// "type": "string"
// }
// }
// },
// "realAssigneeType": {
// "title": "realAssigneeType",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// }
// }
type Components []*Component
+182
View File
@@ -0,0 +1,182 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/CreateMeta.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// CreateMeta defined from schema:
// {
// "title": "Create Meta",
// "id": "https://docs.atlassian.com/jira/REST/schema/create-meta#",
// "type": "object",
// "properties": {
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "projects": {
// "title": "projects",
// "type": "array",
// "items": {
// "title": "Create Meta Project",
// "type": "object",
// "properties": {
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "issuetypes": {
// "title": "issuetypes",
// "type": "array",
// "items": {
// "title": "Create Meta Issue Type",
// "type": "object",
// "properties": {
// "avatarId": {
// "title": "avatarId",
// "type": "integer"
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "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"
// },
// "defaultValue": {
// "title": "defaultValue"
// },
// "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"
// }
// }
// }
// }
// }
// }
// },
// "iconUrl": {
// "title": "iconUrl",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "subtask": {
// "title": "subtask",
// "type": "boolean"
// }
// }
// }
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// }
// }
// }
// }
type CreateMeta struct {
Expand string `json:"expand,omitempty" yaml:"expand,omitempty"`
Projects Projects `json:"projects,omitempty" yaml:"projects,omitempty"`
}
+135
View File
@@ -0,0 +1,135 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/CreateMeta.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// CreateMetaIssueType defined from schema:
// {
// "title": "Create Meta Issue Type",
// "type": "object",
// "properties": {
// "avatarId": {
// "title": "avatarId",
// "type": "integer"
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "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"
// },
// "defaultValue": {
// "title": "defaultValue"
// },
// "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"
// }
// }
// }
// }
// }
// }
// },
// "iconUrl": {
// "title": "iconUrl",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "subtask": {
// "title": "subtask",
// "type": "boolean"
// }
// }
// }
type CreateMetaIssueType struct {
AvatarID int `json:"avatarId,omitempty" yaml:"avatarId,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
Expand string `json:"expand,omitempty" yaml:"expand,omitempty"`
Fields FieldMetaMap `json:"fields,omitempty" yaml:"fields,omitempty"`
IconURL string `json:"iconUrl,omitempty" yaml:"iconUrl,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
Subtask bool `json:"subtask,omitempty" yaml:"subtask,omitempty"`
}
+172
View File
@@ -0,0 +1,172 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/CreateMeta.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// CreateMetaProject defined from schema:
// {
// "title": "Create Meta Project",
// "type": "object",
// "properties": {
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "issuetypes": {
// "title": "issuetypes",
// "type": "array",
// "items": {
// "title": "Create Meta Issue Type",
// "type": "object",
// "properties": {
// "avatarId": {
// "title": "avatarId",
// "type": "integer"
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "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"
// },
// "defaultValue": {
// "title": "defaultValue"
// },
// "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"
// }
// }
// }
// }
// }
// }
// },
// "iconUrl": {
// "title": "iconUrl",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "subtask": {
// "title": "subtask",
// "type": "boolean"
// }
// }
// }
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// }
type CreateMetaProject struct {
AvatarUrls map[string]string `json:"avatarUrls,omitempty" yaml:"avatarUrls,omitempty"`
Expand string `json:"expand,omitempty" yaml:"expand,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Issuetypes Issuetypes `json:"issuetypes,omitempty" yaml:"issuetypes,omitempty"`
Key string `json:"key,omitempty" yaml:"key,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
}
+55
View File
@@ -0,0 +1,55 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir data schemas/CurrentUser.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// CurrentUser defined from schema:
// {
// "title": "Current User",
// "id": "https://docs.atlassian.com/jira/REST/schema/current-user#",
// "type": "object",
// "properties": {
// "loginInfo": {
// "title": "Login Info",
// "type": "object",
// "properties": {
// "failedLoginCount": {
// "title": "failedLoginCount",
// "type": "integer"
// },
// "lastFailedLoginTime": {
// "title": "lastFailedLoginTime",
// "type": "string"
// },
// "loginCount": {
// "title": "loginCount",
// "type": "integer"
// },
// "previousLoginTime": {
// "title": "previousLoginTime",
// "type": "string"
// }
// }
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// }
type CurrentUser struct {
LoginInfo *LoginInfo `json:"loginInfo,omitempty" yaml:"loginInfo,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
}
+63
View File
@@ -0,0 +1,63 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// EditMeta defined from schema:
// {
// "title": "Edit Meta",
// "type": "object",
// "properties": {
// "fields": {
// "title": "fields",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Field Meta",
// "type": "object",
// "properties": {
// "allowedValues": {
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "type": "string"
// },
// "defaultValue": {},
// "hasDefaultValue": {
// "type": "boolean"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "operations": {
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "required": {
// "type": "boolean"
// },
// "schema": {
// "$ref": "#/definitions/json-type"
// }
// }
// }
// }
// }
// }
// }
type EditMeta struct {
Fields FieldMetaMap `json:"fields,omitempty" yaml:"fields,omitempty"`
}
+30
View File
@@ -0,0 +1,30 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// EntityProperty defined from schema:
// {
// "title": "Entity Property",
// "type": "object",
// "properties": {
// "key": {
// "title": "key",
// "type": "string"
// },
// "value": {
// "title": "value"
// }
// }
// }
type EntityProperty struct {
Key string `json:"key,omitempty" yaml:"key,omitempty"`
Value interface{} `json:"value,omitempty" yaml:"value,omitempty"`
}
+45
View File
@@ -0,0 +1,45 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir data schemas/ErrorCollection.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// ErrorCollection defined from schema:
// {
// "title": "Error Collection",
// "id": "https://docs.atlassian.com/jira/REST/schema/error-collection#",
// "type": "object",
// "properties": {
// "errorMessages": {
// "title": "errorMessages",
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "errors": {
// "title": "errors",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "status": {
// "title": "status",
// "type": "integer"
// }
// }
// }
type ErrorCollection struct {
ErrorMessages ErrorMessages `json:"errorMessages,omitempty" yaml:"errorMessages,omitempty"`
Errors map[string]string `json:"errors,omitempty" yaml:"errors,omitempty"`
Status int `json:"status,omitempty" yaml:"status,omitempty"`
}
+20
View File
@@ -0,0 +1,20 @@
package jiradata
import (
"strings"
)
// Error is needed to make ErrorCollection implement the error interface
func (e ErrorCollection) Error() string {
if len(e.ErrorMessages) > 0 {
return strings.Join(e.ErrorMessages, ". ")
}
out := ""
for k, v := range e.Errors {
if len(out) > 0 {
out += ". "
}
out += k + ": " + v
}
return out
}
+21
View File
@@ -0,0 +1,21 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir data schemas/ErrorCollection.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// ErrorMessages defined from schema:
// {
// "title": "errorMessages",
// "type": "array",
// "items": {
// "type": "string"
// }
// }
type ErrorMessages []string
+92
View File
@@ -0,0 +1,92 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir data schemas/Field.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Field defined from schema:
// {
// "title": "Field",
// "id": "https://docs.atlassian.com/jira/REST/schema/field#",
// "type": "object",
// "properties": {
// "clauseNames": {
// "title": "clauseNames",
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "custom": {
// "title": "custom",
// "type": "boolean"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "navigable": {
// "title": "navigable",
// "type": "boolean"
// },
// "orderable": {
// "title": "orderable",
// "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"
// }
// }
// },
// "searchable": {
// "title": "searchable",
// "type": "boolean"
// }
// }
// }
type Field struct {
ClauseNames ClauseNames `json:"clauseNames,omitempty" yaml:"clauseNames,omitempty"`
Custom bool `json:"custom,omitempty" yaml:"custom,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Key string `json:"key,omitempty" yaml:"key,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Navigable bool `json:"navigable,omitempty" yaml:"navigable,omitempty"`
Orderable bool `json:"orderable,omitempty" yaml:"orderable,omitempty"`
Schema *JSONType `json:"schema,omitempty" yaml:"schema,omitempty"`
Searchable bool `json:"searchable,omitempty" yaml:"searchable,omitempty"`
}
+5 -1
View File
@@ -5,7 +5,7 @@ package jiradata
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
@@ -24,6 +24,9 @@ package jiradata
// "title": "autoCompleteUrl",
// "type": "string"
// },
// "defaultValue": {
// "title": "defaultValue"
// },
// "hasDefaultValue": {
// "title": "hasDefaultValue",
// "type": "boolean"
@@ -78,6 +81,7 @@ package jiradata
type FieldMeta struct {
AllowedValues AllowedValues `json:"allowedValues,omitempty" yaml:"allowedValues,omitempty"`
AutoCompleteURL string `json:"autoCompleteUrl,omitempty" yaml:"autoCompleteUrl,omitempty"`
DefaultValue interface{} `json:"defaultValue,omitempty" yaml:"defaultValue,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"`
@@ -5,7 +5,7 @@ package jiradata
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
@@ -28,6 +28,9 @@ package jiradata
// "title": "autoCompleteUrl",
// "type": "string"
// },
// "defaultValue": {
// "title": "defaultValue"
// },
// "hasDefaultValue": {
// "title": "hasDefaultValue",
// "type": "boolean"
+18
View File
@@ -0,0 +1,18 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// FieldOperation defined from schema:
// {
// "title": "Field Operation",
// "type": "object"
// }
type FieldOperation map[string]interface{}
+21
View File
@@ -0,0 +1,21 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// FieldOperations defined from schema:
// {
// "type": "array",
// "items": {
// "title": "Field Operation",
// "type": "object"
// }
// }
type FieldOperations []FieldOperation
+27
View File
@@ -0,0 +1,27 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// FieldOperationsMap defined from schema:
// {
// "title": "update",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "array",
// "items": {
// "title": "Field Operation",
// "type": "object"
// }
// }
// }
// }
type FieldOperationsMap map[string]FieldOperations
+21
View File
@@ -0,0 +1,21 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchRequest.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Fields defined from schema:
// {
// "title": "fields",
// "type": "array",
// "items": {
// "type": "string"
// }
// }
type Fields []string
+232
View File
@@ -0,0 +1,232 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Histories defined from schema:
// {
// "title": "histories",
// "type": "array",
// "items": {
// "title": "Change History",
// "type": "object",
// "properties": {
// "author": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "title": "accountId",
// "type": "string"
// },
// "active": {
// "title": "active",
// "type": "boolean"
// },
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "title": "displayName",
// "type": "string"
// },
// "emailAddress": {
// "title": "emailAddress",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "timeZone": {
// "title": "timeZone",
// "type": "string"
// }
// }
// },
// "created": {
// "title": "created",
// "type": "string"
// },
// "historyMetadata": {
// "title": "History Metadata",
// "type": "object",
// "properties": {
// "activityDescription": {
// "title": "activityDescription",
// "type": "string"
// },
// "activityDescriptionKey": {
// "title": "activityDescriptionKey",
// "type": "string"
// },
// "actor": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "cause": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "descriptionKey": {
// "title": "descriptionKey",
// "type": "string"
// },
// "emailDescription": {
// "title": "emailDescription",
// "type": "string"
// },
// "emailDescriptionKey": {
// "title": "emailDescriptionKey",
// "type": "string"
// },
// "extraData": {
// "title": "extraData",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "generator": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "type": {
// "title": "type",
// "type": "string"
// }
// }
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "items": {
// "title": "items",
// "type": "array",
// "items": {
// "title": "Change Item",
// "type": "object",
// "properties": {
// "field": {
// "title": "field",
// "type": "string"
// },
// "fieldId": {
// "title": "fieldId",
// "type": "string"
// },
// "fieldtype": {
// "title": "fieldtype",
// "type": "string"
// },
// "from": {
// "title": "from",
// "type": "string"
// },
// "fromString": {
// "title": "fromString",
// "type": "string"
// },
// "to": {
// "title": "to",
// "type": "string"
// },
// "toString": {
// "title": "toString",
// "type": "string"
// }
// }
// }
// }
// }
// }
// }
type Histories []*ChangeHistory
+141
View File
@@ -0,0 +1,141 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// HistoryMetadata defined from schema:
// {
// "title": "History Metadata",
// "type": "object",
// "properties": {
// "activityDescription": {
// "title": "activityDescription",
// "type": "string"
// },
// "activityDescriptionKey": {
// "title": "activityDescriptionKey",
// "type": "string"
// },
// "actor": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "cause": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "descriptionKey": {
// "title": "descriptionKey",
// "type": "string"
// },
// "emailDescription": {
// "title": "emailDescription",
// "type": "string"
// },
// "emailDescriptionKey": {
// "title": "emailDescriptionKey",
// "type": "string"
// },
// "extraData": {
// "title": "extraData",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "generator": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "type": {
// "title": "type",
// "type": "string"
// }
// }
// }
type HistoryMetadata struct {
ActivityDescription string `json:"activityDescription,omitempty" yaml:"activityDescription,omitempty"`
ActivityDescriptionKey string `json:"activityDescriptionKey,omitempty" yaml:"activityDescriptionKey,omitempty"`
Actor *HistoryMetadataParticipant `json:"actor,omitempty" yaml:"actor,omitempty"`
Cause *HistoryMetadataParticipant `json:"cause,omitempty" yaml:"cause,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
DescriptionKey string `json:"descriptionKey,omitempty" yaml:"descriptionKey,omitempty"`
EmailDescription string `json:"emailDescription,omitempty" yaml:"emailDescription,omitempty"`
EmailDescriptionKey string `json:"emailDescriptionKey,omitempty" yaml:"emailDescriptionKey,omitempty"`
ExtraData map[string]string `json:"extraData,omitempty" yaml:"extraData,omitempty"`
Generator *HistoryMetadataParticipant `json:"generator,omitempty" yaml:"generator,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
}
+45
View File
@@ -0,0 +1,45 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// HistoryMetadataParticipant defined from schema:
// {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// }
type HistoryMetadataParticipant struct {
AvatarURL string `json:"avatarUrl,omitempty" yaml:"avatarUrl,omitempty"`
DisplayName string `json:"displayName,omitempty" yaml:"displayName,omitempty"`
DisplayNameKey string `json:"displayNameKey,omitempty" yaml:"displayNameKey,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
URL string `json:"url,omitempty" yaml:"url,omitempty"`
}
+18
View File
@@ -0,0 +1,18 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// IncludedFields defined from schema:
// {
// "title": "Included Fields",
// "type": "object"
// }
type IncludedFields map[string]string
+579
View File
@@ -0,0 +1,579 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Issue defined from schema:
// {
// "title": "Issue",
// "type": "object",
// "properties": {
// "changelog": {
// "title": "Changelog",
// "type": "object",
// "properties": {
// "histories": {
// "title": "histories",
// "type": "array",
// "items": {
// "title": "Change History",
// "type": "object",
// "properties": {
// "author": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "title": "accountId",
// "type": "string"
// },
// "active": {
// "title": "active",
// "type": "boolean"
// },
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "title": "displayName",
// "type": "string"
// },
// "emailAddress": {
// "title": "emailAddress",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "timeZone": {
// "title": "timeZone",
// "type": "string"
// }
// }
// },
// "created": {
// "title": "created",
// "type": "string"
// },
// "historyMetadata": {
// "title": "History Metadata",
// "type": "object",
// "properties": {
// "activityDescription": {
// "title": "activityDescription",
// "type": "string"
// },
// "activityDescriptionKey": {
// "title": "activityDescriptionKey",
// "type": "string"
// },
// "actor": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "cause": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "descriptionKey": {
// "title": "descriptionKey",
// "type": "string"
// },
// "emailDescription": {
// "title": "emailDescription",
// "type": "string"
// },
// "emailDescriptionKey": {
// "title": "emailDescriptionKey",
// "type": "string"
// },
// "extraData": {
// "title": "extraData",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "generator": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "type": {
// "title": "type",
// "type": "string"
// }
// }
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "items": {
// "title": "items",
// "type": "array",
// "items": {
// "title": "Change Item",
// "type": "object",
// "properties": {
// "field": {
// "title": "field",
// "type": "string"
// },
// "fieldId": {
// "title": "fieldId",
// "type": "string"
// },
// "fieldtype": {
// "title": "fieldtype",
// "type": "string"
// },
// "from": {
// "title": "from",
// "type": "string"
// },
// "fromString": {
// "title": "fromString",
// "type": "string"
// },
// "to": {
// "title": "to",
// "type": "string"
// },
// "toString": {
// "title": "toString",
// "type": "string"
// }
// }
// }
// }
// }
// }
// },
// "maxResults": {
// "title": "maxResults",
// "type": "integer"
// },
// "startAt": {
// "title": "startAt",
// "type": "integer"
// },
// "total": {
// "title": "total",
// "type": "integer"
// }
// }
// },
// "editmeta": {
// "title": "Edit Meta",
// "type": "object",
// "properties": {
// "fields": {
// "title": "fields",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Field Meta",
// "type": "object",
// "properties": {
// "allowedValues": {
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "type": "string"
// },
// "defaultValue": {},
// "hasDefaultValue": {
// "type": "boolean"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "operations": {
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "required": {
// "type": "boolean"
// },
// "schema": {
// "$ref": "#/definitions/json-type"
// }
// }
// }
// }
// }
// }
// },
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "fields": {
// "title": "fields",
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// },
// "fieldsToInclude": {
// "title": "Included Fields",
// "type": "object"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "names": {
// "title": "names",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "operations": {
// "title": "Opsbar",
// "type": "object",
// "properties": {
// "linkGroups": {
// "title": "linkGroups",
// "type": "array",
// "items": {
// "title": "Link Group",
// "type": "object",
// "properties": {
// "groups": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/link-group"
// }
// },
// "header": {
// "$ref": "#/definitions/simple-link"
// },
// "id": {
// "type": "string"
// },
// "links": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/simple-link"
// }
// },
// "styleClass": {
// "type": "string"
// },
// "weight": {
// "type": "integer"
// }
// }
// }
// }
// }
// },
// "properties": {
// "title": "Properties",
// "type": "object",
// "properties": {
// "properties": {
// "title": "properties",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// }
// }
// },
// "renderedFields": {
// "title": "renderedFields",
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// },
// "schema": {
// "title": "schema",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Json Type",
// "type": "object",
// "properties": {
// "custom": {
// "type": "string"
// },
// "customId": {
// "type": "integer"
// },
// "items": {
// "type": "string"
// },
// "system": {
// "type": "string"
// },
// "type": {
// "type": "string"
// }
// }
// }
// }
// },
// "self": {
// "title": "self",
// "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": {
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "type": "string"
// },
// "defaultValue": {},
// "hasDefaultValue": {
// "type": "boolean"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "operations": {
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "required": {
// "type": "boolean"
// },
// "schema": {
// "$ref": "#/definitions/json-type"
// }
// }
// }
// }
// },
// "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"
// }
// }
// }
// }
// }
// },
// "versionedRepresentations": {
// "title": "versionedRepresentations",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// }
// }
// }
// }
// }
type Issue struct {
Changelog *Changelog `json:"changelog,omitempty" yaml:"changelog,omitempty"`
Editmeta *EditMeta `json:"editmeta,omitempty" yaml:"editmeta,omitempty"`
Expand string `json:"expand,omitempty" yaml:"expand,omitempty"`
Fields map[string]interface{} `json:"fields,omitempty" yaml:"fields,omitempty"`
FieldsToInclude IncludedFields `json:"fieldsToInclude,omitempty" yaml:"fieldsToInclude,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Key string `json:"key,omitempty" yaml:"key,omitempty"`
Names map[string]string `json:"names,omitempty" yaml:"names,omitempty"`
Operations *Opsbar `json:"operations,omitempty" yaml:"operations,omitempty"`
Properties *Properties `json:"properties,omitempty" yaml:"properties,omitempty"`
RenderedFields map[string]interface{} `json:"renderedFields,omitempty" yaml:"renderedFields,omitempty"`
Schema JSONTypeMap `json:"schema,omitempty" yaml:"schema,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
Transitions Transitions `json:"transitions,omitempty" yaml:"transitions,omitempty"`
VersionedRepresentations map[string]map[string]interface{} `json:"versionedRepresentations,omitempty" yaml:"versionedRepresentations,omitempty"`
}
+37
View File
@@ -0,0 +1,37 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/IssueCreateResponse.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// IssueCreateResponse defined from schema:
// {
// "title": "Issue Create Response",
// "id": "https://docs.atlassian.com/jira/REST/schema/issue-create-response#",
// "type": "object",
// "properties": {
// "id": {
// "title": "id",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// }
type IssueCreateResponse struct {
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Key string `json:"key,omitempty" yaml:"key,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
}
+41
View File
@@ -0,0 +1,41 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/LinkIssueRequest.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// IssueLinkType defined from schema:
// {
// "title": "Issue Link Type",
// "type": "object",
// "properties": {
// "id": {
// "title": "id",
// "type": "string"
// },
// "inward": {
// "title": "inward",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "outward": {
// "title": "outward",
// "type": "string"
// }
// }
// }
type IssueLinkType struct {
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Inward string `json:"inward,omitempty" yaml:"inward,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Outward string `json:"outward,omitempty" yaml:"outward,omitempty"`
}
+123
View File
@@ -0,0 +1,123 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/LinkIssueRequest.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// IssueRef defined from schema:
// {
// "title": "Issue Ref",
// "type": "object",
// "properties": {
// "fields": {
// "title": "Fields",
// "type": "object",
// "properties": {
// "issuetype": {
// "title": "Issue Type",
// "type": "object",
// "properties": {
// "avatarId": {
// "type": "integer"
// },
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "subtask": {
// "type": "boolean"
// }
// }
// },
// "priority": {
// "title": "Priority",
// "type": "object",
// "properties": {
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "statusColor": {
// "type": "string"
// }
// }
// },
// "status": {
// "title": "Status",
// "type": "object",
// "properties": {
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "statusCategory": {
// "title": "Status Category",
// "type": "object",
// "properties": {
// "colorName": {
// "type": "string"
// },
// "id": {
// "type": "integer"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// }
// }
// },
// "statusColor": {
// "type": "string"
// }
// }
// },
// "summary": {
// "type": "string"
// }
// }
// },
// "id": {
// "type": "string"
// },
// "key": {
// "type": "string"
// }
// }
// }
type IssueRef struct {
Fields *Fields `json:"fields,omitempty" yaml:"fields,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Key string `json:"key,omitempty" yaml:"key,omitempty"`
}
+56
View File
@@ -0,0 +1,56 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/Project.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// IssueType defined from schema:
// {
// "title": "Issue Type",
// "type": "object",
// "properties": {
// "avatarId": {
// "title": "avatarId",
// "type": "integer"
// },
// "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"
// },
// "subtask": {
// "title": "subtask",
// "type": "boolean"
// }
// }
// }
type IssueType struct {
AvatarID int `json:"avatarId,omitempty" yaml:"avatarId,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
IconURL string `json:"iconUrl,omitempty" yaml:"iconUrl,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
Subtask bool `json:"subtask,omitempty" yaml:"subtask,omitempty"`
}
+344
View File
@@ -0,0 +1,344 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// IssueUpdate defined from schema:
// {
// "title": "Issue Update",
// "id": "https://docs.atlassian.com/jira/REST/schema/issue-update#",
// "type": "object",
// "definitions": {
// "history-metadata-participant": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// }
// },
// "properties": {
// "fields": {
// "title": "fields",
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// },
// "historyMetadata": {
// "title": "History Metadata",
// "type": "object",
// "properties": {
// "activityDescription": {
// "title": "activityDescription",
// "type": "string"
// },
// "activityDescriptionKey": {
// "title": "activityDescriptionKey",
// "type": "string"
// },
// "actor": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "cause": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "descriptionKey": {
// "title": "descriptionKey",
// "type": "string"
// },
// "emailDescription": {
// "title": "emailDescription",
// "type": "string"
// },
// "emailDescriptionKey": {
// "title": "emailDescriptionKey",
// "type": "string"
// },
// "extraData": {
// "title": "extraData",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "generator": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "type": {
// "title": "type",
// "type": "string"
// }
// }
// },
// "properties": {
// "title": "properties",
// "type": "array",
// "items": {
// "title": "Entity Property",
// "type": "object",
// "properties": {
// "key": {
// "title": "key",
// "type": "string"
// },
// "value": {
// "title": "value"
// }
// }
// }
// },
// "transition": {
// "title": "Transition",
// "type": "object",
// "properties": {
// "fields": {
// "title": "fields",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Field Meta",
// "type": "object",
// "properties": {
// "allowedValues": {
// "title": "allowedValues",
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "title": "autoCompleteUrl",
// "type": "string"
// },
// "defaultValue": {
// "title": "defaultValue"
// },
// "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"
// },
// "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"
// }
// }
// },
// "statusColor": {
// "title": "statusColor",
// "type": "string"
// }
// }
// }
// }
// },
// "update": {
// "title": "update",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "array",
// "items": {
// "title": "Field Operation",
// "type": "object"
// }
// }
// }
// }
// }
// }
type IssueUpdate struct {
Fields map[string]interface{} `json:"fields,omitempty" yaml:"fields,omitempty"`
HistoryMetadata *HistoryMetadata `json:"historyMetadata,omitempty" yaml:"historyMetadata,omitempty"`
Properties Properties `json:"properties,omitempty" yaml:"properties,omitempty"`
Transition *Transition `json:"transition,omitempty" yaml:"transition,omitempty"`
Update FieldOperationsMap `json:"update,omitempty" yaml:"update,omitempty"`
}
+567
View File
@@ -0,0 +1,567 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Issues defined from schema:
// {
// "title": "issues",
// "type": "array",
// "items": {
// "title": "Issue",
// "type": "object",
// "properties": {
// "changelog": {
// "title": "Changelog",
// "type": "object",
// "properties": {
// "histories": {
// "title": "histories",
// "type": "array",
// "items": {
// "title": "Change History",
// "type": "object",
// "properties": {
// "author": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "title": "accountId",
// "type": "string"
// },
// "active": {
// "title": "active",
// "type": "boolean"
// },
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "title": "displayName",
// "type": "string"
// },
// "emailAddress": {
// "title": "emailAddress",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "timeZone": {
// "title": "timeZone",
// "type": "string"
// }
// }
// },
// "created": {
// "title": "created",
// "type": "string"
// },
// "historyMetadata": {
// "title": "History Metadata",
// "type": "object",
// "properties": {
// "activityDescription": {
// "title": "activityDescription",
// "type": "string"
// },
// "activityDescriptionKey": {
// "title": "activityDescriptionKey",
// "type": "string"
// },
// "actor": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "cause": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "descriptionKey": {
// "title": "descriptionKey",
// "type": "string"
// },
// "emailDescription": {
// "title": "emailDescription",
// "type": "string"
// },
// "emailDescriptionKey": {
// "title": "emailDescriptionKey",
// "type": "string"
// },
// "extraData": {
// "title": "extraData",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "generator": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "type": {
// "title": "type",
// "type": "string"
// }
// }
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "items": {
// "title": "items",
// "type": "array",
// "items": {
// "title": "Change Item",
// "type": "object",
// "properties": {
// "field": {
// "title": "field",
// "type": "string"
// },
// "fieldId": {
// "title": "fieldId",
// "type": "string"
// },
// "fieldtype": {
// "title": "fieldtype",
// "type": "string"
// },
// "from": {
// "title": "from",
// "type": "string"
// },
// "fromString": {
// "title": "fromString",
// "type": "string"
// },
// "to": {
// "title": "to",
// "type": "string"
// },
// "toString": {
// "title": "toString",
// "type": "string"
// }
// }
// }
// }
// }
// }
// },
// "maxResults": {
// "title": "maxResults",
// "type": "integer"
// },
// "startAt": {
// "title": "startAt",
// "type": "integer"
// },
// "total": {
// "title": "total",
// "type": "integer"
// }
// }
// },
// "editmeta": {
// "title": "Edit Meta",
// "type": "object",
// "properties": {
// "fields": {
// "title": "fields",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Field Meta",
// "type": "object",
// "properties": {
// "allowedValues": {
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "type": "string"
// },
// "defaultValue": {},
// "hasDefaultValue": {
// "type": "boolean"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "operations": {
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "required": {
// "type": "boolean"
// },
// "schema": {
// "$ref": "#/definitions/json-type"
// }
// }
// }
// }
// }
// }
// },
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "fields": {
// "title": "fields",
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// },
// "fieldsToInclude": {
// "title": "Included Fields",
// "type": "object"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "names": {
// "title": "names",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "operations": {
// "title": "Opsbar",
// "type": "object",
// "properties": {
// "linkGroups": {
// "title": "linkGroups",
// "type": "array",
// "items": {
// "title": "Link Group",
// "type": "object",
// "properties": {
// "groups": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/link-group"
// }
// },
// "header": {
// "$ref": "#/definitions/simple-link"
// },
// "id": {
// "type": "string"
// },
// "links": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/simple-link"
// }
// },
// "styleClass": {
// "type": "string"
// },
// "weight": {
// "type": "integer"
// }
// }
// }
// }
// }
// },
// "properties": {
// "title": "Properties",
// "type": "object",
// "properties": {
// "properties": {
// "title": "properties",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// }
// }
// },
// "renderedFields": {
// "title": "renderedFields",
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// },
// "schema": {
// "title": "schema",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Json Type",
// "type": "object",
// "properties": {
// "custom": {
// "type": "string"
// },
// "customId": {
// "type": "integer"
// },
// "items": {
// "type": "string"
// },
// "system": {
// "type": "string"
// },
// "type": {
// "type": "string"
// }
// }
// }
// }
// },
// "self": {
// "title": "self",
// "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": {
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "type": "string"
// },
// "defaultValue": {},
// "hasDefaultValue": {
// "type": "boolean"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "operations": {
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "required": {
// "type": "boolean"
// },
// "schema": {
// "$ref": "#/definitions/json-type"
// }
// }
// }
// }
// },
// "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"
// }
// }
// }
// }
// }
// },
// "versionedRepresentations": {
// "title": "versionedRepresentations",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// }
// }
// }
// }
// }
// }
type Issues []*Issue
+129
View File
@@ -0,0 +1,129 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/CreateMeta.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Issuetypes defined from schema:
// {
// "title": "issuetypes",
// "type": "array",
// "items": {
// "title": "Create Meta Issue Type",
// "type": "object",
// "properties": {
// "avatarId": {
// "title": "avatarId",
// "type": "integer"
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "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"
// },
// "defaultValue": {
// "title": "defaultValue"
// },
// "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"
// }
// }
// }
// }
// }
// }
// },
// "iconUrl": {
// "title": "iconUrl",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "subtask": {
// "title": "subtask",
// "type": "boolean"
// }
// }
// }
// }
type Issuetypes []*CreateMetaIssueType
+52
View File
@@ -0,0 +1,52 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Items defined from schema:
// {
// "title": "items",
// "type": "array",
// "items": {
// "title": "Change Item",
// "type": "object",
// "properties": {
// "field": {
// "title": "field",
// "type": "string"
// },
// "fieldId": {
// "title": "fieldId",
// "type": "string"
// },
// "fieldtype": {
// "title": "fieldtype",
// "type": "string"
// },
// "from": {
// "title": "from",
// "type": "string"
// },
// "fromString": {
// "title": "fromString",
// "type": "string"
// },
// "to": {
// "title": "to",
// "type": "string"
// },
// "toString": {
// "title": "toString",
// "type": "string"
// }
// }
// }
// }
type Items []*ChangeItem
+41
View File
@@ -0,0 +1,41 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// JSONTypeMap defined from schema:
// {
// "title": "schema",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Json Type",
// "type": "object",
// "properties": {
// "custom": {
// "type": "string"
// },
// "customId": {
// "type": "integer"
// },
// "items": {
// "type": "string"
// },
// "system": {
// "type": "string"
// },
// "type": {
// "type": "string"
// }
// }
// }
// }
// }
type JSONTypeMap map[string]*JSONType
+1 -1
View File
@@ -5,7 +5,7 @@ package jiradata
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
+51
View File
@@ -0,0 +1,51 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// LinkGroup defined from schema:
// {
// "title": "Link Group",
// "type": "object",
// "properties": {
// "groups": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/link-group"
// }
// },
// "header": {
// "$ref": "#/definitions/simple-link"
// },
// "id": {
// "type": "string"
// },
// "links": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/simple-link"
// }
// },
// "styleClass": {
// "type": "string"
// },
// "weight": {
// "type": "integer"
// }
// }
// }
type LinkGroup struct {
Groups []interface{} `json:"groups,omitempty" yaml:"groups,omitempty"`
Header interface{} `json:"header,omitempty" yaml:"header,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Links []interface{} `json:"links,omitempty" yaml:"links,omitempty"`
StyleClass string `json:"styleClass,omitempty" yaml:"styleClass,omitempty"`
Weight int `json:"weight,omitempty" yaml:"weight,omitempty"`
}
+48
View File
@@ -0,0 +1,48 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// LinkGroups defined from schema:
// {
// "title": "linkGroups",
// "type": "array",
// "items": {
// "title": "Link Group",
// "type": "object",
// "properties": {
// "groups": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/link-group"
// }
// },
// "header": {
// "$ref": "#/definitions/simple-link"
// },
// "id": {
// "type": "string"
// },
// "links": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/simple-link"
// }
// },
// "styleClass": {
// "type": "string"
// },
// "weight": {
// "type": "integer"
// }
// }
// }
// }
type LinkGroups []*LinkGroup
+527
View File
@@ -0,0 +1,527 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/LinkIssueRequest.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// LinkIssueRequest defined from schema:
// {
// "title": "Link Issue Request",
// "id": "https://docs.atlassian.com/jira/REST/schema/link-issue-request#",
// "type": "object",
// "definitions": {
// "issue-ref": {
// "title": "Issue Ref",
// "type": "object",
// "properties": {
// "fields": {
// "title": "Fields",
// "type": "object",
// "properties": {
// "issuetype": {
// "title": "Issue Type",
// "type": "object",
// "properties": {
// "avatarId": {
// "type": "integer"
// },
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "subtask": {
// "type": "boolean"
// }
// }
// },
// "priority": {
// "title": "Priority",
// "type": "object",
// "properties": {
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "statusColor": {
// "type": "string"
// }
// }
// },
// "status": {
// "title": "Status",
// "type": "object",
// "properties": {
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "statusCategory": {
// "title": "Status Category",
// "type": "object",
// "properties": {
// "colorName": {
// "type": "string"
// },
// "id": {
// "type": "integer"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// }
// }
// },
// "statusColor": {
// "type": "string"
// }
// }
// },
// "summary": {
// "type": "string"
// }
// }
// },
// "id": {
// "type": "string"
// },
// "key": {
// "type": "string"
// }
// }
// },
// "user": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "type": "string"
// },
// "active": {
// "type": "boolean"
// },
// "avatarUrls": {
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "type": "string"
// },
// "emailAddress": {
// "type": "string"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "timeZone": {
// "type": "string"
// }
// }
// }
// },
// "properties": {
// "comment": {
// "title": "Comment",
// "type": "object",
// "properties": {
// "author": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "type": "string"
// },
// "active": {
// "type": "boolean"
// },
// "avatarUrls": {
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "type": "string"
// },
// "emailAddress": {
// "type": "string"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "timeZone": {
// "type": "string"
// }
// }
// },
// "body": {
// "title": "body",
// "type": "string"
// },
// "created": {
// "title": "created",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "properties": {
// "title": "properties",
// "type": "array",
// "items": {
// "title": "Entity Property",
// "type": "object",
// "properties": {
// "key": {
// "title": "key",
// "type": "string"
// },
// "value": {
// "title": "value"
// }
// }
// }
// },
// "renderedBody": {
// "title": "renderedBody",
// "type": "string"
// },
// "updateAuthor": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "type": "string"
// },
// "active": {
// "type": "boolean"
// },
// "avatarUrls": {
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "type": "string"
// },
// "emailAddress": {
// "type": "string"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "timeZone": {
// "type": "string"
// }
// }
// },
// "updated": {
// "title": "updated",
// "type": "string"
// },
// "visibility": {
// "title": "Visibility",
// "type": "object",
// "properties": {
// "type": {
// "title": "type",
// "type": "string"
// },
// "value": {
// "title": "value",
// "type": "string"
// }
// }
// }
// }
// },
// "inwardIssue": {
// "title": "Issue Ref",
// "type": "object",
// "properties": {
// "fields": {
// "title": "Fields",
// "type": "object",
// "properties": {
// "issuetype": {
// "title": "Issue Type",
// "type": "object",
// "properties": {
// "avatarId": {
// "type": "integer"
// },
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "subtask": {
// "type": "boolean"
// }
// }
// },
// "priority": {
// "title": "Priority",
// "type": "object",
// "properties": {
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "statusColor": {
// "type": "string"
// }
// }
// },
// "status": {
// "title": "Status",
// "type": "object",
// "properties": {
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "statusCategory": {
// "title": "Status Category",
// "type": "object",
// "properties": {
// "colorName": {
// "type": "string"
// },
// "id": {
// "type": "integer"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// }
// }
// },
// "statusColor": {
// "type": "string"
// }
// }
// },
// "summary": {
// "type": "string"
// }
// }
// },
// "id": {
// "type": "string"
// },
// "key": {
// "type": "string"
// }
// }
// },
// "outwardIssue": {
// "title": "Issue Ref",
// "type": "object",
// "properties": {
// "fields": {
// "title": "Fields",
// "type": "object",
// "properties": {
// "issuetype": {
// "title": "Issue Type",
// "type": "object",
// "properties": {
// "avatarId": {
// "type": "integer"
// },
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "subtask": {
// "type": "boolean"
// }
// }
// },
// "priority": {
// "title": "Priority",
// "type": "object",
// "properties": {
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "statusColor": {
// "type": "string"
// }
// }
// },
// "status": {
// "title": "Status",
// "type": "object",
// "properties": {
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "statusCategory": {
// "title": "Status Category",
// "type": "object",
// "properties": {
// "colorName": {
// "type": "string"
// },
// "id": {
// "type": "integer"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// }
// }
// },
// "statusColor": {
// "type": "string"
// }
// }
// },
// "summary": {
// "type": "string"
// }
// }
// },
// "id": {
// "type": "string"
// },
// "key": {
// "type": "string"
// }
// }
// },
// "type": {
// "title": "Issue Link Type",
// "type": "object",
// "properties": {
// "id": {
// "title": "id",
// "type": "string"
// },
// "inward": {
// "title": "inward",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "outward": {
// "title": "outward",
// "type": "string"
// }
// }
// }
// }
// }
type LinkIssueRequest struct {
Comment *Comment `json:"comment,omitempty" yaml:"comment,omitempty"`
InwardIssue *IssueRef `json:"inwardIssue,omitempty" yaml:"inwardIssue,omitempty"`
OutwardIssue *IssueRef `json:"outwardIssue,omitempty" yaml:"outwardIssue,omitempty"`
Type *IssueLinkType `json:"type,omitempty" yaml:"type,omitempty"`
}
+41
View File
@@ -0,0 +1,41 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir data schemas/CurrentUser.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// LoginInfo defined from schema:
// {
// "title": "Login Info",
// "type": "object",
// "properties": {
// "failedLoginCount": {
// "title": "failedLoginCount",
// "type": "integer"
// },
// "lastFailedLoginTime": {
// "title": "lastFailedLoginTime",
// "type": "string"
// },
// "loginCount": {
// "title": "loginCount",
// "type": "integer"
// },
// "previousLoginTime": {
// "title": "previousLoginTime",
// "type": "string"
// }
// }
// }
type LoginInfo struct {
FailedLoginCount int `json:"failedLoginCount,omitempty" yaml:"failedLoginCount,omitempty"`
LastFailedLoginTime string `json:"lastFailedLoginTime,omitempty" yaml:"lastFailedLoginTime,omitempty"`
LoginCount int `json:"loginCount,omitempty" yaml:"loginCount,omitempty"`
PreviousLoginTime string `json:"previousLoginTime,omitempty" yaml:"previousLoginTime,omitempty"`
}
@@ -5,7 +5,7 @@ package jiradata
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
+56
View File
@@ -0,0 +1,56 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Opsbar defined from schema:
// {
// "title": "Opsbar",
// "type": "object",
// "properties": {
// "linkGroups": {
// "title": "linkGroups",
// "type": "array",
// "items": {
// "title": "Link Group",
// "type": "object",
// "properties": {
// "groups": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/link-group"
// }
// },
// "header": {
// "$ref": "#/definitions/simple-link"
// },
// "id": {
// "type": "string"
// },
// "links": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/simple-link"
// }
// },
// "styleClass": {
// "type": "string"
// },
// "weight": {
// "type": "integer"
// }
// }
// }
// }
// }
// }
type Opsbar struct {
LinkGroups LinkGroups `json:"linkGroups,omitempty" yaml:"linkGroups,omitempty"`
}
+41
View File
@@ -0,0 +1,41 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/LinkIssueRequest.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Priority defined from schema:
// {
// "title": "Priority",
// "type": "object",
// "properties": {
// "description": {
// "type": "string"
// },
// "iconUrl": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "statusColor": {
// "type": "string"
// }
// }
// }
type Priority struct {
Description string `json:"description,omitempty" yaml:"description,omitempty"`
IconURL string `json:"iconUrl,omitempty" yaml:"iconUrl,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
StatusColor string `json:"statusColor,omitempty" yaml:"statusColor,omitempty"`
}
+41
View File
@@ -0,0 +1,41 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/Project.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// ProjectCategory defined from schema:
// {
// "title": "Project Category",
// "type": "object",
// "properties": {
// "description": {
// "title": "description",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// }
type ProjectCategory struct {
Description string `json:"description,omitempty" yaml:"description,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
}
+21
View File
@@ -0,0 +1,21 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/Project.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// ProjectKeys defined from schema:
// {
// "title": "projectKeys",
// "type": "array",
// "items": {
// "type": "string"
// }
// }
type ProjectKeys []string
+168
View File
@@ -0,0 +1,168 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/CreateMeta.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Projects defined from schema:
// {
// "title": "projects",
// "type": "array",
// "items": {
// "title": "Create Meta Project",
// "type": "object",
// "properties": {
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "issuetypes": {
// "title": "issuetypes",
// "type": "array",
// "items": {
// "title": "Create Meta Issue Type",
// "type": "object",
// "properties": {
// "avatarId": {
// "title": "avatarId",
// "type": "integer"
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "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"
// },
// "defaultValue": {
// "title": "defaultValue"
// },
// "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"
// }
// }
// }
// }
// }
// }
// },
// "iconUrl": {
// "title": "iconUrl",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "subtask": {
// "title": "subtask",
// "type": "boolean"
// }
// }
// }
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// }
// }
type Projects []*CreateMetaProject
+31
View File
@@ -0,0 +1,31 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Properties defined from schema:
// {
// "title": "properties",
// "type": "array",
// "items": {
// "title": "Entity Property",
// "type": "object",
// "properties": {
// "key": {
// "title": "key",
// "type": "string"
// },
// "value": {
// "title": "value"
// }
// }
// }
// }
type Properties []*EntityProperty
+35
View File
@@ -0,0 +1,35 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/Project.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// RemoteEntityLink defined from schema:
// {
// "title": "Remote Entity Link",
// "type": "object",
// "properties": {
// "link": {
// "title": "link"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// }
type RemoteEntityLink struct {
Link interface{} `json:"link,omitempty" yaml:"link,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
}
+35
View File
@@ -0,0 +1,35 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/Project.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Remotelinks defined from schema:
// {
// "title": "remotelinks",
// "type": "array",
// "items": {
// "title": "Remote Entity Link",
// "type": "object",
// "properties": {
// "link": {
// "title": "link"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// }
// }
type Remotelinks []*RemoteEntityLink
+63
View File
@@ -0,0 +1,63 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchRequest.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// SearchRequest defined from schema:
// {
// "title": "Search Request",
// "id": "https://docs.atlassian.com/jira/REST/schema/search-request#",
// "type": "object",
// "properties": {
// "fields": {
// "title": "fields",
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "fieldsByKeys": {
// "title": "fieldsByKeys",
// "type": "boolean"
// },
// "jql": {
// "title": "jql",
// "type": "string"
// },
// "maxResults": {
// "title": "maxResults",
// "type": "integer"
// },
// "properties": {
// "title": "properties",
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "startAt": {
// "title": "startAt",
// "type": "integer"
// },
// "validateQuery": {
// "title": "validateQuery",
// "type": "string"
// }
// }
// }
type SearchRequest struct {
Fields Fields `json:"fields,omitempty" yaml:"fields,omitempty"`
FieldsByKeys bool `json:"fieldsByKeys,omitempty" yaml:"fieldsByKeys,omitempty"`
JQL string `json:"jql,omitempty" yaml:"jql,omitempty"`
MaxResults int `json:"maxResults,omitempty" yaml:"maxResults,omitempty"`
Properties Properties `json:"properties,omitempty" yaml:"properties,omitempty"`
StartAt int `json:"startAt,omitempty" yaml:"startAt,omitempty"`
ValidateQuery string `json:"validateQuery,omitempty" yaml:"validateQuery,omitempty"`
}
+781
View File
@@ -0,0 +1,781 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// SearchResults defined from schema:
// {
// "title": "Search Results",
// "id": "https://docs.atlassian.com/jira/REST/schema/search-results#",
// "type": "object",
// "definitions": {
// "field-meta": {
// "title": "Field Meta",
// "type": "object",
// "properties": {
// "allowedValues": {
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "type": "string"
// },
// "defaultValue": {},
// "hasDefaultValue": {
// "type": "boolean"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "operations": {
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "required": {
// "type": "boolean"
// },
// "schema": {
// "$ref": "#/definitions/json-type"
// }
// }
// },
// "history-metadata-participant": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "json-type": {
// "title": "Json Type",
// "type": "object",
// "properties": {
// "custom": {
// "type": "string"
// },
// "customId": {
// "type": "integer"
// },
// "items": {
// "type": "string"
// },
// "system": {
// "type": "string"
// },
// "type": {
// "type": "string"
// }
// }
// },
// "link-group": {
// "title": "Link Group",
// "type": "object",
// "properties": {
// "groups": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/link-group"
// }
// },
// "header": {
// "$ref": "#/definitions/simple-link"
// },
// "id": {
// "type": "string"
// },
// "links": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/simple-link"
// }
// },
// "styleClass": {
// "type": "string"
// },
// "weight": {
// "type": "integer"
// }
// }
// },
// "simple-link": {
// "title": "Simple Link",
// "type": "object",
// "properties": {
// "href": {
// "type": "string"
// },
// "iconClass": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "label": {
// "type": "string"
// },
// "styleClass": {
// "type": "string"
// },
// "title": {
// "type": "string"
// },
// "weight": {
// "type": "integer"
// }
// }
// }
// },
// "properties": {
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "issues": {
// "title": "issues",
// "type": "array",
// "items": {
// "title": "Issue",
// "type": "object",
// "properties": {
// "changelog": {
// "title": "Changelog",
// "type": "object",
// "properties": {
// "histories": {
// "title": "histories",
// "type": "array",
// "items": {
// "title": "Change History",
// "type": "object",
// "properties": {
// "author": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "title": "accountId",
// "type": "string"
// },
// "active": {
// "title": "active",
// "type": "boolean"
// },
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "title": "displayName",
// "type": "string"
// },
// "emailAddress": {
// "title": "emailAddress",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "timeZone": {
// "title": "timeZone",
// "type": "string"
// }
// }
// },
// "created": {
// "title": "created",
// "type": "string"
// },
// "historyMetadata": {
// "title": "History Metadata",
// "type": "object",
// "properties": {
// "activityDescription": {
// "title": "activityDescription",
// "type": "string"
// },
// "activityDescriptionKey": {
// "title": "activityDescriptionKey",
// "type": "string"
// },
// "actor": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "cause": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "description": {
// "title": "description",
// "type": "string"
// },
// "descriptionKey": {
// "title": "descriptionKey",
// "type": "string"
// },
// "emailDescription": {
// "title": "emailDescription",
// "type": "string"
// },
// "emailDescriptionKey": {
// "title": "emailDescriptionKey",
// "type": "string"
// },
// "extraData": {
// "title": "extraData",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "generator": {
// "title": "History Metadata Participant",
// "type": "object",
// "properties": {
// "avatarUrl": {
// "type": "string"
// },
// "displayName": {
// "type": "string"
// },
// "displayNameKey": {
// "type": "string"
// },
// "id": {
// "type": "string"
// },
// "type": {
// "type": "string"
// },
// "url": {
// "type": "string"
// }
// }
// },
// "type": {
// "title": "type",
// "type": "string"
// }
// }
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "items": {
// "title": "items",
// "type": "array",
// "items": {
// "title": "Change Item",
// "type": "object",
// "properties": {
// "field": {
// "title": "field",
// "type": "string"
// },
// "fieldId": {
// "title": "fieldId",
// "type": "string"
// },
// "fieldtype": {
// "title": "fieldtype",
// "type": "string"
// },
// "from": {
// "title": "from",
// "type": "string"
// },
// "fromString": {
// "title": "fromString",
// "type": "string"
// },
// "to": {
// "title": "to",
// "type": "string"
// },
// "toString": {
// "title": "toString",
// "type": "string"
// }
// }
// }
// }
// }
// }
// },
// "maxResults": {
// "title": "maxResults",
// "type": "integer"
// },
// "startAt": {
// "title": "startAt",
// "type": "integer"
// },
// "total": {
// "title": "total",
// "type": "integer"
// }
// }
// },
// "editmeta": {
// "title": "Edit Meta",
// "type": "object",
// "properties": {
// "fields": {
// "title": "fields",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Field Meta",
// "type": "object",
// "properties": {
// "allowedValues": {
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "type": "string"
// },
// "defaultValue": {},
// "hasDefaultValue": {
// "type": "boolean"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "operations": {
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "required": {
// "type": "boolean"
// },
// "schema": {
// "$ref": "#/definitions/json-type"
// }
// }
// }
// }
// }
// }
// },
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "fields": {
// "title": "fields",
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// },
// "fieldsToInclude": {
// "title": "Included Fields",
// "type": "object"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "names": {
// "title": "names",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "operations": {
// "title": "Opsbar",
// "type": "object",
// "properties": {
// "linkGroups": {
// "title": "linkGroups",
// "type": "array",
// "items": {
// "title": "Link Group",
// "type": "object",
// "properties": {
// "groups": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/link-group"
// }
// },
// "header": {
// "$ref": "#/definitions/simple-link"
// },
// "id": {
// "type": "string"
// },
// "links": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/simple-link"
// }
// },
// "styleClass": {
// "type": "string"
// },
// "weight": {
// "type": "integer"
// }
// }
// }
// }
// }
// },
// "properties": {
// "title": "Properties",
// "type": "object",
// "properties": {
// "properties": {
// "title": "properties",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// }
// }
// },
// "renderedFields": {
// "title": "renderedFields",
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// },
// "schema": {
// "title": "schema",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Json Type",
// "type": "object",
// "properties": {
// "custom": {
// "type": "string"
// },
// "customId": {
// "type": "integer"
// },
// "items": {
// "type": "string"
// },
// "system": {
// "type": "string"
// },
// "type": {
// "type": "string"
// }
// }
// }
// }
// },
// "self": {
// "title": "self",
// "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": {
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "type": "string"
// },
// "defaultValue": {},
// "hasDefaultValue": {
// "type": "boolean"
// },
// "key": {
// "type": "string"
// },
// "name": {
// "type": "string"
// },
// "operations": {
// "type": "array",
// "items": {
// "type": "string"
// }
// },
// "required": {
// "type": "boolean"
// },
// "schema": {
// "$ref": "#/definitions/json-type"
// }
// }
// }
// }
// },
// "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"
// }
// }
// }
// }
// }
// },
// "versionedRepresentations": {
// "title": "versionedRepresentations",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// }
// }
// }
// }
// }
// },
// "maxResults": {
// "title": "maxResults",
// "type": "integer"
// },
// "names": {
// "title": "names",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "schema": {
// "title": "schema",
// "type": "object",
// "patternProperties": {
// ".+": {
// "title": "Json Type",
// "type": "object",
// "properties": {
// "custom": {
// "type": "string"
// },
// "customId": {
// "type": "integer"
// },
// "items": {
// "type": "string"
// },
// "system": {
// "type": "string"
// },
// "type": {
// "type": "string"
// }
// }
// }
// }
// },
// "startAt": {
// "title": "startAt",
// "type": "integer"
// },
// "total": {
// "title": "total",
// "type": "integer"
// },
// "warningMessages": {
// "title": "warningMessages",
// "type": "array",
// "items": {
// "type": "string"
// }
// }
// }
// }
type SearchResults struct {
Expand string `json:"expand,omitempty" yaml:"expand,omitempty"`
Issues Issues `json:"issues,omitempty" yaml:"issues,omitempty"`
MaxResults int `json:"maxResults,omitempty" yaml:"maxResults,omitempty"`
Names map[string]string `json:"names,omitempty" yaml:"names,omitempty"`
Schema JSONTypeMap `json:"schema,omitempty" yaml:"schema,omitempty"`
StartAt int `json:"startAt,omitempty" yaml:"startAt,omitempty"`
Total int `json:"total,omitempty" yaml:"total,omitempty"`
WarningMessages WarningMessages `json:"warningMessages,omitempty" yaml:"warningMessages,omitempty"`
}
+31
View File
@@ -0,0 +1,31 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -dir data schemas/AuthSuccess.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// SessionInfo defined from schema:
// {
// "title": "Session Info",
// "type": "object",
// "properties": {
// "name": {
// "title": "name",
// "type": "string"
// },
// "value": {
// "title": "value",
// "type": "string"
// }
// }
// }
type SessionInfo struct {
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Value string `json:"value,omitempty" yaml:"value,omitempty"`
}
+56
View File
@@ -0,0 +1,56 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata schemas/Project.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// SimpleLink defined from schema:
// {
// "title": "Simple Link",
// "type": "object",
// "properties": {
// "href": {
// "title": "href",
// "type": "string"
// },
// "iconClass": {
// "title": "iconClass",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "string"
// },
// "label": {
// "title": "label",
// "type": "string"
// },
// "styleClass": {
// "title": "styleClass",
// "type": "string"
// },
// "title": {
// "title": "title",
// "type": "string"
// },
// "weight": {
// "title": "weight",
// "type": "integer"
// }
// }
// }
type SimpleLink struct {
Href string `json:"href,omitempty" yaml:"href,omitempty"`
IconClass string `json:"iconClass,omitempty" yaml:"iconClass,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Label string `json:"label,omitempty" yaml:"label,omitempty"`
StyleClass string `json:"styleClass,omitempty" yaml:"styleClass,omitempty"`
Title string `json:"title,omitempty" yaml:"title,omitempty"`
Weight int `json:"weight,omitempty" yaml:"weight,omitempty"`
}
+1 -10
View File
@@ -5,7 +5,7 @@ package jiradata
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
@@ -31,10 +31,6 @@ package jiradata
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "statusCategory": {
// "title": "Status Category",
// "type": "object",
@@ -54,10 +50,6 @@ package jiradata
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// },
@@ -72,7 +64,6 @@ type Status struct {
IconURL string `json:"iconUrl,omitempty" yaml:"iconUrl,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
StatusCategory *StatusCategory `json:"statusCategory,omitempty" yaml:"statusCategory,omitempty"`
StatusColor string `json:"statusColor,omitempty" yaml:"statusColor,omitempty"`
}
@@ -5,7 +5,7 @@ package jiradata
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
@@ -30,10 +30,6 @@ package jiradata
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// }
@@ -42,5 +38,4 @@ type StatusCategory struct {
ID int `json:"id,omitempty" yaml:"id,omitempty"`
Key string `json:"key,omitempty" yaml:"key,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
}
+4 -14
View File
@@ -5,7 +5,7 @@ package jiradata
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
// slipscheme -pkg jiradata -dir jiradata -overwrite schemas/IssueUpdate.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
@@ -15,10 +15,6 @@ package jiradata
// "title": "Transition",
// "type": "object",
// "properties": {
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "fields": {
// "title": "fields",
// "type": "object",
@@ -36,6 +32,9 @@ package jiradata
// "title": "autoCompleteUrl",
// "type": "string"
// },
// "defaultValue": {
// "title": "defaultValue"
// },
// "hasDefaultValue": {
// "title": "hasDefaultValue",
// "type": "boolean"
@@ -121,10 +120,6 @@ package jiradata
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "statusCategory": {
// "title": "Status Category",
// "type": "object",
@@ -144,10 +139,6 @@ package jiradata
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// }
// }
// },
@@ -160,7 +151,6 @@ package jiradata
// }
// }
type Transition struct {
Expand string `json:"expand,omitempty" yaml:"expand,omitempty"`
Fields FieldMetaMap `json:"fields,omitempty" yaml:"fields,omitempty"`
HasScreen bool `json:"hasScreen,omitempty" yaml:"hasScreen,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
@@ -5,7 +5,7 @@ package jiradata
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -pkg jiradata -overwrite ../schemas/TransitionsMeta.json
// slipscheme -dir data -pkg jiradata -overwrite schemas/SearchResults.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
@@ -31,62 +31,33 @@ package jiradata
// "type": "object",
// "properties": {
// "allowedValues": {
// "title": "allowedValues",
// "type": "array",
// "items": {}
// },
// "autoCompleteUrl": {
// "title": "autoCompleteUrl",
// "type": "string"
// },
// "defaultValue": {},
// "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"
// }
// }
// "$ref": "#/definitions/json-type"
// }
// }
// }

Some files were not shown because too many files have changed in this diff Show More