Compare commits

..

28 Commits

Author SHA1 Message Date
Cory Bennett b5417ef585 update version tag to prefix with v 2016-01-21 17:38:50 -08:00
Cory Bennett c5af781c41 Updated Changelog 2016-01-21 17:36:23 -08:00
Cory Bennett f2c4df9b3e [issue #28] check to make sure we got back issuetypes for create metadata 2016-01-21 17:35:18 -08:00
Cory Bennett 1dde7e06e6 gofmt 2016-01-21 10:52:15 -08:00
coryb 7bc1897792 Merge pull request #27 from blalor/insecure-skip-verify
Add insecure option for TLS endpoints
2016-01-21 10:15:29 -08:00
Brian Lalor 37aab3580b Add insecure option for TLS endpoints
This gives the option of disabling TLS certificate verification for
the server.

Closes #25
2016-01-21 12:30:23 -05:00
coryb 42990d8ca0 Merge pull request #21 from mikepea/label_command
Add 'labels' command to set/add/remove labels
2016-01-04 08:50:15 -08:00
Mike Pountney 8e662462da Correct naming of parameter: set/add/remove are actions.
'command' is not approprirate for the set/add/remove operations, and is
confusing. Rename to 'action' to remove this confusion.
2016-01-03 20:28:02 -08:00
Mike Pountney ad7bb2b724 Tweak CmdLabels args so that magic happens with CLI
The CLI looks for commands (like 'labels') in the first two positional args. This
is how commands like 'BLOCKER blocks ISSUE' work.

As per @coryb's comments in #21 - this allows us to support set/add/remove in a
consistent way for other types: components for example.

This commit rearranges the command to be as follows:

    jira (set/add/remove) labels ISSUE LABELS...

The options to CmdLabels have been reordered accordingly.
2016-01-03 20:10:49 -08:00
Mike Pountney a8cce44178 Merge branch 'master' into label_command 2016-01-03 19:50:47 -08:00
coryb 35955a7a93 Merge pull request #22 from mikepea/library_break_out
Expose key functionality for library consumption
2015-12-31 12:22:09 -08:00
Mike Pountney f349e25bb9 Expose ViewTicket as per FindIssues
This allows external users of the API to retreive issue details, in the same
manner that FindIssues provides for lists of issues.
2015-12-31 12:06:04 -08:00
Mike Pountney a92a93b282 Add exposed versions of getTemplate and runTemplate
GetTemplate and RunTemplate allow external users to access the template system,
and in particular allow them to provide their own Buffer to write the output to.

I've implemented exposed versions calling the private functions, rather than breaking
the internal API. If this isn't a concern, we should remove getTemplate and runTemplate
in a future commit.
2015-12-31 12:03:22 -08:00
Mike Pountney 8645ef11f1 go fmt 2015-12-31 11:52:55 -08:00
Mike Pountney e042a3e62a Add 'labels' command to set/add/remove labels
This adds 'labels' command, which allows for the setting, addition and removal
of labels on an issue.

'set' action resets the issue labels to the list provided.
'add' action adds the supplied labels to the issue
'remove' action removes the supplied labels from the issue

The API already gracefully handles duplication, removal of non-existant labels, and the
supplying of an empty list of labels (which is useful in the case of 'set')

Eg

jira labels TEST-123 add label1 label2 label3
jira labels TEST-123 remove label1 label2
jira labels TEST-123 set label1 label2 label3
jira labels TEST-123 set # clears any labels on the issue
jira labels TEST-123 add # no-op
jira labels TEST-123 remove # no-op

This mirrors the functionality of the API.
2015-12-24 11:30:52 -08:00
coryb a738d1515e Merge pull request #20 from mikepea/add_join_template_func
Add a 'join' func to the template engine
2015-12-23 12:05:34 -08:00
Mike Pountney d4f15ae5c6 Add a 'join' func to the template engine
I needed this so that I can display JIRA labels in my 'list' template.
2015-12-23 06:15:31 -08:00
Cory Bennett bc70b43868 make "jira" golang package, move code from jira/cli to root, move jira/main.go to main/main.go 2015-12-22 17:56:53 -08:00
Cory Bennett e24b431b7a Updated Changelog 2015-12-09 20:58:11 -08:00
Cory Bennett 101bc1da68 fix jira trans TRANS ISSUE (case sensitivity issue), also go fmt 2015-12-09 20:57:10 -08:00
Cory Bennett 63e035c5c1 Updated Changelog 2015-12-03 14:47:55 -08:00
Cory Bennett 40bafc9b66 need to default "quiet" to false 2015-12-03 14:47:31 -08:00
Cory Bennett 5d863ffed4 Updated Changelog 2015-12-03 12:56:18 -08:00
Cory Bennett 577394b0bd add --quiet command to not print the OK ..
add --saveFile option to print the issue/link to a file on create command
2015-12-03 12:55:14 -08:00
Cory Bennett c1a7e1bbdb fix overrides 2015-12-03 12:21:55 -08:00
Cory Bennett f904f3c089 add abstract request wrapper to allow you to access/process random apis
supported by Jira but not yet supported by go-jira
2015-12-03 11:35:51 -08:00
Cory Bennett e35e518368 Updated Changelog 2015-11-23 17:09:17 -08:00
Cory Bennett 159d142f37 jira edit should not require one arguemnt (allow for --query) 2015-11-23 17:08:40 -08:00
7 changed files with 290 additions and 50 deletions
+30
View File
@@ -1,5 +1,35 @@
# Changelog
## 0.0.20 - 2016-01-21
* [issue [#28](https://github.com/Netflix-Skunkworks/go-jira/issues/28)] check to make sure we got back issuetypes for create metadata [Cory Bennett] [[ee0e780](https://github.com/Netflix-Skunkworks/go-jira/commit/ee0e780)]
* Add insecure option for TLS endpoints [Brian Lalor] [[6a88bb9](https://github.com/Netflix-Skunkworks/go-jira/commit/6a88bb9)]
* Correct naming of parameter: set/add/remove are actions. [Mike Pountney] [[303784f](https://github.com/Netflix-Skunkworks/go-jira/commit/303784f)]
* Tweak CmdLabels args so that magic happens with CLI [Mike Pountney] [[40a7c65](https://github.com/Netflix-Skunkworks/go-jira/commit/40a7c65)]
* Expose ViewTicket as per FindIssues [Mike Pountney] [[8977f3d](https://github.com/Netflix-Skunkworks/go-jira/commit/8977f3d)]
* Add exposed versions of getTemplate and runTemplate [Mike Pountney] [[da6cbd5](https://github.com/Netflix-Skunkworks/go-jira/commit/da6cbd5)]
* Add 'labels' command to set/add/remove labels [Mike Pountney] [[230b52d](https://github.com/Netflix-Skunkworks/go-jira/commit/230b52d)]
* Add a 'join' func to the template engine [Mike Pountney] [[a7820fe](https://github.com/Netflix-Skunkworks/go-jira/commit/a7820fe)]
* make "jira" golang package, move code from jira/cli to root, move jira/main.go to main/main.go [Cory Bennett] [[7268b9e](https://github.com/Netflix-Skunkworks/go-jira/commit/7268b9e)]
## 0.0.19 - 2015-12-09
* fix jira trans TRANS ISSUE (case sensitivity issue), also go fmt [Cory Bennett] [[3c30f3b](https://github.com/Netflix-Skunkworks/go-jira/commit/3c30f3b)]
## 0.0.18 - 2015-12-03
* need to default "quiet" to false [Cory Bennett] [[4f4a89b](https://github.com/Netflix-Skunkworks/go-jira/commit/4f4a89b)]
## 0.0.17 - 2015-12-03
* add --quiet command to not print the OK .. add --saveFile option to print the issue/link to a file on create command [Cory Bennett] [[c9ac162](https://github.com/Netflix-Skunkworks/go-jira/commit/c9ac162)]
* fix overrides [Cory Bennett] [[eaddfe6](https://github.com/Netflix-Skunkworks/go-jira/commit/eaddfe6)]
* add abstract request wrapper to allow you to access/process random apis supported by Jira but not yet supported by go-jira [Cory Bennett] [[90ef56a](https://github.com/Netflix-Skunkworks/go-jira/commit/90ef56a)]
## 0.0.16 - 2015-11-23
* jira edit should not require one arguemnt (allow for --query) [Cory Bennett] [[a1eb4a1](https://github.com/Netflix-Skunkworks/go-jira/commit/a1eb4a1)]
## 0.0.15 - 2015-11-23
* [[#17](https://github.com/Netflix-Skunkworks/go-jira/issues/17)] print usage on missing arguments [Cory Bennett] [[fd2a2fe](https://github.com/Netflix-Skunkworks/go-jira/commit/fd2a2fe)]
+28 -13
View File
@@ -14,20 +14,32 @@ PLATFORMS= \
$(NULL)
DIST=$(shell pwd)/dist
export GOPATH=$(shell pwd)
GOBIN ?= $(shell pwd)/bin
GOBIN ?= $(shell pwd)
NAME=jira
BIN ?= $(GOBIN)/$(NAME)
CURVER ?= $(shell [ -d .git ] && git describe --abbrev=0 --tags || grep ^\#\# CHANGELOG.md | awk '{print $$2; exit}')
LDFLAGS:=-X main.buildVersion=$(CURVER)
LDFLAGS:=-X jira.VERSION=$(patsubst v%,%,$(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
else
GOBUILD=go build -v -ldflags "$(LDFLAGS) -s"
endif
build: src/github.com/Netflix-Skunkworks/go-jira
go build -ldflags "$(LDFLAGS)" -o $(GOBIN)/$(NAME) jira/main.go
$(GOBUILD) -o $(BIN) main/main.go
src/%:
mkdir -p $(@D)
test -L $@ || ln -sf ../../.. $@
go get -v $*/jira
go get -v $* $*/main
cross-setup:
for p in $(PLATFORMS); do \
@@ -40,33 +52,36 @@ all:
mkdir -p $(DIST); \
for p in $(PLATFORMS); do \
echo "Building for $$p"; \
GOOS=$${p/-*/} GOARCH=$${p/*-/} go build -v -ldflags "$(LDFLAGS) -s" -o $(DIST)/$(NAME)-$$p jira/main.go ; \
${MAKE} build GOOS=$${p/-*/} GOARCH=$${p/*-/} BIN=$(DIST)/$(NAME)-$$p; \
done
fmt:
gofmt -s -w jira
gofmt -s -w main/*.go *.go
install:
export GOBIN=~/bin && ${MAKE} build
${MAKE} GOBIN=~/bin build
NEWVER ?= $(shell echo $(CURVER) | awk -F. '{print $$1"."$$2"."$$3+1}')
TODAY := $(shell date +%Y-%m-%d)
changes:
@git log --pretty=format:"* %s [%cn] [%h]" --no-merges ^$(CURVER) HEAD jira | grep -v gofmt | grep -v "bump version"
@git log --pretty=format:"* %s [%cn] [%h]" --no-merges ^$(CURVER) HEAD main/*.go *.go | grep -vE 'gofmt|go fmt'
update-changelog:
update-changelog:
@echo "# Changelog" > CHANGELOG.md.new; \
echo >> CHANGELOG.md.new; \
echo "## $(NEWVER) - $(TODAY)" >> CHANGELOG.md.new; \
echo >> CHANGELOG.md.new; \
$(MAKE) changes | \
$(MAKE) --no-print-directory --silent changes | \
perl -pe 's{\[([a-f0-9]+)\]}{[[$$1](https://github.com/Netflix-Skunkworks/go-jira/commit/$$1)]}g' | \
perl -pe 's{\#(\d+)}{[#$$1](https://github.com/Netflix-Skunkworks/go-jira/issues/$$1)}g' >> CHANGELOG.md.new; \
tail +2 CHANGELOG.md >> CHANGELOG.md.new; \
tail -n +2 CHANGELOG.md >> CHANGELOG.md.new; \
mv CHANGELOG.md.new CHANGELOG.md; \
git commit -m "Updated Changelog" CHANGELOG.md; \
git tag $(NEWVER)
git tag v$(NEWVER)
version:
@echo $(patsubst v%,%,$(CURVER))
clean:
rm -rf pkg dist bin src ./toolkit
rm -rf pkg dist bin src ./$(NAME)
+39 -3
View File
@@ -1,7 +1,8 @@
package cli
package jira
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"github.com/kballard/go-shellquote"
@@ -18,7 +19,10 @@ import (
"time"
)
var log = logging.MustGetLogger("jira.cli")
var (
log = logging.MustGetLogger("jira")
VERSION string
)
type Cli struct {
endpoint *url.URL
@@ -33,15 +37,26 @@ func New(opts map[string]interface{}) *Cli {
endpoint, _ := opts["endpoint"].(string)
url, _ := url.Parse(strings.TrimRight(endpoint, "/"))
transport := &http.Transport{
TLSClientConfig: &tls.Config{},
}
if project, ok := opts["project"].(string); ok {
opts["project"] = strings.ToUpper(project)
}
if insecureSkipVerify, ok := opts["insecure"].(bool); ok {
transport.TLSClientConfig.InsecureSkipVerify = insecureSkipVerify
}
cli := &Cli{
endpoint: url,
opts: opts,
cookieFile: fmt.Sprintf("%s/.jira.d/cookies.js", homedir),
ua: &http.Client{Jar: cookieJar},
ua: &http.Client{
Jar: cookieJar,
Transport: transport,
},
}
cli.ua.Jar.SetCookies(url, cli.loadCookies())
@@ -174,6 +189,10 @@ func (c *Cli) makeRequest(req *http.Request) (resp *http.Response, err error) {
return resp, nil
}
func (c *Cli) GetTemplate(name string) string {
return c.getTemplate(name)
}
func (c *Cli) getTemplate(name string) string {
if override, ok := c.opts["template"].(string); ok {
if _, err := os.Stat(override); err == nil {
@@ -354,6 +373,23 @@ func (c *Cli) Browse(issue string) error {
return nil
}
func (c *Cli) SaveData(data interface{}) error {
if val, ok := c.opts["saveFile"].(string); ok && val != "" {
yamlWrite(val, data)
}
return nil
}
func (c *Cli) ViewIssue(issue string) (interface{}, error) {
uri := fmt.Sprintf("%s/rest/api/2/issue/%s", c.endpoint, issue)
data, err := responseToJson(c.get(uri))
if err != nil {
return nil, err
} else {
return data, nil
}
}
func (c *Cli) FindIssues() (interface{}, error) {
var query string
var ok bool
+126 -16
View File
@@ -1,4 +1,4 @@
package cli
package jira
import (
"bytes"
@@ -80,12 +80,10 @@ func (c *Cli) CmdList() error {
func (c *Cli) CmdView(issue string) error {
log.Debug("view called")
c.Browse(issue)
uri := fmt.Sprintf("%s/rest/api/2/issue/%s", c.endpoint, issue)
data, err := responseToJson(c.get(uri))
data, err := c.ViewIssue(issue)
if err != nil {
return err
}
return runTemplate(c.getTemplate("view"), data, nil)
}
@@ -126,7 +124,9 @@ func (c *Cli) CmdEdit(issue string) error {
if resp.StatusCode == 204 {
c.Browse(issueData["key"].(string))
fmt.Printf("OK %s %s/browse/%s\n", issueData["key"], c.endpoint, issueData["key"])
if !c.opts["quiet"].(bool) {
fmt.Printf("OK %s %s/browse/%s\n", issueData["key"], c.endpoint, issueData["key"])
}
return nil
} else {
logBuffer := bytes.NewBuffer(make([]byte, 0))
@@ -233,6 +233,11 @@ func (c *Cli) CmdCreate() error {
return err
}
if val, ok = val.([]interface{})[0].(map[string]interface{})["issuetypes"]; ok {
if len(val.([]interface{})) == 0 {
err = fmt.Errorf("Project '%s' does not support issuetype '%s'. Unable to create issue.", project, issuetype)
log.Error("%s", err)
return err
}
issueData["meta"] = val.([]interface{})[0]
}
}
@@ -260,10 +265,16 @@ func (c *Cli) CmdCreate() error {
if json, err := responseToJson(resp, nil); err != nil {
return err
} else {
key := json.(map[string]interface{})["key"]
c.Browse(key.(string))
fmt.Printf("OK %s %s/browse/%s\n", key, c.endpoint, key)
key := json.(map[string]interface{})["key"].(string)
link := fmt.Sprintf("%s/browse/%s", c.endpoint, key)
c.Browse(key)
c.SaveData(map[string]string{
"issue": key,
"link": link,
})
if !c.opts["quiet"].(bool) {
fmt.Printf("OK %s %s\n", key, link)
}
}
return nil
} else {
@@ -318,7 +329,9 @@ func (c *Cli) CmdBlocks(blocker string, issue string) error {
}
if resp.StatusCode == 201 {
c.Browse(issue)
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
if !c.opts["quiet"].(bool) {
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
}
} else {
logBuffer := bytes.NewBuffer(make([]byte, 0))
resp.Write(logBuffer)
@@ -359,7 +372,9 @@ func (c *Cli) CmdDups(duplicate string, issue string) error {
}
if resp.StatusCode == 201 {
c.Browse(issue)
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
if !c.opts["quiet"].(bool) {
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
}
} else {
logBuffer := bytes.NewBuffer(make([]byte, 0))
resp.Write(logBuffer)
@@ -391,7 +406,9 @@ func (c *Cli) CmdWatch(issue string) error {
}
if resp.StatusCode == 204 {
c.Browse(issue)
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
if !c.opts["quiet"].(bool) {
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
}
} else {
logBuffer := bytes.NewBuffer(make([]byte, 0))
resp.Write(logBuffer)
@@ -418,7 +435,7 @@ func (c *Cli) CmdTransition(issue string, trans string) error {
name := transition.(map[string]interface{})["name"].(string)
id := transition.(map[string]interface{})["id"].(string)
found = append(found, name)
if strings.Contains(strings.ToLower(name), trans) {
if strings.Contains(strings.ToLower(name), strings.ToLower(trans)) {
transName = name
transId = id
transMeta = transition.(map[string]interface{})
@@ -445,7 +462,9 @@ func (c *Cli) CmdTransition(issue string, trans string) error {
}
if resp.StatusCode == 204 {
c.Browse(issue)
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
if !c.opts["quiet"].(bool) {
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
}
} else {
logBuffer := bytes.NewBuffer(make([]byte, 0))
resp.Write(logBuffer)
@@ -496,7 +515,9 @@ func (c *Cli) CmdComment(issue string) error {
if resp.StatusCode == 201 {
c.Browse(issue)
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
if !c.opts["quiet"].(bool) {
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
}
return nil
} else {
logBuffer := bytes.NewBuffer(make([]byte, 0))
@@ -526,6 +547,71 @@ func (c *Cli) CmdComment(issue string) error {
return nil
}
func (c *Cli) CmdLabels(action string, issue string, labels []string) error {
log.Debug("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 {
log.Debug("JSON: %s", json)
uri := fmt.Sprintf("%s/rest/api/2/issue/%s", c.endpoint, issue)
if c.getOptBool("dryrun", false) {
log.Debug("PUT: %s", json)
log.Debug("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.opts["quiet"].(bool) {
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
}
return nil
} else {
logBuffer := bytes.NewBuffer(make([]byte, 0))
resp.Write(logBuffer)
err := fmt.Errorf("Unexpected Response From PUT")
log.Error("%s:\n%s", err, logBuffer)
return err
}
}
var labels_json string
var err error
if action == "set" {
labelsActions := make([]map[string][]string, 1)
labelsActions[0] = map[string][]string{
"set": labels,
}
labels_json, err = jsonEncode(map[string]interface{}{
"labels": labelsActions,
})
} else {
labelsActions := make([]map[string]string, len(labels))
for i, label := range labels {
labelActionMap := map[string]string{
action: label,
}
labelsActions[i] = labelActionMap
}
labels_json, err = jsonEncode(map[string]interface{}{
"labels": labelsActions,
})
}
if err != nil {
return err
}
json := fmt.Sprintf("{ \"update\": %s }", labels_json)
return handlePut(json)
}
func (c *Cli) CmdAssign(issue string, user string) error {
log.Debug("assign called")
@@ -548,7 +634,9 @@ func (c *Cli) CmdAssign(issue string, user string) error {
}
if resp.StatusCode == 204 {
c.Browse(issue)
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
if !c.opts["quiet"].(bool) {
fmt.Printf("OK %s %s/browse/%s\n", issue, c.endpoint, issue)
}
} else {
logBuffer := bytes.NewBuffer(make([]byte, 0))
resp.Write(logBuffer)
@@ -585,3 +673,25 @@ func (c *Cli) CmdExportTemplates() error {
}
return nil
}
func (c *Cli) CmdRequest(uri, content string) (err error) {
log.Debug("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)
}
+37 -15
View File
@@ -3,7 +3,7 @@ package main
import (
"bytes"
"fmt"
"github.com/Netflix-Skunkworks/go-jira/jira/cli"
"github.com/Netflix-Skunkworks/go-jira"
"github.com/coryb/optigo"
"github.com/op/go-logging"
"gopkg.in/coryb/yaml.v2"
@@ -14,10 +14,9 @@ import (
)
var (
log = logging.MustGetLogger("jira")
log = logging.MustGetLogger("jira")
format = "%{color}%{time:2006-01-02T15:04:05.000Z07:00} %{level:-5s} [%{shortfile}]%{color:reset} %{message}"
buildVersion string
)
)
func main() {
logBackend := logging.NewLogBackend(os.Stderr, "", 0)
@@ -66,6 +65,7 @@ Usage:
jira start ISSUE [--edit] <Edit Options>
jira stop ISSUE [--edit] <Edit Options>
jira comment ISSUE [--noedit] <Edit Options>
jira (set,add,remove) labels ISSUE [LABEL] ...
jira take ISSUE
jira (assign|give) ISSUE ASSIGNEE
jira fields
@@ -78,11 +78,13 @@ Usage:
jira export-templates [-d DIR] [-t template]
jira (b|browse) ISSUE
jira login
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)
@@ -136,6 +138,8 @@ Command Options:
"start": "start",
"stop": "stop",
"comment": "comment",
"label": "labels",
"labels": "labels",
"take": "take",
"assign": "assign",
"give": "assign",
@@ -149,6 +153,8 @@ Command Options:
"export-templates": "export-templates",
"browse": "browse",
"login": "login",
"req": "request",
"request": "request",
}
defaults := map[string]interface{}{
@@ -157,11 +163,11 @@ Command Options:
"directory": fmt.Sprintf("%s/.jira.d/templates", home),
"sort": defaultSort,
"max_results": defaultMaxResults,
"method": "GET",
"quiet": false,
}
opts := make(map[string]interface{})
overrides := make(map[string]string)
setopt := func(name string, value interface{}) {
opts[name] = value
}
@@ -169,7 +175,7 @@ Command Options:
op := optigo.NewDirectAssignParser(map[string]interface{}{
"h|help": usage,
"version": func() {
fmt.Println(fmt.Sprintf("version: %s", buildVersion))
fmt.Println(fmt.Sprintf("version: %s", jira.VERSION))
os.Exit(0)
},
"v|verbose+": func() {
@@ -180,6 +186,7 @@ Command Options:
"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,
@@ -191,11 +198,14 @@ Command Options:
"f|queryfields=s": setopt,
"s|sort=s": setopt,
"l|limit|max_results=i": setopt,
"o|override=s%": &overrides,
"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,
"Q|quiet": setopt,
})
if err := op.ProcessAll(os.Args[1:]); err != nil {
@@ -203,7 +213,6 @@ Command Options:
usage(false)
}
args := op.Args
opts["overrides"] = overrides
var command string
if len(args) > 0 {
@@ -212,6 +221,7 @@ Command Options:
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:]...)
@@ -253,7 +263,7 @@ Command Options:
os.Exit(1)
}
c := cli.New(opts)
c := jira.New(opts)
log.Debug("opts: %s", opts)
@@ -291,7 +301,6 @@ Command Options:
case "list":
err = c.CmdList()
case "edit":
requireArgs(1)
setEditing(true)
if len(args) > 0 {
err = c.CmdEdit(args[0])
@@ -302,7 +311,7 @@ Command Options:
for _, issue := range issues {
if err = c.CmdEdit(issue.(map[string]interface{})["key"].(string)); err != nil {
switch err.(type) {
case cli.NoChangesFound:
case jira.NoChangesFound:
log.Warning("No Changes found: %s", err)
err = nil
continue
@@ -345,7 +354,7 @@ Command Options:
case "transition":
requireArgs(2)
setEditing(true)
err = c.CmdTransition(args[0], args[1])
err = c.CmdTransition(args[1], args[0])
case "close":
requireArgs(1)
setEditing(false)
@@ -374,6 +383,12 @@ Command Options:
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 "take":
requireArgs(1)
err = c.CmdAssign(args[0], opts["user"].(string))
@@ -389,6 +404,13 @@ Command Options:
case "view":
requireArgs(1)
err = c.CmdView(args[0])
case "request":
requireArgs(1)
data := ""
if len(args) > 1 {
data = args[1]
}
err = c.CmdRequest(args[0], data)
default:
log.Error("Unknown command %s", command)
os.Exit(1)
@@ -430,9 +452,9 @@ func populateEnv(opts map[string]interface{}) {
func loadConfigs(opts map[string]interface{}) {
populateEnv(opts)
paths := cli.FindParentPaths(".jira.d/config.yml")
paths := jira.FindParentPaths(".jira.d/config.yml")
// prepend
paths = append([]string{"/etc/jira-cli.yml"}, paths...)
paths = append([]string{"/etc/go-jira.yml"}, paths...)
// iterate paths in reverse
for i := len(paths) - 1; i >= 0; i-- {
+2 -1
View File
@@ -1,4 +1,4 @@
package cli
package jira
var all_templates = map[string]string{
"debug": default_debug_template,
@@ -16,6 +16,7 @@ var all_templates = map[string]string{
"create": default_create_template,
"comment": default_comment_template,
"transition": default_transition_template,
"request": default_debug_template,
}
const default_debug_template = "{{ . | toJson}}\n"
+28 -2
View File
@@ -1,4 +1,4 @@
package cli
package jira
import (
"bufio"
@@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"github.com/mgutz/ansi"
"gopkg.in/coryb/yaml.v2"
"io"
"io/ioutil"
"net/http"
@@ -108,8 +109,11 @@ func dateFormat(format string, content string) (string, error) {
}
}
func runTemplate(templateContent string, data interface{}, out io.Writer) error {
func RunTemplate(templateContent string, data interface{}, out io.Writer) error {
return runTemplate(templateContent, data, out)
}
func runTemplate(templateContent string, data interface{}, out io.Writer) error {
if out == nil {
out = os.Stdout
}
@@ -160,6 +164,13 @@ func runTemplate(templateContent string, data interface{}, out io.Writer) error
"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
@@ -245,6 +256,21 @@ func jsonWrite(file string, data interface{}) {
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.Error("Failed to open %s: %s", file, err)
os.Exit(1)
}
if out, err := yaml.Marshal(data); err != nil {
log.Error("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 {