Compare commits

..

35 Commits

Author SHA1 Message Date
Cory Bennett 9597f9b56f fix transition comman 2017-10-28 14:46:50 -07:00
Cory Bennett 66c069e3b4 version bump 2017-10-28 14:26:38 -07:00
Cory Bennett 14189c197b Updated Changelog 2017-10-28 14:26:38 -07:00
Cory Bennett c9b5054cde fix default values to load after parsing configs 2017-10-28 14:23:27 -07:00
coryb f23b1c4370 Merge pull request #126 from schorsch3000/master
Add regexReplace template function
2017-10-28 14:07:25 -07:00
Cory Bennett 6c742dad0a ignore "composite literal uses unkeyed fields" vet checks 2017-10-28 12:42:48 -07:00
Cory Bennett 3966defc53 add test to make sure IssueType.Fields does not disappear on regeneration 2017-10-28 12:28:25 -07:00
Cory Bennett 794f8dd259 Merge branch 'thedillonb-fix-missing-fields' 2017-10-28 12:21:37 -07:00
Cory Bennett 41d1a7c9a1 add tests for validating changes to auto-generated jiradata files 2017-10-28 12:21:07 -07:00
Brian Lachniet 90007771bf Fix typo in 'logout' command help 2017-10-28 12:21:07 -07:00
Mark Harrison 7bfa241547 Add URL escaping to an additional issuetype call
In #34 a fix was made to escape the issue type to support issue types
with spaces in. This is an additional place where the issue type needs
escaping, otherwise you get 400 Bad Request when trying to create an
issue for an issuetype that has a space in.
2017-10-28 12:21:07 -07:00
Ivan Andrus e6600cf1a5 Add --resolution option 2017-10-28 12:21:07 -07:00
Cory Bennett 2e608207cb add tests for validating changes to auto-generated jiradata files 2017-10-28 12:19:36 -07:00
coryb bc1b994019 Merge pull request #129 from blachniet/logout-help-typo-fix
Fix typo in 'logout' command help
2017-10-28 09:21:15 -07:00
Brian Lachniet fd399d817e Fix typo in 'logout' command help 2017-10-28 11:04:02 -04:00
coryb f7b587ee91 Merge pull request #124 from gvol/master
Allow overriding resolution
2017-10-27 12:08:36 -07:00
coryb de69971c1c Merge pull request #128 from mivok/escape-issuetype
Add URL escaping to an additional issuetype call
2017-10-26 13:53:08 -07:00
Mark Harrison 2f9b8bb5c1 Add URL escaping to an additional issuetype call
In #34 a fix was made to escape the issue type to support issue types
with spaces in. This is an additional place where the issue type needs
escaping, otherwise you get 400 Bad Request when trying to create an
issue for an issuetype that has a space in.
2017-10-26 16:28:41 -04:00
Dillon Buchanan 093c510ca2 Create Metadata Not Populated Correctly
Fixes #123
2017-10-25 14:28:49 -04:00
Dirk Heilig d3e294e1ce add regexReplace template function 2017-10-19 14:58:11 +02:00
Ivan Andrus 4ed8edbd19 Add --resolution option 2017-10-13 12:22:12 -06:00
Cory Bennett 28d92eb659 version bump 2017-10-04 10:58:50 -04:00
Cory Bennett d16db04e58 Updated Changelog 2017-10-04 10:58:49 -04:00
Cory Bennett 4d74554300 add {{env.VARNAME}} template support to allow use of env vars 2017-10-03 18:47:33 -04:00
Cory Bennett 172793ea69 version bump 2017-09-26 22:50:54 -07:00
Cory Bennett dc504de271 Updated Changelog 2017-09-26 22:50:54 -07:00
Cory Bennett 986cc78ed5 [#115] fix transition template for description 2017-09-26 22:49:40 -07:00
Cory Bennett 3913726991 update edit command to set queryFields on search to match what is used in template 2017-09-19 00:27:11 -07:00
Cory Bennett 0ba8aa035b fix edit with query loop, allow continuation when not submitting previous issue 2017-09-18 14:45:21 -07:00
Cory Bennett 098eb99ed6 fix edit when priority is not set 2017-09-18 14:45:04 -07:00
Cory Bennett 2ddaed2c29 flatten CommandRegistry list to make it more readable 2017-09-18 14:44:36 -07:00
Cory Bennett 9a62d1a553 tweak format 2017-09-18 00:53:57 -07:00
Cory Bennett 74d7287589 fix formatting 2017-09-18 00:50:49 -07:00
Cory Bennett c6e4b3dc0e add TOC 2017-09-18 00:49:34 -07:00
Cory Bennett 8b5e7b7568 fix usage 2017-09-18 00:47:35 -07:00
21 changed files with 300 additions and 292 deletions
+6 -3
View File
@@ -5,12 +5,15 @@ before_install:
language: go
go_import_path: gopkg.in/Netflix-Skunkworks/go-jira.v1
go:
- 1.8
- 1.9
matrix:
fast_finish: true
script:
- make vet
- go get -t -v ./...
- go test ./...
- go vet -composites=false ./...
- make
- make prove 2>&1
- make prove 2>&1
+23
View File
@@ -1,5 +1,28 @@
# Changelog
## 1.0.13 - 2017-10-28
* fix default values to load after parsing configs [Cory Bennett] [[c9b5054](https://github.com/Netflix-Skunkworks/go-jira/commit/c9b5054)]
* add test to make sure IssueType.Fields does not disappear on regeneration [Cory Bennett] [[3966def](https://github.com/Netflix-Skunkworks/go-jira/commit/3966def)]
* add tests for validating changes to auto-generated jiradata files [Cory Bennett] [[41d1a7c](https://github.com/Netflix-Skunkworks/go-jira/commit/41d1a7c)]
* Fix typo in 'logout' command help [Cory Bennett] [[9000777](https://github.com/Netflix-Skunkworks/go-jira/commit/9000777)]
* Add URL escaping to an additional issuetype call [Cory Bennett] [[7bfa241](https://github.com/Netflix-Skunkworks/go-jira/commit/7bfa241)]
* Add --resolution option [Cory Bennett] [[e6600cf](https://github.com/Netflix-Skunkworks/go-jira/commit/e6600cf)]
* Create Metadata Not Populated Correctly [Dillon Buchanan] [[093c510](https://github.com/Netflix-Skunkworks/go-jira/commit/093c510)]
* add regexReplace template function [Dirk Heilig] [[d3e294e](https://github.com/Netflix-Skunkworks/go-jira/commit/d3e294e)]
## 1.0.12 - 2017-10-04
* add `{{env.VARNAME}}` template support to allow use of env vars [Cory Bennett] [[4d74554](https://github.com/Netflix-Skunkworks/go-jira/commit/4d74554)]
## 1.0.11 - 2017-09-26
* [[#115](https://github.com/Netflix-Skunkworks/go-jira/issues/115)] fix transition template for description [Cory Bennett] [[986cc78](https://github.com/Netflix-Skunkworks/go-jira/commit/986cc78)]
* update edit command to set queryFields on search to match what is used in template [Cory Bennett] [[3913726](https://github.com/Netflix-Skunkworks/go-jira/commit/3913726)]
* fix edit with query loop, allow continuation when not submitting previous issue [Cory Bennett] [[0ba8aa0](https://github.com/Netflix-Skunkworks/go-jira/commit/0ba8aa0)]
* fix edit when priority is not set [Cory Bennett] [[098eb99](https://github.com/Netflix-Skunkworks/go-jira/commit/098eb99)]
* flatten CommandRegistry list to make it more readable [Cory Bennett] [[2ddaed2](https://github.com/Netflix-Skunkworks/go-jira/commit/2ddaed2)]
## 1.0.10 - 2017-09-18
* clean up usage formatting, print aliases [Cory Bennett] [[9f433ac](https://github.com/Netflix-Skunkworks/go-jira/commit/9f433ac)]
+2 -2
View File
@@ -41,7 +41,7 @@ all:
go get -u github.com/karalabe/xgo
rm -rf dist
mkdir -p dist
xgo --targets="freebsd/amd64,linux/386,linux/amd64,windows/386,windows/amd64,darwin/amd64" -dest ./dist -ldflags="-w -s" ./cmd/jira
xgo --go 1.9.0 --targets="freebsd/amd64,linux/386,linux/amd64,windows/386,windows/amd64,darwin/amd64" -dest ./dist -ldflags="-w -s" ./cmd/jira
install:
${MAKE} GOBIN=$$HOME/bin build
@@ -68,7 +68,7 @@ update-changelog:
release:
perl -pi -e 'undef $$/; s/\n```\nusage.*```//sg' README.md
echo '```' >> README.md
./jira --help >> README.md || true
./jira --help >> README.md 2>&1 || true
echo '```' >> README.md
git diff --exit-code --quiet README.md || git commit -m "Updated Usage" README.md
git commit -m "Updated Changelog" CHANGELOG.md
+99
View File
@@ -3,6 +3,34 @@
[![GoDoc](https://godoc.org/gopkg.in/Netflix-Skunkworks/go-jira.v1?status.svg)](https://godoc.org/gopkg.in/Netflix-Skunkworks/go-jira.v1)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
### Table of Contents
* [Summary](#go-jira)
* [Install](#install)
* [Download](#download)
* [Build](#build)
* [v1 vs v0 changes](#v1-vs-v0-changes)
* [<strong>Golang library import</strong>](#golang-library-import)
* [<strong>Configs per command</strong>](#configs-per-command)
* [<strong>Custom Commands</strong>](#custom-commands)
* [<strong>Incompatible command changes</strong>](#incompatible-command-changes)
* [<strong>Login process change</strong>](#login-process-change)
* [Configuration](#configuration)
* [Dynamic Configuration](#dynamic-configuration)
* [Custom Commands](#custom-commands-1)
* [Commands](#commands)
* [Options](#options)
* [Arguments](#arguments)
* [Script Template](#script-template)
* [Examples](#examples)
* [Editing](#editing)
* [Templates](#templates)
* [Writing/Editing Templates](#writingediting-templates)
* [Authentication](#authentication)
* [keyring password source](#keyring-password-source)
* [pass password source](#pass-password-source)
* [Usage](#usage)
# go-jira
simple command line client for Atlassian's Jira service written in Go
@@ -395,4 +423,75 @@ export GPG_TTY=$(tty)
## Usage
```
usage: jira [<flags>] <command> [<args> ...]
Jira Command Line Interface
Global flags:
--help Show context-sensitive help (also try --help-long and --help-man).
-v, --verbose ... Increase verbosity for debugging
-e, --endpoint=ENDPOINT Base URI to use for Jira
-k, --insecure Disable TLS certificate verification
-Q, --quiet Suppress output to console
--unixproxy=UNIXPROXY Path for a unix-socket proxy
-u, --user=USER Login name used for authentication with Jira service
Commands:
help: Show help.
version: Prints version
acknowledge: Transition issue to acknowledge state
assign: Assign user to issue
attach create: Attach file to issue
attach get: Fetch attachment
attach list: Prints attachment details for issue
attach remove: Delete attachment
backlog: Transition issue to Backlog state
block: Mark issues as blocker
browse: Open issue in browser
close: Transition issue to close state
comment: Add comment to issue
component add: Add component
components: Show components for a project
create: Create issue
createmeta: View 'create' metadata
done: Transition issue to Done state
dup: Mark issues as duplicate
edit: Edit issue details
editmeta: View 'edit' metadata
epic add: Add issues to Epic
epic create: Create Epic
epic list: Prints list of issues for an epic with optional search criteria
epic remove: Remove issues from Epic
export-templates: Export templates for customizations
fields: Prints all fields, both System and Custom
in-progress: Transition issue to Progress state
issuelink: Link two issues
issuelinktypes: Show the issue link types
issuetypes: Show issue types for a project
labels add: Add labels to an issue
labels remove: Remove labels from an issue
labels set: Set labels on an issue
list: Prints list of issues for given search criteria
login: Attempt to login into jira server
logout: Deactivate session with Jira server
rank: Mark issues as blocker
reopen: Transition issue to reopen state
request: Open issue in requestr
resolve: Transition issue to resolve state
start: Transition issue to start state
stop: Transition issue to stop state
subtask: Subtask issue
take: Assign issue to yourself
todo: Transition issue to To Do state
transition: Transition issue to given state
transitions: List valid issue transitions
transmeta: List valid issue transitions
unassign: Unassign an issue
unexport-templates: Remove unmodified exported templates
view: Prints issue details
vote: Vote up/down an issue
watch: Add/Remove watcher to issue
worklog add: Add a worklog to an issue
worklog list: Prints the worklog data for given issue
```
+54 -229
View File
@@ -189,235 +189,60 @@ func main() {
o := oreo.New().WithCookieFile(filepath.Join(jiracli.Homedir(), fig.ConfigDir, "cookies.js"))
registry := []jiracli.CommandRegistry{
jiracli.CommandRegistry{
Command: "acknowledge",
Aliases: []string{"ack"},
Entry: jiracmd.CmdTransitionRegistry("acknowledge"),
},
jiracli.CommandRegistry{
Command: "assign",
Entry: jiracmd.CmdAssignRegistry(),
Aliases: []string{"give"},
},
jiracli.CommandRegistry{
Command: "attach create",
Entry: jiracmd.CmdAttachCreateRegistry(),
},
jiracli.CommandRegistry{
Command: "attach get",
Entry: jiracmd.CmdAttachGetRegistry(),
},
jiracli.CommandRegistry{
Command: "attach list",
Entry: jiracmd.CmdAttachListRegistry(),
Aliases: []string{"ls"},
},
jiracli.CommandRegistry{
Command: "attach remove",
Entry: jiracmd.CmdAttachRemoveRegistry(),
Aliases: []string{"rm"},
},
jiracli.CommandRegistry{
Command: "backlog",
Entry: jiracmd.CmdTransitionRegistry("Backlog"),
},
jiracli.CommandRegistry{
Command: "block",
Entry: jiracmd.CmdBlockRegistry(),
},
jiracli.CommandRegistry{
Command: "browse",
Entry: jiracmd.CmdBrowseRegistry(),
Aliases: []string{"b"},
},
jiracli.CommandRegistry{
Command: "close",
Entry: jiracmd.CmdTransitionRegistry("close"),
},
jiracli.CommandRegistry{
Command: "comment",
Entry: jiracmd.CmdCommentRegistry(),
},
jiracli.CommandRegistry{
Command: "component add",
Entry: jiracmd.CmdComponentAddRegistry(),
},
jiracli.CommandRegistry{
Command: "components",
Entry: jiracmd.CmdComponentsRegistry(),
},
jiracli.CommandRegistry{
Command: "create",
Entry: jiracmd.CmdCreateRegistry(),
},
jiracli.CommandRegistry{
Command: "createmeta",
Entry: jiracmd.CmdCreateMetaRegistry(),
},
jiracli.CommandRegistry{
Command: "done",
Entry: jiracmd.CmdTransitionRegistry("Done"),
},
jiracli.CommandRegistry{
Command: "dup",
Entry: jiracmd.CmdDupRegistry(),
},
jiracli.CommandRegistry{
Command: "edit",
Entry: jiracmd.CmdEditRegistry(),
},
jiracli.CommandRegistry{
Command: "editmeta",
Entry: jiracmd.CmdEditMetaRegistry(),
},
jiracli.CommandRegistry{
Command: "epic add",
Entry: jiracmd.CmdEpicAddRegistry(),
},
jiracli.CommandRegistry{
Command: "epic create",
Entry: jiracmd.CmdEpicCreateRegistry(),
},
jiracli.CommandRegistry{
Command: "epic list",
Entry: jiracmd.CmdEpicListRegistry(),
Aliases: []string{"ls"},
},
jiracli.CommandRegistry{
Command: "epic remove",
Entry: jiracmd.CmdEpicRemoveRegistry(),
Aliases: []string{"rm"},
},
jiracli.CommandRegistry{
Command: "export-templates",
Entry: jiracmd.CmdExportTemplatesRegistry(),
},
jiracli.CommandRegistry{
Command: "fields",
Entry: jiracmd.CmdFieldsRegistry(),
},
jiracli.CommandRegistry{
Command: "in-progress",
Aliases: []string{"prog", "progress"},
Entry: jiracmd.CmdTransitionRegistry("Progress"),
},
jiracli.CommandRegistry{
Command: "issuelink",
Entry: jiracmd.CmdIssueLinkRegistry(),
},
jiracli.CommandRegistry{
Command: "issuelinktypes",
Entry: jiracmd.CmdIssueLinkTypesRegistry(),
},
jiracli.CommandRegistry{
Command: "issuetypes",
Entry: jiracmd.CmdIssueTypesRegistry(),
},
jiracli.CommandRegistry{
Command: "labels add",
Entry: jiracmd.CmdLabelsAddRegistry(),
},
jiracli.CommandRegistry{
Command: "labels remove",
Entry: jiracmd.CmdLabelsRemoveRegistry(),
Aliases: []string{"rm"},
},
jiracli.CommandRegistry{
Command: "labels set",
Entry: jiracmd.CmdLabelsSetRegistry(),
},
jiracli.CommandRegistry{
Command: "list",
Aliases: []string{"ls"},
Entry: jiracmd.CmdListRegistry(),
},
jiracli.CommandRegistry{
Command: "login",
Entry: jiracmd.CmdLoginRegistry(),
},
jiracli.CommandRegistry{
Command: "logout",
Entry: jiracmd.CmdLogoutRegistry(),
},
jiracli.CommandRegistry{
Command: "rank",
Entry: jiracmd.CmdRankRegistry(),
},
jiracli.CommandRegistry{
Command: "reopen",
Entry: jiracmd.CmdTransitionRegistry("reopen"),
},
jiracli.CommandRegistry{
Command: "request",
Entry: jiracmd.CmdRequestRegistry(),
Aliases: []string{"req"},
},
jiracli.CommandRegistry{
Command: "resolve",
Entry: jiracmd.CmdTransitionRegistry("resolve"),
},
jiracli.CommandRegistry{
Command: "start",
Entry: jiracmd.CmdTransitionRegistry("start"),
},
jiracli.CommandRegistry{
Command: "stop",
Entry: jiracmd.CmdTransitionRegistry("stop"),
},
jiracli.CommandRegistry{
Command: "subtask",
Entry: jiracmd.CmdSubtaskRegistry(),
},
jiracli.CommandRegistry{
Command: "take",
Entry: jiracmd.CmdTakeRegistry(),
},
jiracli.CommandRegistry{
Command: "todo",
Entry: jiracmd.CmdTransitionRegistry("To Do"),
},
jiracli.CommandRegistry{
Command: "transition",
Aliases: []string{"trans"},
Entry: jiracmd.CmdTransitionRegistry(""),
},
jiracli.CommandRegistry{
Command: "transitions",
Entry: jiracmd.CmdTransitionsRegistry("transitions"),
},
jiracli.CommandRegistry{
Command: "transmeta",
Entry: jiracmd.CmdTransitionsRegistry("debug"),
},
jiracli.CommandRegistry{
Command: "unassign",
Entry: jiracmd.CmdUnassignRegistry(),
},
jiracli.CommandRegistry{
Command: "unexport-templates",
Entry: jiracmd.CmdUnexportTemplatesRegistry(),
},
jiracli.CommandRegistry{
Command: "view",
Entry: jiracmd.CmdViewRegistry(),
},
jiracli.CommandRegistry{
Command: "vote",
Entry: jiracmd.CmdVoteRegistry(),
},
jiracli.CommandRegistry{
Command: "watch",
Entry: jiracmd.CmdWatchRegistry(),
},
jiracli.CommandRegistry{
Command: "worklog add",
Entry: jiracmd.CmdWorklogAddRegistry(),
},
jiracli.CommandRegistry{
Command: "worklog list",
Entry: jiracmd.CmdWorklogListRegistry(),
Default: true,
},
{Command: "acknowledge", Entry: jiracmd.CmdTransitionRegistry("acknowledge"), Aliases: []string{"ack"}},
{Command: "assign", Entry: jiracmd.CmdAssignRegistry(), Aliases: []string{"give"}},
{Command: "attach create", Entry: jiracmd.CmdAttachCreateRegistry()},
{Command: "attach get", Entry: jiracmd.CmdAttachGetRegistry()},
{Command: "attach list", Entry: jiracmd.CmdAttachListRegistry(), Aliases: []string{"ls"}},
{Command: "attach remove", Entry: jiracmd.CmdAttachRemoveRegistry(), Aliases: []string{"rm"}},
{Command: "backlog", Entry: jiracmd.CmdTransitionRegistry("Backlog")},
{Command: "block", Entry: jiracmd.CmdBlockRegistry()},
{Command: "browse", Entry: jiracmd.CmdBrowseRegistry(), Aliases: []string{"b"}},
{Command: "close", Entry: jiracmd.CmdTransitionRegistry("close")},
{Command: "comment", Entry: jiracmd.CmdCommentRegistry()},
{Command: "component add", Entry: jiracmd.CmdComponentAddRegistry()},
{Command: "components", Entry: jiracmd.CmdComponentsRegistry()},
{Command: "create", Entry: jiracmd.CmdCreateRegistry()},
{Command: "createmeta", Entry: jiracmd.CmdCreateMetaRegistry()},
{Command: "done", Entry: jiracmd.CmdTransitionRegistry("Done")},
{Command: "dup", Entry: jiracmd.CmdDupRegistry()},
{Command: "edit", Entry: jiracmd.CmdEditRegistry()},
{Command: "editmeta", Entry: jiracmd.CmdEditMetaRegistry()},
{Command: "epic add", Entry: jiracmd.CmdEpicAddRegistry()},
{Command: "epic create", Entry: jiracmd.CmdEpicCreateRegistry()},
{Command: "epic list", Entry: jiracmd.CmdEpicListRegistry(), Aliases: []string{"ls"}},
{Command: "epic remove", Entry: jiracmd.CmdEpicRemoveRegistry(), Aliases: []string{"rm"}},
{Command: "export-templates", Entry: jiracmd.CmdExportTemplatesRegistry()},
{Command: "fields", Entry: jiracmd.CmdFieldsRegistry()},
{Command: "in-progress", Entry: jiracmd.CmdTransitionRegistry("Progress"), Aliases: []string{"prog", "progress"}},
{Command: "issuelink", Entry: jiracmd.CmdIssueLinkRegistry()},
{Command: "issuelinktypes", Entry: jiracmd.CmdIssueLinkTypesRegistry()},
{Command: "issuetypes", Entry: jiracmd.CmdIssueTypesRegistry()},
{Command: "labels add", Entry: jiracmd.CmdLabelsAddRegistry()},
{Command: "labels remove", Entry: jiracmd.CmdLabelsRemoveRegistry(), Aliases: []string{"rm"}},
{Command: "labels set", Entry: jiracmd.CmdLabelsSetRegistry()},
{Command: "list", Entry: jiracmd.CmdListRegistry(), Aliases: []string{"ls"}},
{Command: "login", Entry: jiracmd.CmdLoginRegistry()},
{Command: "logout", Entry: jiracmd.CmdLogoutRegistry()},
{Command: "rank", Entry: jiracmd.CmdRankRegistry()},
{Command: "reopen", Entry: jiracmd.CmdTransitionRegistry("reopen")},
{Command: "request", Entry: jiracmd.CmdRequestRegistry(), Aliases: []string{"req"}},
{Command: "resolve", Entry: jiracmd.CmdTransitionRegistry("resolve")},
{Command: "start", Entry: jiracmd.CmdTransitionRegistry("start")},
{Command: "stop", Entry: jiracmd.CmdTransitionRegistry("stop")},
{Command: "subtask", Entry: jiracmd.CmdSubtaskRegistry()},
{Command: "take", Entry: jiracmd.CmdTakeRegistry()},
{Command: "todo", Entry: jiracmd.CmdTransitionRegistry("To Do")},
{Command: "transition", Entry: jiracmd.CmdTransitionRegistry(""), Aliases: []string{"trans"}},
{Command: "transitions", Entry: jiracmd.CmdTransitionsRegistry("transitions")},
{Command: "transmeta", Entry: jiracmd.CmdTransitionsRegistry("debug")},
{Command: "unassign", Entry: jiracmd.CmdUnassignRegistry()},
{Command: "unexport-templates", Entry: jiracmd.CmdUnexportTemplatesRegistry()},
{Command: "view", Entry: jiracmd.CmdViewRegistry()},
{Command: "vote", Entry: jiracmd.CmdVoteRegistry()},
{Command: "watch", Entry: jiracmd.CmdWatchRegistry()},
{Command: "worklog add", Entry: jiracmd.CmdWorklogAddRegistry()},
{Command: "worklog list", Entry: jiracmd.CmdWorklogListRegistry(), Default: true},
}
jiracli.Register(app, o, fig, registry)
+1 -10
View File
@@ -246,7 +246,7 @@ func (j *Jira) GetIssueCreateMetaIssueType(projectKey, issueTypeName string) (*j
}
func GetIssueCreateMetaIssueType(ua HttpClient, endpoint string, projectKey, issueTypeName string) (*jiradata.IssueType, error) {
uri := fmt.Sprintf("%s/rest/api/2/issue/createmeta?projectKeys=%s&issuetypeNames=%s&expand=projects.issuetypes.fields", endpoint, projectKey, issueTypeName)
uri := fmt.Sprintf("%s/rest/api/2/issue/createmeta?projectKeys=%s&issuetypeNames=%s&expand=projects.issuetypes.fields", endpoint, projectKey, url.QueryEscape(issueTypeName))
resp, err := ua.GetJSON(uri)
if err != nil {
return nil, err
@@ -571,15 +571,6 @@ func IssueAttachFile(ua HttpClient, endpoint string, issue, filename string, con
defer resp.Body.Close()
if resp.StatusCode == 200 {
// FIXME move this to a test, and run go tests as part of our regression
if false {
// this is because schema is wrong, defaults to type `int`, so we manually change it
// to `string`. If the jiradata is regenerated we need to manually make the change
// again.
log.Debugf("Assert Attachment.ID is a string, rather than int: %v", &jiradata.Attachment{
ID: jiradata.IntOrString(0),
})
}
results := jiradata.ListOfAttachment{}
return &results, readJSON(resp.Body, &results)
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
var log = logging.MustGetLogger("jira")
const VERSION = "1.0.10"
const VERSION = "1.0.13"
type Jira struct {
Endpoint string `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
+16 -14
View File
@@ -250,15 +250,17 @@ func (o *CommonOptions) editFile(fileName string) (changes bool, err error) {
return false, err
}
var EditLoopAbort = fmt.Errorf("Edit Loop aborted by request")
func EditLoop(opts *CommonOptions, input interface{}, output interface{}, submit func() error) error {
tmpFile, err := tmpTemplate(opts.Template.Value, input)
if err != nil {
return err
}
confirm := func(msg string) (answer bool) {
confirm := func(dflt bool, msg string) (answer bool) {
survey.AskOne(
&survey.Confirm{Message: msg, Default: true},
&survey.Confirm{Message: msg, Default: dflt},
&answer,
nil,
)
@@ -279,14 +281,14 @@ func EditLoop(opts *CommonOptions, input interface{}, output interface{}, submit
changes, err := opts.editFile(tmpFile)
if err != nil {
log.Error(err.Error())
if confirm("Editor reported an error, edit again?") {
if confirm(true, "Editor reported an error, edit again?") {
continue
}
panic(Exit{Code: 1})
return EditLoopAbort
}
if !changes {
if !confirm("No changes detected, submit anyway?") {
panic(Exit{Code: 1})
if !confirm(false, "No changes detected, submit anyway?") {
return EditLoopAbort
}
}
}
@@ -319,35 +321,35 @@ func EditLoop(opts *CommonOptions, input interface{}, output interface{}, submit
var raw interface{}
if err := yaml.Unmarshal(data, &raw); err != nil {
log.Error(err.Error())
if confirm("Invalid YAML syntax, edit again?") {
if confirm(true, "Invalid YAML syntax, edit again?") {
continue
}
panic(Exit{Code: 1})
return EditLoopAbort
}
yamlFixup(&raw)
fixedYAML, err := yaml.Marshal(&raw)
if err != nil {
log.Error(err.Error())
if confirm("Invalid YAML syntax, edit again?") {
if confirm(true, "Invalid YAML syntax, edit again?") {
continue
}
panic(Exit{Code: 1})
return EditLoopAbort
}
if err := yaml.Unmarshal(fixedYAML, output); err != nil {
log.Error(err.Error())
if confirm("Invalid YAML syntax, edit again?") {
if confirm(true, "Invalid YAML syntax, edit again?") {
continue
}
panic(Exit{Code: 1})
return EditLoopAbort
}
// submit template
if err := submit(); err != nil {
log.Error(err.Error())
if confirm("Jira reported an error, edit again?") {
if confirm(true, "Jira reported an error, edit again?") {
continue
}
panic(Exit{Code: 1})
return EditLoopAbort
}
break
}
+19 -4
View File
@@ -8,6 +8,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"regexp"
"reflect"
"strconv"
"strings"
@@ -65,6 +66,14 @@ func TemplateProcessor() *template.Template {
"jira": func() string {
return os.Args[0]
},
"env": func() map[string]string {
out := map[string]string{}
for _, env := range os.Environ() {
kv := strings.SplitN(env, "=", 2)
out[kv[0]] = kv[1]
}
return out
},
"toJson": func(content interface{}) (string, error) {
bytes, err := json.MarshalIndent(content, "", " ")
if err != nil {
@@ -123,6 +132,10 @@ func TemplateProcessor() *template.Template {
"color": func(color string) string {
return ansi.ColorCode(color)
},
"regReplace": func(search string, replace string, content string) string {
re := regexp.MustCompile(search)
return re.ReplaceAllString(content, replace)
},
"split": func(sep string, content string) []string {
return strings.Split(content, sep)
},
@@ -326,7 +339,7 @@ comments:
{{end -}}
`
const defaultEditTemplate = `{{/* edit template */ -}}
# issue: {{ .key }}
# issue: {{ .key }} - created: {{ .fields.created | age}} ago
update:
comment:
- add:
@@ -352,9 +365,10 @@ fields:
- 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 }}{{end}}
name: {{ or .overrides.priority .fields.priority.name "" }}{{end}}
description: |~
{{ or .overrides.description (or .fields.description "") | indent 4 }}
{{ or .overrides.description .fields.description "" | indent 4 }}
# votes: {{ .fields.votes.votes }}
# comments:
# {{ range .fields.comment.comments }} - | # {{.author.name}}, {{.created | age}} ago
# {{ or .body "" | indent 4 | comment}}
@@ -473,7 +487,8 @@ fields:
- name: {{ .name }}{{end}}{{end}}
{{- end -}}
{{if .meta.fields.description}}
description: {{or .overrides.description .fields.description }}
description: |~
{{ or .fields.description "" | indent 4 }}
{{- end -}}
{{if .meta.fields.fixVersions -}}
{{if .meta.fields.fixVersions.allowedValues}}
+22 -2
View File
@@ -5,7 +5,7 @@ import (
"github.com/coryb/figtree"
"github.com/coryb/oreo"
"gopkg.in/AlecAivazis/survey.v1"
"gopkg.in/Netflix-Skunkworks/go-jira.v1"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
@@ -36,6 +36,9 @@ func CmdEditRegistry() *jiracli.CommandRegistryEntry {
return CmdEditUsage(cmd, &opts, fig)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
if opts.QueryFields == "" {
opts.QueryFields = "assignee,created,priority,reporter,status,summary,updated,issuetype,comments,description,votes,created,customfield_10110,components"
}
return CmdEdit(o, globals, &opts)
},
}
@@ -106,7 +109,7 @@ func CmdEdit(o *oreo.Client, globals *jiracli.GlobalOptions, opts *EditOptions)
if err != nil {
return err
}
for _, issueData := range results.Issues {
for i, issueData := range results.Issues {
editMeta, err := jira.GetIssueEditMeta(o, globals.Endpoint.Value, issueData.Key)
if err != nil {
return err
@@ -121,6 +124,23 @@ func CmdEdit(o *oreo.Client, globals *jiracli.GlobalOptions, opts *EditOptions)
err = jiracli.EditLoop(&opts.CommonOptions, &input, &issueUpdate, func() error {
return jira.EditIssue(o, globals.Endpoint.Value, issueData.Key, &issueUpdate)
})
if err == jiracli.EditLoopAbort {
if len(results.Issues) > i+1 {
var answer bool
survey.AskOne(
&survey.Confirm{
Message: fmt.Sprintf("Continue to edit next issue %s?", results.Issues[i+1].Key),
Default: true,
},
&answer,
nil,
)
if answer {
continue
}
panic(jiracli.Exit{1})
}
}
if err != nil {
return err
}
+3 -3
View File
@@ -26,6 +26,9 @@ func CmdEpicListRegistry() *jiracli.CommandRegistryEntry {
"Prints list of issues for an epic with optional search criteria",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
return CmdEpicListUsage(cmd, &opts, fig)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
if opts.MaxResults == 0 {
opts.MaxResults = 500
}
@@ -35,9 +38,6 @@ func CmdEpicListRegistry() *jiracli.CommandRegistryEntry {
if opts.Sort == "" {
opts.Sort = "priority asc, key"
}
return CmdEpicListUsage(cmd, &opts, fig)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
return CmdEpicList(o, globals, &opts)
},
}
+3 -3
View File
@@ -23,12 +23,12 @@ func CmdExportTemplatesRegistry() *jiracli.CommandRegistryEntry {
"Export templates for customizations",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
if opts.Dir == "" {
opts.Dir = fmt.Sprintf("%s/.jira.d/templates", jiracli.Homedir())
}
return CmdExportTemplatesUsage(cmd, &opts)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
if opts.Dir == "" {
opts.Dir = fmt.Sprintf("%s/.jira.d/templates", jiracli.Homedir())
}
return CmdExportTemplates(globals, &opts)
},
}
+3 -3
View File
@@ -27,6 +27,9 @@ func CmdListRegistry() *jiracli.CommandRegistryEntry {
"Prints list of issues for given search criteria",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
return CmdListUsage(cmd, &opts, fig)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
if opts.MaxResults == 0 {
opts.MaxResults = 500
}
@@ -36,9 +39,6 @@ func CmdListRegistry() *jiracli.CommandRegistryEntry {
if opts.Sort == "" {
opts.Sort = "priority asc, key"
}
return CmdListUsage(cmd, &opts, fig)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
return CmdList(o, globals, &opts)
},
}
+1 -1
View File
@@ -14,7 +14,7 @@ import (
func CmdLogoutRegistry() *jiracli.CommandRegistryEntry {
opts := jiracli.CommonOptions{}
return &jiracli.CommandRegistryEntry{
"Deactivate sesssion with Jira server",
"Deactivate session with Jira server",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
return nil
+3 -3
View File
@@ -32,14 +32,14 @@ func CmdRequestRegistry() *jiracli.CommandRegistryEntry {
"Open issue in requestr",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
if opts.Method == "" {
opts.Method = "GET"
}
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
jiracli.GJsonQueryUsage(cmd, &opts.CommonOptions)
return CmdRequestUsage(cmd, &opts)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
if opts.Method == "" {
opts.Method = "GET"
}
return CmdRequest(o, globals, &opts)
},
}
+3 -3
View File
@@ -33,12 +33,12 @@ func CmdSubtaskRegistry() *jiracli.CommandRegistryEntry {
"Subtask issue",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
if opts.IssueType == "" {
opts.IssueType = "Sub-task"
}
return CmdSubtaskUsage(cmd, &opts)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
if opts.IssueType == "" {
opts.IssueType = "Sub-task"
}
return CmdSubtask(o, globals, &opts)
},
}
+1
View File
@@ -63,6 +63,7 @@ func CmdTransitionUsage(cmd *kingpin.CmdClause, opts *TransitionOptions) error {
cmd.Arg("TRANSITION", "State to transition issue to").Required().StringVar(&opts.Transition)
}
cmd.Arg("ISSUE", "issue to transition").Required().StringVar(&opts.Issue)
cmd.Flag("resolution", "Set resolution on transition").StringVar(&opts.Resolution)
return nil
}
+3 -4
View File
@@ -20,13 +20,12 @@ func CmdUnexportTemplatesRegistry() *jiracli.CommandRegistryEntry {
"Remove unmodified exported templates",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
if opts.Dir != "" {
opts.Dir = fmt.Sprintf("%s/.jira.d/templates", jiracli.Homedir())
}
return CmdExportTemplatesUsage(cmd, &opts)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
if opts.Dir != "" {
opts.Dir = fmt.Sprintf("%s/.jira.d/templates", jiracli.Homedir())
}
return CmdUnexportTemplates(globals, &opts)
},
}
+15
View File
@@ -0,0 +1,15 @@
package jiradata
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestAttachmentID(t *testing.T) {
// this is because schema is wrong, defaults to type `int`, so we manually change it
// to `string`. If the jiradata is regenerated we need to manually make the change
// again to include:
// ID IntOrString `json:"id,omitempty" yaml:"id,omitempty"`
assert.IsType(t, IntOrString(0), Attachment{}.ID)
}
+8 -7
View File
@@ -46,11 +46,12 @@ package jiradata
// }
// }
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"`
AvatarID int `json:"avatarId,omitempty" yaml:"avatarId,omitempty"`
Description string `json:"description,omitempty" yaml:"description,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"`
}
+14
View File
@@ -0,0 +1,14 @@
package jiradata
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIssueTypeFields(t *testing.T) {
// this is because schema is wrong, missing the 'Fields' arguments, so we manually add it.
// If the jiradata is regenerated we need to manually make the change again to include:
// Fields FieldMetaMap `json:"fields,omitempty" yaml:"fields,omitempty"`
assert.IsType(t, FieldMetaMap{}, IssueType{}.Fields)
}