Compare commits

..

74 Commits

Author SHA1 Message Date
Cory Bennett 445f8f1f84 Updated Changelog 2017-04-24 11:06:39 -07:00
Cory Bennett 485f73181c revert update 2017-04-24 11:06:31 -07:00
Cory Bennett 4d321ec202 work around github.com/tmc/keyring compile error for windows 2017-04-24 10:50:30 -07:00
Cory Bennett d7bce222b6 Updated Changelog 2017-04-24 10:30:33 -07:00
coryb f231f55d74 Merge pull request #78 from davidreuss/generic-issuelink
Added generic issuelink command
2017-04-24 09:10:31 -07:00
coryb 28242c9c7e Merge pull request #77 from davidreuss/fix-start-parameter-for-pagination
Added --start parameter for pagination on results
2017-04-24 09:07:05 -07:00
David Reuss 05951f1c0d Added generic issuelink command
This allows adding generic links, and could replace 'blocks', and 'dups'
command, since it's pretty much just a copy/paste job.

Usage will be something like:

$ jira issuelink $INWARDISSUE "Relates" OUTWARDISSUE

Pulling the list of the names, for your issuelinktypes

$ jira issuelinktypes | jq '.issueLinkTypes | map(.name)'
[
  "Blocks",
  "Bonfire testing",
  "Clones",
  "Deprecates",
  "Duplicate",
  "Relates",
  "Risks"
]
2017-04-24 12:45:24 +02:00
David Reuss f47563048b Added --start parameter for pagination on results 2017-04-24 11:33:17 +02:00
Cory Bennett cd9976ae4e Updated Changelog 2017-03-22 22:25:25 -07:00
coryb f3aa2f4c1a Merge pull request #74 from clausb/BrowseOnWindows
Implement "browse" subcommand on Windows
2017-03-22 22:24:50 -07:00
Claus Brod f6230ca8c6 Implement "browse" subcommand on Windows 2017-03-22 22:36:21 +01:00
Cory Bennett 412174f8a9 Updated Changelog 2017-02-26 22:58:28 -08:00
Cory Bennett 52085417e6 [#69] add subtask command 2017-02-26 22:38:47 -08:00
Cory Bennett 7a2490c0e6 Updated Changelog 2017-02-08 08:45:42 -08:00
Cory Bennett 437532ae89 minor tweak to 'all' target 2017-02-08 08:45:09 -08:00
coryb 69b565eeaa Merge pull request #65 from mlbright/patch-1
Update README.md
2017-01-24 22:26:17 -08:00
Martin-Louis Bright cc393a3498 Update README.md 2017-01-24 21:35:20 -05:00
coryb c6ba4c681b Merge pull request #64 from astrostl/patch-2
Noting implied usage for the keyring provider
2017-01-05 14:55:15 -08:00
Cory Bennett 63bc2ae15a Merge branch 'master' of github.com:Netflix-Skunkworks/go-jira 2017-01-05 14:54:09 -08:00
Cory Bennett 7d6a5d143d fix random sort ordering in "watchers" response 2017-01-05 14:53:44 -08:00
Justin Honold 0ca0f09aa8 Noting implied usage for the keyring provider 2017-01-05 15:06:25 -06:00
coryb 75242a5204 Merge pull request #62 from astrostl/patch-1
Doc tweak: add info for setting username
2017-01-05 12:55:39 -08:00
Justin Honold e6faa4eab1 Doc tweak: add info for setting username
Couple sentences of cleanup
2017-01-05 14:41:08 -06:00
Cory Bennett 9b53a617a7 update .bashrc for GPG 2016-12-21 17:46:22 -08:00
Cory Bennett d5eed3a635 set GPG_TTY in .bashrc 2016-12-19 16:07:33 -08:00
Cory Bennett 4017339b56 fix typos 2016-12-18 22:41:13 -08:00
Cory Bennett a40b17deed update docs for authentication 2016-12-18 22:04:25 -08:00
Cory Bennett 33807cbbec run full test suite now 2016-12-18 15:56:53 -08:00
Cory Bennett 989c072b94 force password in case password already exists 2016-12-18 15:53:00 -08:00
Cory Bennett d187eee826 fix gpg file permissions after checkout 2016-12-18 15:43:55 -08:00
Cory Bennett 6d34ef3f28 debugging travis 2016-12-18 15:37:23 -08:00
Cory Bennett 7852883202 tweak how prove is run 2016-12-18 15:15:46 -08:00
Cory Bennett cb70941aad refactor password source, allow for "pass" to be used, update tests to use password-source: pass 2016-12-18 15:07:17 -08:00
Cory Bennett 24fd8f6fad update changelog 2016-12-18 09:49:20 -08:00
Cory Bennett ba08d51437 Updated Changelog 2016-12-18 09:48:21 -08:00
Cory Bennett 09d718b5d8 stabbing in the dark 2016-12-17 19:57:45 -08:00
Cory Bennett e3e84d7aa0 only test jira cloud service 2016-12-17 18:52:07 -08:00
Cory Bennett a4f1d754e4 debugging tests 2016-12-17 18:50:20 -08:00
Cory Bennett 683541de1e add verbose test 2016-12-17 18:40:21 -08:00
Cory Bennett e0fd6bab66 only warn about needing login when not already running the login command 2016-12-17 18:32:47 -08:00
Cory Bennett 5ca096ab6e use go-jira.atlassian.net for testing via travis 2016-12-17 17:25:11 -08:00
Cory Bennett ac515e2743 Merge branch 'master' of github.com:Netflix-Skunkworks/go-jira 2016-12-17 14:13:39 -08:00
Cory Bennett be4a5f9156 update for isolated xgo build 2016-12-17 14:13:00 -08:00
coryb 7f10eaa667 Merge pull request #61 from sylus/feature-proxy
fix(http): Add proxy transport
2016-12-17 14:06:45 -08:00
William Hearn b326623ed2 fix(http): Add proxy transport 2016-12-17 16:50:34 -05:00
William Hearn 72c78c6c1c fix(http): Add proxy transport 2016-12-17 14:13:20 -05:00
coryb 5df5a39405 Merge pull request #60 from facundoolano/patch-1
fix typo in readme
2016-12-15 14:00:31 -08:00
Facundo Olano bd54ecc4f6 fix typo in readme 2016-12-15 15:18:11 -03:00
Cory Bennett 073e0bdcce Updated Changelog 2016-11-24 00:11:53 -08:00
Cory Bennett 1347ebe6b6 [#12] integrate with keyring for password storage and provide http basic auth
credentials for every request since most jira services have websudo enabled with
does not allow cookie based authentication
2016-11-23 23:43:29 -08:00
coryb c7565b08a1 Merge pull request #53 from jshirley/master
Add support for a unix socket proxy
2016-09-22 19:14:07 -07:00
Jay Shirley 01067e859c Cleaning up usage 2016-09-22 18:54:52 -07:00
Jay Shirley 8b174625d9 Update usage 2016-09-20 06:46:04 -07:00
Cory Bennett 8acc177627 use gopkg.in for links to maintain version compatibility 2016-09-18 12:44:00 -07:00
Cory Bennett 8d9db0e399 remove extraneous tee 2016-08-29 01:00:35 -07:00
Cory Bennett 998e4601c0 reduce mega verbosity 2016-08-29 01:00:01 -07:00
Cory Bennett 2df70edd00 up plan count for the sleep 2016-08-29 00:58:23 -07:00
Cory Bennett f73b3a5dc8 add missing src directory 2016-08-29 00:49:10 -07:00
Cory Bennett e74c94b030 move start.log to directory 2016-08-29 00:23:05 -07:00
Cory Bennett c18d2140e4 try travis cache and log atlas-run start output 2016-08-29 00:19:27 -07:00
Cory Bennett 2b56833c1c break setup to debug in travis 2016-08-29 00:04:21 -07:00
Cory Bennett fe69ad1cec wait for docker service to start? 2016-08-28 23:47:34 -07:00
Cory Bennett 3b18a1863c make maven cache directory local so we can ensure it is always there for travis testing 2016-08-28 23:36:37 -07:00
Cory Bennett d6d6578b11 make prove verbose 2016-08-28 23:32:03 -07:00
Cory Bennett 2b433dda40 golint 2016-08-28 23:30:25 -07:00
Cory Bennett 08a24e7dc3 require docker, run prove after build 2016-08-28 23:24:12 -07:00
Cory Bennett a746ddc6fb use altas-run to build jira test service in docker container 2016-08-28 23:10:54 -07:00
Cory Bennett e254435734 add "rank" command allow ordering backlog issues in agile projects 2016-08-26 19:44:38 -07:00
Jay Shirley 14298bfa52 Adding a unixproxy mechanism 2016-08-25 10:27:59 -07:00
Cory Bennett a3633aa537 Updated Changelog 2016-08-24 12:27:42 -07:00
coryb 2a8b6521dc Merge pull request #52 from dbrower/master
Prefer transition names which match exactly
2016-08-24 12:26:56 -07:00
Don Brower 4cc172de6b Prefer transition names which match exactly
Some transitions are substrings of other transitions, and the current
loop sometimes never chose the correct one. For example, it would never
choose "QA" if there were also a transtion "Deploy to QA". Ditto for
"Open" and "Reopen".
2016-08-24 14:36:23 -04:00
Cory Bennett 0dd6061992 update tempates to make them more readable with space trimming added to go-1.6 2016-08-21 23:51:45 -07:00
Cory Bennett 9d12f56332 add simple test for the "table" list output 2016-08-21 23:51:30 -07:00
47 changed files with 1537 additions and 358 deletions
+2 -1
View File
@@ -11,4 +11,5 @@ schemas/*.json
t/issue.props
t/.jira.d/templates
dist/
src/
src/
t/.maven-cache
+11 -6
View File
@@ -1,12 +1,17 @@
sudo: true
before_install:
- sudo apt-get update && sudo apt-get install -y pass gnupg
language: go
go:
- 1.6
- 1.6
matrix:
fast_finish: true
fast_finish: true
script:
- make vet
- make lint
- make
- make vet
- make lint
- make
- make prove 2>&1
+40
View File
@@ -1,5 +1,45 @@
# Changelog
## 0.1.13 - 2017-04-24
* work around `github.com/tmc/keyring` compile error for windows [Cory Bennett] [[85298e9](https://github.com/Netflix-Skunkworks/go-jira/commit/85298e9)]
* Added generic issuelink command [David Reuss] [[cc54d11](https://github.com/Netflix-Skunkworks/go-jira/commit/cc54d11)]
* Added --start parameter for pagination on results [David Reuss] [[9b94d9e](https://github.com/Netflix-Skunkworks/go-jira/commit/9b94d9e)]
## 0.1.12 - 2017-03-22
* Implement "browse" subcommand on Windows [Claus Brod] [[ca333d8](https://github.com/Netflix-Skunkworks/go-jira/commit/ca333d8)]
## 0.1.11 - 2017-02-26
* [[#69](https://github.com/Netflix-Skunkworks/go-jira/issues/69)] add subtask command [Cory Bennett] [[21a2ed5](https://github.com/Netflix-Skunkworks/go-jira/commit/21a2ed5)]
## 0.1.10 - 2017-02-08
* set GPG_TTY in .bashrc [Cory Bennett] [[b1e552f](https://github.com/Netflix-Skunkworks/go-jira/commit/b1e552f)]
* force password in case password already exists [Cory Bennett] [[d5a2c3b](https://github.com/Netflix-Skunkworks/go-jira/commit/d5a2c3b)]
* refactor password source, allow for "pass" to be used, update tests to use `password-source: pass` [Cory Bennett] [[5a71939](https://github.com/Netflix-Skunkworks/go-jira/commit/5a71939)]
## 0.1.9 - 2016-12-18
* only warn about needing login when not already running the login command [Cory Bennett] [[6c24e55](https://github.com/Netflix-Skunkworks/go-jira/commit/6c24e55)]
* fix(http): Add proxy transport [William Hearn] [[4bd740b](https://github.com/Netflix-Skunkworks/go-jira/commit/4bd740b)] [[2dff6c9](https://github.com/Netflix-Skunkworks/go-jira/commit/2dff6c9)]
## 0.1.8 - 2016-11-24
* [[#12](https://github.com/Netflix-Skunkworks/go-jira/issues/12)] integrate with keyring for password storage and provide http basic auth credentials for every request since most jira services have websudo enabled with does not allow cookie based authentication [Cory Bennett] [[b8a6e57](https://github.com/Netflix-Skunkworks/go-jira/commit/b8a6e57)]
* Cleaning up usage [Jay Shirley] [[8add52b](https://github.com/Netflix-Skunkworks/go-jira/commit/8add52b)]
* Update usage [Jay Shirley] [[b56e32a](https://github.com/Netflix-Skunkworks/go-jira/commit/b56e32a)]
* use gopkg.in for links to maintain version compatibility [Cory Bennett] [[1414d1f](https://github.com/Netflix-Skunkworks/go-jira/commit/1414d1f)]
* golint [Cory Bennett] [[44cdebf](https://github.com/Netflix-Skunkworks/go-jira/commit/44cdebf)]
* add "rank" command allow ordering backlog issues in agile projects [Cory Bennett] [[e4cc9c6](https://github.com/Netflix-Skunkworks/go-jira/commit/e4cc9c6)]
* Adding a unixproxy mechanism [Jay Shirley] [[5b9c0dd](https://github.com/Netflix-Skunkworks/go-jira/commit/5b9c0dd)]
## 0.1.7 - 2016-08-24
* Prefer transition names which match exactly [Don Brower] [[e40f9c1](https://github.com/Netflix-Skunkworks/go-jira/commit/e40f9c1)]
* update tempates to make them more readable with space trimming added to go-1.6 [Cory Bennett] [[693b3e4](https://github.com/Netflix-Skunkworks/go-jira/commit/693b3e4)]
## 0.1.6 - 2016-08-21
* make "worklogs" command print output through template allow "add worklog" command to open edit template [Cory Bennett] [[cc3fbee](https://github.com/Netflix-Skunkworks/go-jira/commit/cc3fbee)]
+34 -16
View File
@@ -1,10 +1,10 @@
PLATFORMS= \
freebsd-amd64 \
linux-386 \
linux-amd64 \
windows-386 \
windows-amd64 \
darwin-amd64 \
freebsd/amd64 \
linux/386 \
linux/amd64 \
windows/386 \
windows/amd64 \
darwin/amd64 \
$(NULL)
# freebsd-386 \
@@ -45,7 +45,7 @@ else
GOBUILD=go build -v -ldflags "$(LDFLAGS) -s"
endif
build: src/github.com/Netflix-Skunkworks/go-jira
build: src/gopkg.in/Netflix-Skunkworks/go-jira.v0
$(GOBUILD) -o '$(BIN)' main/main.go
debug:
@@ -53,7 +53,7 @@ debug:
src/%:
mkdir -p $(@D)
test -L $@ || ln -sf '$(GOPATH)' $@
test -L $@ || ln -sf '../../..' $@
go get -v $* $*/main
vet:
@@ -73,14 +73,24 @@ cross-setup:
cd $(GOROOT)/src && sudo GOROOT_BOOTSTRAP=$(GOROOT) GOOS=$${p/-*/} GOARCH=$${p/*-/} bash ./make.bash --no-clean; \
done
all:
rm -rf $(DIST); \
mkdir -p $(DIST); \
for p in $(PLATFORMS); do \
echo "Building for $$p"; \
${MAKE} build GOOS=$${p/-*/} GOARCH=$${p/*-/} BIN=$(DIST)/$(NAME)-$$p; \
done
for x in $(DIST)/jira-windows-*; do mv $$x $$x.exe; done
all:
git push --tags
rm -rf src
${MAKE} src/gopkg.in/Netflix-Skunkworks/go-jira.v0
docker pull karalabe/xgo-latest
rm -rf dist
mkdir -p dist
docker run --rm -e EXT_GOPATH=/gopath -v $$(pwd):/gopath -e TARGETS="$(PLATFORMS)" -v $$(pwd)/dist:/build karalabe/xgo-latest gopkg.in/Netflix-Skunkworks/go-jira.v0/main
cd $(DIST) && for x in main-*; do mv $$x jira-$$(echo $$x | cut -c 6-); done
# all:
# rm -rf $(DIST); \
# mkdir -p $(DIST); \
# for p in $(PLATFORMS); do \
# echo "Building for $$p"; \
# ${MAKE} build GOOS=$${p/-*/} GOARCH=$${p/*-/} BIN=$(DIST)/$(NAME)-$$p; \
# done
# for x in $(DIST)/jira-windows-*; do mv $$x $$x.exe; done
fmt:
gofmt -s -w main/*.go *.go
@@ -112,3 +122,11 @@ version:
clean:
rm -rf pkg dist bin src ./$(NAME)
export GNUPGHOME=$(CWD)/t/.gnupg
export PASSWORD_STORE_DIR=$(CWD)/t/.password-store
export JIRACLOUD=1
prove:
chmod -R g-rwx,o-rwx $(GNUPGHOME)
OSHT_VERBOSE=1 prove -v
+60 -5
View File
@@ -9,7 +9,7 @@ simple command line client for Atlassian's Jira service written in Go
## Synopsis
```bash
jira ls -p GOJIRA # list all unresolved issues for project GOJRIA
jira ls -p GOJIRA # list all unresolved issues for project GOJIRA
jira ls -p GOJIRA -a mothra # as above also assigned to user mothra
jira ls -p GOJIRA -w mothra # lists GOJIRA unresolved issues watched by user mothra
jira ls -p GOJIRA -r mothra # list GOJIRA unresolved issues reported by user mothra
@@ -21,7 +21,7 @@ jira GOJIRA-321 # same as above
jira edit GOJIRA-321 # open up the issue in an editor, when you exit the
# editor the issue will post the updates to the server
# edit the issue, using the overirdes on the command line, skip the interactive editor:
# edit the issue, using the overrides on the command line, skip the interactive editor:
jira edit GOJIRA-321 --noedit \
-o assignee=mothra \
-o comment="mothra, please take care of this." \
@@ -38,7 +38,7 @@ jira trans close GOJIRA-321 -o resolution="Won't Fix" --noedit
# same as above
jira close GOJIRA-321 -o resolution="Won't Fix"
jira repopen GOJIRA-321 -m "reopening" # reopen issue
jira reopen GOJIRA-321 -m "reopening" # reopen issue
jira watch GOJIRA-321 # add self as watcher to the issue
@@ -91,7 +91,7 @@ a child directory of your homedir, then your homedir will also be inspected for
discovered **go-jira** will load a **config.yml** if found. The configuration properties found in a file closests to your current working directory
will have precedence. Properties overriden with command line options will have final precedence.
The complicated configuration heirarchy is used because **go-jira** attempts to be context aware. For example, if you are working on a "foo" project and
The complicated configuration hierarchy is used because **go-jira** attempts to be context aware. For example, if you are working on a "foo" project and
you `cd` into your project workspace, wouldn't it be nice if `jira ls` automatically knew to list only issues related to the "foo" project? Likewise when you
`cd` to the "bar" project then `jira ls` should only list issues related to "bar" project. You can do this with by creating a configuration under your project
workspace at **./.jira.d/config.yml** that looks like:
@@ -110,7 +110,7 @@ endpoint: https://jira.mycompany.com
EOM
```
Then use `jira login` to authenticate yourself.
Then use `jira login` to authenticate yourself as $USER. To change your username, use the `-u` CLI flag or set `user:` in your config.yml
### Dynamic Configuration
@@ -182,6 +182,61 @@ jira create --dryrun -t debug --editor /bin/cat
```
This will attempt to fetch metadata for your default project (you can provide any options that you would normally specify for the `create` operation). It uses the `--dryrun` option to prevent any actual updates being sent to Jira. The `-t debug` is like before to cause the input to be serialized to JSON and printed for your inspection. Finally the `--editor /bin/cat` will cause `go-jira` to just print the template rather than open up an editor and wait for you to edit/save it.
### Authentication
By default `go-jira` will prompt for a password automatically when we receive an 403 http response. Then after authentication we cache the JSESSSION cookie returned by the service and reuse that on subsequent requests. Typically this cookie will be valid for several hours (depending on the service configuration). Many deployments of Jira (like the cloud services on atlassian.net) have "websudo" enabled which will prevent the cookie based authentcation from working. On these deployments you have a few options with `go-jira`. You can enable a `password-source` via `.jira.d/config.yml` with possible values of `keyring` or `pass`.
#### keyring password source
**Note: Version 0.1.9 required.**
On OSX and Linux there are a few keyring providers that `go-jira` can use (via this [golang module](https://github.com/tmc/keyring)). To integrate `go-jira` with a supported keyring just add this configuration to `$HOME/.jira.d/config.yml`:
```yaml
password-source: keyring
```
After setting this and issuing a `jira login`, your credentials will be stored in your platform's backend (e.g. Keychain for Mac OS X) automatically. Subsequent operations, like a `jira ls`, should "just work" from there.
#### `pass` password source
**Note: Version 0.1.9 required.**
An alternative to the keyring password source is the `pass` tool (documentation [here](https://www.passwordstore.org/)). This uses gpg to encrypt/decrypt passwords on demand and by using `gpg-agent` you can cache the gpg credentials for a period of time so you will not be prompted repeatedly for decrypting the passwords. The advantage over the keyring integration is that `pass` can be used on more platforms than OSX and Linux, although it does require more setup. To use `pass` for password storage and retrieval via `go-jira` just add this configuration to `$HOME/.jira.d/config.yml`:
```yaml
password-source: pass
```
This assumes you have already setup `pass` correctly on your system. Specifically you will need to have created a gpg key like this:
```
$ gpg --gen-key
```
Then you will need the GPG Key ID you want associated with `pass`. First list the available keys:
```
$ gpg --list-keys
/home/gojira/.gnupg/pubring.gpg
-------------------------------------------------
pub 2048R/A307D709 2016-12-18
uid Go Jira <gojira@example.com>
sub 2048R/F9A047B8 2016-12-18
```
Then initialize the `pass` tool to use the correct key:
```
$ pass init "Go Jira <gojira@example.com>"
```
You probably want to setup gpg-agent so that you dont have to type in your gpg passphrase all the time. You can get `gpg-agent` to automatically start by adding something like this to your `$HOME/.bashrc`
```bash
if [ -f $HOME/.gpg-agent-info ]; then
. $HOME/.gpg-agent-info
export GPG_AGENT_INFO
fi
# verify sock file from GPG_AGENT_INFO is actually present
if [ ! -S "${GPG_AGENT_INFO%%:*}" ]; then
# set passphrase cache so I only have to type my passphrase once a day
eval $(gpg-agent --default-cache-ttl 604800 --daemon --write-env-file $HOME/.gpg-agent-info)
fi
export GPG_TTY=$(tty)
```
## Usage
```
+86 -14
View File
@@ -5,9 +5,6 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"github.com/kballard/go-shellquote"
"gopkg.in/coryb/yaml.v2"
"gopkg.in/op/go-logging.v1"
"io/ioutil"
"net/http"
"net/http/cookiejar"
@@ -20,6 +17,10 @@ import (
"runtime"
"strings"
"time"
"github.com/kballard/go-shellquote"
"gopkg.in/coryb/yaml.v2"
"gopkg.in/op/go-logging.v1"
)
var (
@@ -43,26 +44,36 @@ 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
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: &http.Client{
Jar: cookieJar,
Transport: transport,
},
ua: ua,
}
cli.ua.Jar.SetCookies(url, cli.loadCookies())
@@ -203,6 +214,16 @@ 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) {
@@ -430,6 +451,8 @@ func (c *Cli) Browse(issue string) error {
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
@@ -521,7 +544,7 @@ func (c *Cli) FindIssues() (interface{}, error) {
json, err := jsonEncode(map[string]interface{}{
"jql": query,
"startAt": "0",
"startAt": c.opts["start_at"],
"maxResults": c.opts["max_results"],
"fields": fields,
"expand": c.expansions(),
@@ -538,6 +561,55 @@ func (c *Cli) FindIssues() (interface{}, error) {
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 {
+173 -31
View File
@@ -4,13 +4,13 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/Netflix-Skunkworks/go-jira/data"
"github.com/howeyc/gopass"
"io/ioutil"
"net/http"
"net/url"
"os"
"strings"
"gopkg.in/Netflix-Skunkworks/go-jira.v0/data"
// "github.com/kr/pretty"
)
@@ -21,13 +21,7 @@ func (c *Cli) CmdLogin() error {
req, _ := http.NewRequest("GET", uri, nil)
user, _ := c.opts["user"].(string)
fmt.Printf("Jira Password [%s]: ", user)
pw, err := gopass.GetPasswdMasked()
if err != nil {
return err
}
passwd := string(pw)
passwd := c.GetPass(user)
req.SetBasicAuth(user, passwd)
resp, err := c.makeRequest(req)
@@ -53,6 +47,9 @@ func (c *Cli) CmdLogin() error {
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")
@@ -135,7 +132,7 @@ func (c *Cli) CmdWorklog(action string, issue string) error {
uri := fmt.Sprintf("%s/rest/api/2/issue/%s/worklog", c.endpoint, issue)
worklogData := map[string]interface{}{
"issue": issue,
"issue": issue,
"comment": c.opts["comment"],
}
@@ -157,7 +154,7 @@ func (c *Cli) CmdWorklog(action string, issue string) error {
if err != nil {
return err
}
if resp.StatusCode == 201 {
c.Browse(issue)
if !c.opts["quiet"].(bool) {
@@ -379,31 +376,15 @@ func (c *Cli) CmdCreate() error {
issuetype = c.defaultIssueType()
}
uri := fmt.Sprintf("%s/rest/api/2/issue/createmeta?projectKeys=%s&issuetypeNames=%s&expand=projects.issuetypes.fields", c.endpoint, project, url.QueryEscape(issuetype))
data, err := responseToJSON(c.get(uri))
if err != nil {
return err
}
issueData := make(map[string]interface{})
issueData["overrides"] = c.opts
issueData["overrides"].(map[string]interface{})["issuetype"] = issuetype
if val, ok := data.(map[string]interface{})["projects"]; ok {
if len(val.([]interface{})) == 0 {
err = fmt.Errorf("Project '%s' or issuetype '%s' unknown. Unable to create issue.", project, issuetype)
log.Errorf("%s", err)
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.Errorf("%s", err)
return err
}
issueData["meta"] = val.([]interface{})[0]
}
meta, err := c.createIssueMetaData(project, issuetype)
if err != nil {
return err
}
issueData["meta"] = meta
sanitizedType := strings.ToLower(strings.Replace(issuetype, " ", "", -1))
return c.editTemplate(
@@ -449,6 +430,96 @@ func (c *Cli) CmdCreate() error {
)
}
func (c *Cli) createIssueMetaData(project, issuetype string) (interface{}, error) {
uri := fmt.Sprintf("%s/rest/api/2/issue/createmeta?projectKeys=%s&issuetypeNames=%s&expand=projects.issuetypes.fields", c.endpoint, project, url.QueryEscape(issuetype))
metaData, err := responseToJSON(c.get(uri))
if err != nil {
return nil, err
}
if val, ok := metaData.(map[string]interface{})["projects"]; ok {
if len(val.([]interface{})) == 0 {
err = fmt.Errorf("Project '%s' or issuetype '%s' unknown. Unable to create issue.", project, issuetype)
log.Errorf("%s", err)
return nil, 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.Errorf("%s", err)
return nil, err
}
return val.([]interface{})[0], nil
}
}
return nil, nil
}
// CmdSubtask sends the create-metadata to the "subtask" template for editing, then
// will parse the edited document as YAML and submit the document to jira.
func (c *Cli) CmdSubtask(issue string) error {
log.Debugf("subtask called")
uri := fmt.Sprintf("%s/rest/api/2/issue/%s", c.endpoint, issue)
parentData, err := responseToJSON(c.get(uri))
if err != nil {
return err
}
subtaskData := make(map[string]interface{})
subtaskData["parent"] = parentData
subtaskData["overrides"] = c.opts
project := parentData.(map[string]interface{})["fields"].(map[string]interface{})["project"].(map[string]interface{})["key"].(string)
meta, err := c.createIssueMetaData(project, "Sub-task")
if err != nil {
return err
}
subtaskData["meta"] = meta
return c.editTemplate(
c.getTemplate("subtask"),
"subtask-",
subtaskData,
func(json string) error {
uri := fmt.Sprintf("%s/rest/api/2/issue", 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 {
// response: {"id":"410836","key":"PROJ-238","self":"https://jira/rest/api/2/issue/410836"}
json, err := responseToJSON(resp, nil)
if err != nil {
return err
}
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
}
logBuffer := bytes.NewBuffer(make([]byte, 0))
resp.Write(logBuffer)
err = fmt.Errorf("Unexpected Response From POST")
log.Errorf("%s:\n%s", err, logBuffer)
return err
},
)
}
// CmdIssueLinkTypes will send the issue link type data to the "issuelinktypes" template.
func (c *Cli) CmdIssueLinkTypes() error {
log.Debugf("Transitions called")
@@ -460,6 +531,50 @@ func (c *Cli) CmdIssueLinkTypes() error {
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.opts["quiet"].(bool) {
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
}
// CmdBlocks will update the given issue as being "blocked" by the given blocker
func (c *Cli) CmdBlocks(blocker string, issue string) error {
log.Debugf("blocks called")
@@ -645,6 +760,30 @@ func (c *Cli) CmdVote(issue string, up bool) error {
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.opts["quiet"].(bool) {
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.opts["quiet"].(bool) {
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")
@@ -666,6 +805,9 @@ func (c *Cli) CmdTransition(issue string, trans string) error {
transName = name
transID = id
transMeta = transition.(map[string]interface{})
if strings.ToLower(name) == strings.ToLower(trans) {
break
}
}
}
if transID == "" {
+13
View File
@@ -0,0 +1,13 @@
// +build !windows
package jira
import "github.com/tmc/keyring"
func keyringGet(user string) (string, error) {
return keyring.Get("go-jira", user)
}
func keyringSet(user, passwd string) error {
return keyring.Set("go-jira", user, passwd)
}
+11
View File
@@ -0,0 +1,11 @@
package jira
import "fmt"
func keyringGet(user string) (string, error) {
return "", fmt.Errorf("Keyring is not supported for Windows, see: https://github.com/tmc/keyring")
}
func keyringSet(user, passwd string) error {
return fmt.Errorf("Keyring is not supported for Windows, see: https://github.com/tmc/keyring")
}
+28 -4
View File
@@ -3,14 +3,15 @@ package main
import (
"bytes"
"fmt"
"github.com/Netflix-Skunkworks/go-jira"
"github.com/coryb/optigo"
"gopkg.in/coryb/yaml.v2"
"gopkg.in/op/go-logging.v1"
"io/ioutil"
"os"
"os/exec"
"strings"
"github.com/coryb/optigo"
"gopkg.in/Netflix-Skunkworks/go-jira.v0"
"gopkg.in/coryb/yaml.v2"
"gopkg.in/op/go-logging.v1"
)
var (
@@ -60,9 +61,12 @@ Usage:
jira add worklog ISSUE <Worklog Options>
jira edit [--noedit] <Edit Options> [ISSUE | <Query Options>]
jira create [--noedit] [-p PROJECT] <Create Options>
jira subtask ISSUE [--noedit] <Create Options>
jira DUPLICATE dups ISSUE
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 ack ISSUE [--edit] <Edit Options>
@@ -103,6 +107,7 @@ General Options:
-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:
@@ -111,6 +116,7 @@ Query Options:
-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
@@ -143,8 +149,10 @@ Command Options:
"view": "view",
"edit": "edit",
"create": "create",
"subtask": "subtask",
"dups": "dups",
"blocks": "blocks",
"issuelink": "issuelink",
"watch": "watch",
"trans": "transition",
"transition": "transition",
@@ -183,6 +191,7 @@ Command Options:
"req": "request",
"request": "request",
"vote": "vote",
"rank": "rank",
"worklog": "worklog",
"addworklog": "addworklog",
}
@@ -230,6 +239,7 @@ Command Options:
"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,
@@ -239,6 +249,7 @@ Command Options:
"S|saveFile=s": setopt,
"T|time-spent=s": setopt,
"Q|quiet": setopt,
"unixproxy": setopt,
"down": setopt,
})
@@ -328,6 +339,9 @@ Command Options:
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":
@@ -372,6 +386,9 @@ Command Options:
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])
@@ -507,6 +524,13 @@ Command Options:
} 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 := ""
+78
View File
@@ -0,0 +1,78 @@
package jira
import (
"bytes"
"fmt"
"os/exec"
"strings"
"github.com/howeyc/gopass"
)
func (c *Cli) GetPass(user string) string {
passwd := ""
if source, ok := c.opts["password-source"].(string); ok {
if source == "keyring" {
var err error
passwd, err = keyringGet(user)
if err != nil {
panic(err)
}
} else if source == "pass" {
if bin, err := exec.LookPath("pass"); err == nil {
buf := bytes.NewBufferString("")
cmd := exec.Command(bin, fmt.Sprintf("GoJira/%s", 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", source)
}
}
if passwd != "" {
return passwd
}
fmt.Printf("Jira Password [%s]: ", user)
pw, err := gopass.GetPasswdMasked()
if err != nil {
return ""
}
passwd = string(pw)
return passwd
}
func (c *Cli) SetPass(user, passwd string) error {
log.Debugf("SetPass called: %s => %s", user, passwd)
if source, ok := c.opts["password-source"].(string); ok {
log.Debugf("password-source: %s", source)
if source == "keyring" {
// save password in keychain so that it can be used for subsequent http requests
err := keyringSet(user, passwd)
if err != nil {
log.Errorf("Failed to set password in keyring: %s", err)
return err
}
} else if source == "pass" {
log.Debugf("processing %s", source)
if bin, err := exec.LookPath("pass"); err == nil {
log.Debugf("using %s", bin)
in := bytes.NewBufferString(fmt.Sprintf("%s\n%s\n", passwd, passwd))
out := bytes.NewBufferString("")
cmd := exec.Command(bin, "insert", "--force", fmt.Sprintf("GoJira/%s", user))
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 {
return fmt.Errorf("Unknown password-source: %s", source)
}
}
return nil
}
+1
View File
@@ -0,0 +1 @@
!src/
+236
View File
@@ -0,0 +1,236 @@
# Options for GnuPG
# Copyright 1998, 1999, 2000, 2001, 2002, 2003,
# 2010 Free Software Foundation, Inc.
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# Unless you specify which option file to use (with the command line
# option "--options filename"), GnuPG uses the file ~/.gnupg/gpg.conf
# by default.
#
# An options file can contain any long options which are available in
# GnuPG. If the first non white space character of a line is a '#',
# this line is ignored. Empty lines are also ignored.
#
# See the man page for a list of options.
# Uncomment the following option to get rid of the copyright notice
#no-greeting
# If you have more than 1 secret key in your keyring, you may want to
# uncomment the following option and set your preferred keyid.
#default-key 621CC013
# If you do not pass a recipient to gpg, it will ask for one. Using
# this option you can encrypt to a default key. Key validation will
# not be done in this case. The second form uses the default key as
# default recipient.
#default-recipient some-user-id
#default-recipient-self
# Use --encrypt-to to add the specified key as a recipient to all
# messages. This is useful, for example, when sending mail through a
# mail client that does not automatically encrypt mail to your key.
# In the example, this option allows you to read your local copy of
# encrypted mail that you've sent to others.
#encrypt-to some-key-id
# By default GnuPG creates version 4 signatures for data files as
# specified by OpenPGP. Some earlier (PGP 6, PGP 7) versions of PGP
# require the older version 3 signatures. Setting this option forces
# GnuPG to create version 3 signatures.
#force-v3-sigs
# Because some mailers change lines starting with "From " to ">From "
# it is good to handle such lines in a special way when creating
# cleartext signatures; all other PGP versions do it this way too.
#no-escape-from-lines
# If you do not use the Latin-1 (ISO-8859-1) charset, you should tell
# GnuPG which is the native character set. Please check the man page
# for supported character sets. This character set is only used for
# metadata and not for the actual message which does not undergo any
# translation. Note that future version of GnuPG will change to UTF-8
# as default character set. In most cases this option is not required
# as GnuPG is able to figure out the correct charset at runtime.
#charset utf-8
# Group names may be defined like this:
# group mynames = paige 0x12345678 joe patti
#
# Any time "mynames" is a recipient (-r or --recipient), it will be
# expanded to the names "paige", "joe", and "patti", and the key ID
# "0x12345678". Note there is only one level of expansion - you
# cannot make an group that points to another group. Note also that
# if there are spaces in the recipient name, this will appear as two
# recipients. In these cases it is better to use the key ID.
#group mynames = paige 0x12345678 joe patti
# Lock the file only once for the lifetime of a process. If you do
# not define this, the lock will be obtained and released every time
# it is needed, which is usually preferable.
#lock-once
# GnuPG can send and receive keys to and from a keyserver. These
# servers can be HKP, email, or LDAP (if GnuPG is built with LDAP
# support).
#
# Example HKP keyserver:
# hkp://keys.gnupg.net
# hkp://subkeys.pgp.net
#
# Example email keyserver:
# mailto:pgp-public-keys@keys.pgp.net
#
# Example LDAP keyservers:
# ldap://keyserver.pgp.com
#
# Regular URL syntax applies, and you can set an alternate port
# through the usual method:
# hkp://keyserver.example.net:22742
#
# Most users just set the name and type of their preferred keyserver.
# Note that most servers (with the notable exception of
# ldap://keyserver.pgp.com) synchronize changes with each other. Note
# also that a single server name may actually point to multiple
# servers via DNS round-robin. hkp://keys.gnupg.net is an example of
# such a "server", which spreads the load over a number of physical
# servers. To see the IP address of the server actually used, you may use
# the "--keyserver-options debug".
keyserver hkp://keys.gnupg.net
#keyserver mailto:pgp-public-keys@keys.nl.pgp.net
#keyserver ldap://keyserver.pgp.com
# Common options for keyserver functions:
#
# include-disabled : when searching, include keys marked as "disabled"
# on the keyserver (not all keyservers support this).
#
# no-include-revoked : when searching, do not include keys marked as
# "revoked" on the keyserver.
#
# verbose : show more information as the keys are fetched.
# Can be used more than once to increase the amount
# of information shown.
#
# use-temp-files : use temporary files instead of a pipe to talk to the
# keyserver. Some platforms (Win32 for one) always
# have this on.
#
# keep-temp-files : do not delete temporary files after using them
# (really only useful for debugging)
#
# http-proxy="proxy" : set the proxy to use for HTTP and HKP keyservers.
# This overrides the "http_proxy" environment variable,
# if any.
#
# auto-key-retrieve : automatically fetch keys as needed from the keyserver
# when verifying signatures or when importing keys that
# have been revoked by a revocation key that is not
# present on the keyring.
#
# no-include-attributes : do not include attribute IDs (aka "photo IDs")
# when sending keys to the keyserver.
#keyserver-options auto-key-retrieve
# Display photo user IDs in key listings
# list-options show-photos
# Display photo user IDs when a signature from a key with a photo is
# verified
# verify-options show-photos
# Use this program to display photo user IDs
#
# %i is expanded to a temporary file that contains the photo.
# %I is the same as %i, but the file isn't deleted afterwards by GnuPG.
# %k is expanded to the key ID of the key.
# %K is expanded to the long OpenPGP key ID of the key.
# %t is expanded to the extension of the image (e.g. "jpg").
# %T is expanded to the MIME type of the image (e.g. "image/jpeg").
# %f is expanded to the fingerprint of the key.
# %% is %, of course.
#
# If %i or %I are not present, then the photo is supplied to the
# viewer on standard input. If your platform supports it, standard
# input is the best way to do this as it avoids the time and effort in
# generating and then cleaning up a secure temp file.
#
# If no photo-viewer is provided, GnuPG will look for xloadimage, eog,
# or display (ImageMagick). On Mac OS X and Windows, the default is
# to use your regular JPEG image viewer.
#
# Some other viewers:
# photo-viewer "qiv %i"
# photo-viewer "ee %i"
#
# This one saves a copy of the photo ID in your home directory:
# photo-viewer "cat > ~/photoid-for-key-%k.%t"
#
# Use your MIME handler to view photos:
# photo-viewer "metamail -q -d -b -c %T -s 'KeyID 0x%k' -f GnuPG"
# Passphrase agent
#
# We support the old experimental passphrase agent protocol as well as
# the new Assuan based one (currently available in the "newpg" package
# at ftp.gnupg.org/gcrypt/alpha/aegypten/). To make use of the agent,
# you have to run an agent as daemon and use the option
#
# use-agent
#
# which tries to use the agent but will fallback to the regular mode
# if there is a problem connecting to the agent. The normal way to
# locate the agent is by looking at the environment variable
# GPG_AGENT_INFO which should have been set during gpg-agent startup.
# In certain situations the use of this variable is not possible, thus
# the option
#
# --gpg-agent-info=<path>:<pid>:1
#
# may be used to override it.
# Automatic key location
#
# GnuPG can automatically locate and retrieve keys as needed using the
# auto-key-locate option. This happens when encrypting to an email
# address (in the "user@example.com" form), and there are no
# user@example.com keys on the local keyring. This option takes the
# following arguments, in the order they are to be tried:
#
# cert = locate a key using DNS CERT, as specified in RFC-4398.
# GnuPG can handle both the PGP (key) and IPGP (URL + fingerprint)
# CERT methods.
#
# pka = locate a key using DNS PKA.
#
# ldap = locate a key using the PGP Universal method of checking
# "ldap://keys.(thedomain)". For example, encrypting to
# user@example.com will check ldap://keys.example.com.
#
# keyserver = locate a key using whatever keyserver is defined using
# the keyserver option.
#
# You may also list arbitrary keyservers here by URL.
#
# Try CERT, then PKA, then LDAP, then hkp://subkeys.net:
#auto-key-locate cert pka ldap hkp://subkeys.pgp.net
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Regular → Executable
+9 -2
View File
@@ -1,2 +1,9 @@
endpoint: http://localhost:8080
user: gojira
#!/bin/sh
echo password-source: pass
if [ -z "$JIRACLOUD" ]; then
echo endpoint: http://localhost:8080
echo user: gojira
else
echo endpoint: https://go-jira.atlassian.net
echo user: gojira@example.com
fi
+1
View File
@@ -0,0 +1 @@
Go Jira <gojira@example.com>
+1
View File
@@ -0,0 +1 @@
 (ΡαΆω GΈώ20,ΧΎ„ι―’«$Ggu©y1_a-ΟI'ΥΈοΘ}Ν£4 ¨s@,]?P­ξs>uθ¤QpΓxΛΠΡA|x]"Ύf„ς—λΫ£B2Εν ytΌΡ±c…¥ο β8L ΙvgΗΚi] ΙKΥzu0yKΩ.“ §ΣBΑw| ƒ†_K'zθ΅Ύ“c¦ύυάά…ύ)?ΔoT #G8PΧΙπΩ=υP-,Ί}¥άώΝ X:,ΊfB'=WG²I±¨­  0BΈ£ξJΞ3Η εϋοΛΞσ;;;)Iι_UMfα•τ’}·’,―CΒhπΟμ£ο®μ\‰kκtΞ&ωµNύΌΐ½άjξ™ά
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
 (Ñá¢ù G¸ü ©oCº™*šâj0OÊ! =ldÿ§ô~2%p7•>´·kbñ#d›‹'¥d|_à{±ºa¶ŠÔο=mÂm½ð°Lí&‹À',^‰ý$¡¨!HÞ>]Ð4WïôêÔi+q=†N 2¿1´K;_% ~Ø ™¶£Õ‡ØÄ~\¶' : Ï[*:ï´ËFÃáSÌooApö¦*dËËH¬ôz‘È-vÝÞ#¼5†¡Ü[…« Ü„zê,e ¸˜È¤H„e#"=¾$y5kÐ+$Ë Ô¸šÇϨ~Õç’÷¾Ë3×Ïçj®¹3O£|WéÝÿîA#TI)ö± «âU }ô¹Ò;M3³ÞŒžëÁ9.ª}iT΂Š Ëì0S s…Jp…ìå’*½çѶPob‘¼™(*ò
Binary file not shown.
+19 -11
View File
@@ -3,28 +3,36 @@ eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira="../jira --user admin"
PLAN 14
SKIP test -n "$JIRACLOUD" # using Jira Cloud at go-jira.atlassian.net
PLAN 15
# clean out any old containers
docker rm -f go-jira-test
# start newt jira service
RUNS docker run --detach --name go-jira-test --publish 8080:8080 go-jira-test:latest
RUNS docker build . -t go-jira-test
# wait a few seconds for it to bind to port 8080
RUNS sleep 10
mkdir -p $(pwd)/.maven-cache
# wait for healthchecks to pass, curl will retry 60 times over 5 min waiting
RUNS curl -q -L --retry 360 --retry-delay 1 -f -s "http://localhost:8080/rest/api/2/serverInfo?doHealthCheck=1"
# start newt jira service, cache the users m2 directory to make startup faster
RUNS docker run --detach -v $(pwd)/.maven-cache:/root/.m2/repository --name go-jira-test --publish 8080:8080 go-jira-test:latest
# wait for docker service to get started
RUNS sleep 5
echo "# Waiting for jira service to be listening on port 8080"
docker exec -i go-jira-test tail -f screenlog.0 | grep -m 1 'jira started successfully' | sed 's/^/# /'
# wait for healthchecks to pass, curl will retry 900 times over 15 min waiting
RUNS curl -q -L --retry 900 --retry-delay 1 -f -s "http://localhost:8080/rest/api/2/serverInfo?doHealthCheck=1"
# login to jira as admin user
echo "admin123" | RUNS $jira login
RUNS $jira login
# create gojira user
RUNS $jira req -M POST /rest/api/2/user '{"name":"gojira","password":"gojira123","emailAddress":"gojira@example.com","displayName":"Go Jira"}'
RUNS $jira req -M POST /rest/api/2/user '{"name":"gojira","password":"gojira123","emailAddress":"gojira@example.com","displayName":"GoJira"}'
# create mojira user (need secondary user for voting)
RUNS $jira req -M POST /rest/api/2/user '{"name":"mojira","password":"mojira123","emailAddress":"mojira@example.com","displayName":"Mo Jira"}'
# create mothra user (need secondary user for voting)
RUNS $jira req -M POST /rest/api/2/user '{"name":"mothra","password":"mothra123","emailAddress":"mothra@example.com","displayName":"Mothra"}'
# create SCRUM softwareproject
RUNS $jira req -M POST /rest/api/2/project '{"key":"SCRUM","name":"Scrum","projectTypeKey":"software","projectTemplateKey":"com.pyxis.greenhopper.jira:gh-scrum-template","lead":"gojira"}'
+3 -1
View File
@@ -3,6 +3,8 @@ eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira=../jira
SKIP test -n "$JIRACLOUD" # using Jira Cloud at go-jira.atlassian.net
PLAN 7
###############################################################################
@@ -24,6 +26,6 @@ echo "gojira123" | RUNS $jira login
RUNS $jira req /rest/auth/1/session </dev/null
GREP '"name": "gojira"'
GREP '"self": "http://localhost:8080/rest/api/latest/user?username=gojira"'
GREP "\"self\": \"$ENDPOINT/rest/api/latest/user?username=gojira\""
+52 -34
View File
@@ -4,11 +4,16 @@ cd $(dirname $0)
jira="../jira --project BASIC"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
PLAN 84
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
PLAN 86
# reset login
RUNS $jira logout
echo "gojira123" | RUNS $jira login
RUNS $jira login
# cleanup from previous failed test executions
($jira ls | awk -F: '{print $1}' | while read issue; do ../jira done $issue; done) | sed 's/^/# CLEANUP: /g'
@@ -20,7 +25,7 @@ RUNS $jira create -o summary=summary -o description=description --noedit --saveF
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -52,6 +57,19 @@ DIFF <<EOF
$(printf %-12s $issue:) summary
EOF
###############################################################################
## List all issues, using the table template
###############################################################################
RUNS $jira ls --template table
DIFF <<EOF
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
| Issue | Summary | Priority | Status | Age | Reporter | Assignee |
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
| $(printf %-14s $issue) | summary | Medium | To Do | a minute | gojira | gojira |
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
EOF
###############################################################################
## Try to close the issue, bug Basic projects do not allow that state
###############################################################################
@@ -67,7 +85,7 @@ EOF
RUNS $jira done $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -85,13 +103,13 @@ EOF
RUNS $jira create -o summary=summary -o description=description --noedit --saveFile issue.props
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira create -o summary=dup -o description=dup --noedit --saveFile issue.props
dup=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $dup http://localhost:8080/browse/$dup
OK $dup $ENDPOINT/browse/$dup
EOF
###############################################################################
@@ -102,8 +120,8 @@ EOF
RUNS $jira $dup dups $issue --noedit
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $dup http://localhost:8080/browse/$dup
OK $issue $ENDPOINT/browse/$issue
OK $dup $ENDPOINT/browse/$dup
EOF
RUNS $jira $issue
@@ -140,7 +158,7 @@ EOF
RUNS $jira create -o summary=blocks -o description=blocks --noedit --saveFile issue.props
blocker=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -149,7 +167,7 @@ EOF
RUNS $jira $blocker blocks $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -181,13 +199,13 @@ $(printf %-12s $blocker:) blocks
EOF
###############################################################################
# reset login for mojira for voting
# reset login for mothra for voting
###############################################################################
jira="$jira --user mojira"
jira="$jira --user mothra"
RUNS $jira logout
echo "mojira123" | RUNS $jira login
RUNS $jira login
###############################################################################
## vote for main issue, verify it shows when viewing the issue
@@ -195,7 +213,7 @@ echo "mojira123" | RUNS $jira login
RUNS $jira vote $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -222,7 +240,7 @@ EOF
RUNS $jira vote $issue --down
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -244,19 +262,19 @@ description: |
EOF
###############################################################################
## set mojira user as watcher to issue and verify from REST api
## set mothra user as watcher to issue and verify from REST api
###############################################################################
RUNS $jira watch $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
# FIXME we probably need a watchers command to wrap this?
RUNS sh -c "$jira req /rest/api/2/issue/$issue/watchers | jq -r .watchers[].name"
RUNS sh -c "$jira req /rest/api/2/issue/$issue/watchers | jq -r .watchers[].name | sort"
DIFF <<EOF
gojira
mojira
mothra
EOF
###############################################################################
@@ -265,7 +283,7 @@ EOF
RUNS $jira trans "In Progress" $blocker --noedit
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -274,7 +292,7 @@ EOF
RUNS $jira todo $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -283,7 +301,7 @@ EOF
RUNS $jira trans "review" $blocker --noedit
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -292,7 +310,7 @@ EOF
RUNS $jira todo $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -301,7 +319,7 @@ EOF
RUNS $jira prog $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -310,7 +328,7 @@ EOF
RUNS $jira done $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -341,7 +359,7 @@ EOF
RUNS $jira comment $issue --noedit -m "Yo, Comment"
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -362,7 +380,7 @@ description: |
description
comments:
- | # mojira, a minute ago
- | # mothra, a minute ago
Yo, Comment
EOF
@@ -373,7 +391,7 @@ EOF
RUNS $jira add labels $blocker test-label another-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -401,7 +419,7 @@ EOF
RUNS $jira remove labels $blocker another-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -429,7 +447,7 @@ EOF
RUNS $jira set labels $blocker more-label better-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -452,12 +470,12 @@ description: |
EOF
###############################################################################
## Verify that "mojira" user can take the issue (reassign to self)
## Verify that "mothra" user can take the issue (reassign to self)
###############################################################################
RUNS $jira take $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -468,7 +486,7 @@ status: Done
summary: blocks
project: BASIC
issuetype: Bug
assignee: mojira
assignee: mothra
reporter: gojira
blockers:
depends: $issue[To Do]
@@ -485,7 +503,7 @@ EOF
RUNS $jira give $blocker gojira
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
+8 -3
View File
@@ -4,11 +4,16 @@ cd $(dirname $0)
jira="../jira --project BASIC"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
PLAN 8
# reset login
RUNS $jira logout
echo "gojira123" | RUNS $jira login
RUNS $jira login
# cleanup from previous failed test executions
($jira ls | awk -F: '{print $1}' | while read issue; do ../jira done $issue; done) | sed 's/^/# CLEANUP: /g'
@@ -20,7 +25,7 @@ RUNS $jira create -o summary=summary -o description=description --noedit --saveF
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -28,7 +33,7 @@ EOF
###############################################################################
RUNS $jira add worklog $issue --comment "work is hard" --time-spent "1h 12m" --noedit
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
+36 -31
View File
@@ -4,6 +4,11 @@ cd $(dirname $0)
jira="../jira --project SCRUM"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
PLAN 84
# cleanup from previous failed test executions
@@ -20,7 +25,7 @@ RUNS $jira create -o summary=summary -o description=description --noedit --saveF
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -67,7 +72,7 @@ EOF
RUNS $jira done $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -85,13 +90,13 @@ EOF
RUNS $jira create -o summary=summary -o description=description --noedit --saveFile issue.props
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira create -o summary=dup -o description=dup --noedit --saveFile issue.props
dup=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $dup http://localhost:8080/browse/$dup
OK $dup $ENDPOINT/browse/$dup
EOF
###############################################################################
@@ -102,8 +107,8 @@ EOF
RUNS $jira $dup dups $issue --noedit
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $dup http://localhost:8080/browse/$dup
OK $issue $ENDPOINT/browse/$issue
OK $dup $ENDPOINT/browse/$dup
EOF
RUNS $jira $issue
@@ -140,7 +145,7 @@ EOF
RUNS $jira create -o summary=blocks -o description=blocks --noedit --saveFile issue.props
blocker=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -149,7 +154,7 @@ EOF
RUNS $jira $blocker blocks $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -181,13 +186,13 @@ $(printf %-12s $blocker:) blocks
EOF
###############################################################################
# reset login for mojira for voting
# reset login for mothra for voting
###############################################################################
jira="$jira --user mojira"
jira="$jira --user mothra"
RUNS $jira logout
echo "mojira123" | RUNS $jira login
echo "mothra123" | RUNS $jira login
###############################################################################
## vote for main issue, verify it shows when viewing the issue
@@ -195,7 +200,7 @@ echo "mojira123" | RUNS $jira login
RUNS $jira vote $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -222,7 +227,7 @@ EOF
RUNS $jira vote $issue --down
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -244,19 +249,19 @@ description: |
EOF
###############################################################################
## set mojira user as watcher to issue and verify from REST api
## set mothra user as watcher to issue and verify from REST api
###############################################################################
RUNS $jira watch $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
# FIXME we probably need a watchers command to wrap this?
RUNS sh -c "$jira req /rest/api/2/issue/$issue/watchers | jq -r .watchers[].name"
RUNS sh -c "$jira req /rest/api/2/issue/$issue/watchers | jq -r .watchers[].name | sort"
DIFF <<EOF
gojira
mojira
mothra
EOF
###############################################################################
@@ -265,7 +270,7 @@ EOF
RUNS $jira trans "In Progress" $blocker --noedit
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -274,7 +279,7 @@ EOF
RUNS $jira todo $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -292,7 +297,7 @@ EOF
RUNS $jira todo $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -301,7 +306,7 @@ EOF
RUNS $jira prog $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -310,7 +315,7 @@ EOF
RUNS $jira done $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -341,7 +346,7 @@ EOF
RUNS $jira comment $issue --noedit -m "Yo, Comment"
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -362,7 +367,7 @@ description: |
description
comments:
- | # mojira, a minute ago
- | # mothra, a minute ago
Yo, Comment
EOF
@@ -373,7 +378,7 @@ EOF
RUNS $jira add labels $blocker test-label another-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -401,7 +406,7 @@ EOF
RUNS $jira remove labels $blocker another-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -429,7 +434,7 @@ EOF
RUNS $jira set labels $blocker more-label better-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -452,12 +457,12 @@ description: |
EOF
###############################################################################
## Verify that "mojira" user can take the issue (reassign to self)
## Verify that "mothra" user can take the issue (reassign to self)
###############################################################################
RUNS $jira take $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -468,7 +473,7 @@ status: Done
summary: blocks
project: SCRUM
issuetype: Bug
assignee: mojira
assignee: mothra
reporter: gojira
blockers:
depends: $issue[To Do]
@@ -485,7 +490,7 @@ EOF
RUNS $jira give $blocker gojira
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
+36 -31
View File
@@ -4,6 +4,11 @@ cd $(dirname $0)
jira="../jira --project KANBAN"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
PLAN 86
# cleanup from previous failed test executions
@@ -20,7 +25,7 @@ RUNS $jira create -o summary=summary -o description=description --noedit --saveF
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -67,7 +72,7 @@ EOF
RUNS $jira done $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -85,13 +90,13 @@ EOF
RUNS $jira create -o summary=summary -o description=description --noedit --saveFile issue.props
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira create -o summary=dup -o description=dup --noedit --saveFile issue.props
dup=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $dup http://localhost:8080/browse/$dup
OK $dup $ENDPOINT/browse/$dup
EOF
###############################################################################
@@ -102,8 +107,8 @@ EOF
RUNS $jira $dup dups $issue --noedit
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $dup http://localhost:8080/browse/$dup
OK $issue $ENDPOINT/browse/$issue
OK $dup $ENDPOINT/browse/$dup
EOF
RUNS $jira $issue
@@ -140,7 +145,7 @@ EOF
RUNS $jira create -o summary=blocks -o description=blocks --noedit --saveFile issue.props
blocker=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -149,7 +154,7 @@ EOF
RUNS $jira $blocker blocks $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -181,13 +186,13 @@ $(printf %-12s $blocker:) blocks
EOF
###############################################################################
# reset login for mojira for voting
# reset login for mothra for voting
###############################################################################
jira="$jira --user mojira"
jira="$jira --user mothra"
RUNS $jira logout
echo "mojira123" | RUNS $jira login
echo "mothra123" | RUNS $jira login
###############################################################################
## vote for main issue, verify it shows when viewing the issue
@@ -195,7 +200,7 @@ echo "mojira123" | RUNS $jira login
RUNS $jira vote $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -222,7 +227,7 @@ EOF
RUNS $jira vote $issue --down
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -244,19 +249,19 @@ description: |
EOF
###############################################################################
## set mojira user as watcher to issue and verify from REST api
## set mothra user as watcher to issue and verify from REST api
###############################################################################
RUNS $jira watch $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
# FIXME we probably need a watchers command to wrap this?
RUNS sh -c "$jira req /rest/api/2/issue/$issue/watchers | jq -r .watchers[].name"
RUNS sh -c "$jira req /rest/api/2/issue/$issue/watchers | jq -r .watchers[].name | sort"
DIFF <<EOF
gojira
mojira
mothra
EOF
###############################################################################
@@ -265,7 +270,7 @@ EOF
RUNS $jira trans "In Progress" $blocker --noedit
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -283,7 +288,7 @@ EOF
RUNS $jira backlog $blocker --noedit
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -301,7 +306,7 @@ EOF
RUNS $jira backlog $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -310,7 +315,7 @@ EOF
RUNS $jira prog $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -319,7 +324,7 @@ EOF
RUNS $jira done $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -350,7 +355,7 @@ EOF
RUNS $jira comment $issue --noedit -m "Yo, Comment"
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -371,7 +376,7 @@ description: |
description
comments:
- | # mojira, a minute ago
- | # mothra, a minute ago
Yo, Comment
EOF
@@ -382,7 +387,7 @@ EOF
RUNS $jira add labels $blocker test-label another-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -410,7 +415,7 @@ EOF
RUNS $jira remove labels $blocker another-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -438,7 +443,7 @@ EOF
RUNS $jira set labels $blocker more-label better-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -461,12 +466,12 @@ description: |
EOF
###############################################################################
## Verify that "mojira" user can take the issue (reassign to self)
## Verify that "mothra" user can take the issue (reassign to self)
###############################################################################
RUNS $jira take $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -477,7 +482,7 @@ status: Done
summary: blocks
project: KANBAN
issuetype: Bug
assignee: mojira
assignee: mothra
reporter: gojira
blockers:
depends: $issue[Backlog]
@@ -494,7 +499,7 @@ EOF
RUNS $jira give $blocker gojira
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
+39 -34
View File
@@ -4,6 +4,11 @@ cd $(dirname $0)
jira="../jira --project PROJECT"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
PLAN 84
# cleanup from previous failed test executions
@@ -20,7 +25,7 @@ RUNS $jira create -o summary=summary -o description=description --noedit --saveF
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -67,7 +72,7 @@ EOF
RUNS $jira done $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -85,13 +90,13 @@ EOF
RUNS $jira create -o summary=summary -o description=description --noedit --saveFile issue.props
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira create -o summary=dup -o description=dup --noedit --saveFile issue.props
dup=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $dup http://localhost:8080/browse/$dup
OK $dup $ENDPOINT/browse/$dup
EOF
###############################################################################
@@ -102,8 +107,8 @@ EOF
RUNS $jira $dup dups $issue --noedit
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $dup http://localhost:8080/browse/$dup
OK $issue $ENDPOINT/browse/$issue
OK $dup $ENDPOINT/browse/$dup
EOF
RUNS $jira $issue
@@ -140,7 +145,7 @@ EOF
RUNS $jira create -o summary=blocks -o description=blocks --noedit --saveFile issue.props
blocker=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -149,7 +154,7 @@ EOF
RUNS $jira $blocker blocks $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -181,13 +186,13 @@ $(printf %-12s $blocker:) blocks
EOF
###############################################################################
# reset login for mojira for voting
# reset login for mothra for voting
###############################################################################
jira="$jira --user mojira"
jira="$jira --user mothra"
RUNS $jira logout
echo "mojira123" | RUNS $jira login
echo "mothra123" | RUNS $jira login
###############################################################################
## vote for main issue, verify it shows when viewing the issue
@@ -195,7 +200,7 @@ echo "mojira123" | RUNS $jira login
RUNS $jira vote $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -222,7 +227,7 @@ EOF
RUNS $jira vote $issue --down
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -244,19 +249,19 @@ description: |
EOF
###############################################################################
## set mojira user as watcher to issue and verify from REST api
## set mothra user as watcher to issue and verify from REST api
###############################################################################
RUNS $jira watch $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
# FIXME we probably need a watchers command to wrap this?
RUNS sh -c "$jira req /rest/api/2/issue/$issue/watchers | jq -r .watchers[].name"
RUNS sh -c "$jira req /rest/api/2/issue/$issue/watchers | jq -r .watchers[].name | sort"
DIFF <<EOF
gojira
mojira
mothra
EOF
###############################################################################
@@ -279,12 +284,12 @@ ERROR Invalid Transition 'review', Available: Start Progress, Done
EOF
###############################################################################
## Set it to "Start Progress" and verify that assignee is set to mojira
## Set it to "Start Progress" and verify that assignee is set to mothra
###############################################################################
RUNS $jira start $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -295,7 +300,7 @@ status: In Progress
summary: blocks
project: PROJECT
issuetype: Task
assignee: mojira
assignee: mothra
reporter: gojira
blockers:
depends: $issue[To Do]
@@ -311,7 +316,7 @@ EOF
RUNS $jira stop $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
@@ -321,7 +326,7 @@ EOF
RUNS $jira done $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -352,7 +357,7 @@ EOF
RUNS $jira comment $issue --noedit -m "Yo, Comment"
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -373,7 +378,7 @@ description: |
description
comments:
- | # mojira, a minute ago
- | # mothra, a minute ago
Yo, Comment
EOF
@@ -384,7 +389,7 @@ EOF
RUNS $jira add labels $blocker test-label another-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -395,7 +400,7 @@ status: Done
summary: blocks
project: PROJECT
issuetype: Task
assignee: mojira
assignee: mothra
reporter: gojira
blockers:
depends: $issue[To Do]
@@ -412,7 +417,7 @@ EOF
RUNS $jira remove labels $blocker another-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -423,7 +428,7 @@ status: Done
summary: blocks
project: PROJECT
issuetype: Task
assignee: mojira
assignee: mothra
reporter: gojira
blockers:
depends: $issue[To Do]
@@ -440,7 +445,7 @@ EOF
RUNS $jira set labels $blocker more-label better-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -451,7 +456,7 @@ status: Done
summary: blocks
project: PROJECT
issuetype: Task
assignee: mojira
assignee: mothra
reporter: gojira
blockers:
depends: $issue[To Do]
@@ -468,7 +473,7 @@ EOF
RUNS $jira give $blocker gojira
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -491,12 +496,12 @@ description: |
EOF
###############################################################################
## Verify that "mojira" user can take the issue (reassign to self)
## Verify that "mothra" user can take the issue (reassign to self)
###############################################################################
RUNS $jira take $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -507,7 +512,7 @@ status: Done
summary: blocks
project: PROJECT
issuetype: Task
assignee: mojira
assignee: mothra
reporter: gojira
blockers:
depends: $issue[To Do]
+36 -31
View File
@@ -4,6 +4,11 @@ cd $(dirname $0)
jira="../jira --project PROCESS"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
PLAN 84
# cleanup from previous failed test executions
@@ -21,7 +26,7 @@ RUNS $jira create -o summary=summary -o description=description --noedit --saveF
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -69,13 +74,13 @@ EOF
RUNS $jira start $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira stop $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -93,13 +98,13 @@ EOF
RUNS $jira create -o summary=summary -o description=description --noedit --saveFile issue.props
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira create -o summary=dup -o description=dup --noedit --saveFile issue.props
dup=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $dup http://localhost:8080/browse/$dup
OK $dup $ENDPOINT/browse/$dup
EOF
###############################################################################
@@ -112,9 +117,9 @@ EOF
RUNS $jira $dup dups $issue --noedit
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $dup http://localhost:8080/browse/$dup
OK $dup http://localhost:8080/browse/$dup
OK $issue $ENDPOINT/browse/$issue
OK $dup $ENDPOINT/browse/$dup
OK $dup $ENDPOINT/browse/$dup
EOF
RUNS $jira $issue
@@ -151,7 +156,7 @@ EOF
RUNS $jira create -o summary=blocks -o description=blocks --noedit --saveFile issue.props
blocker=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -160,7 +165,7 @@ EOF
RUNS $jira $blocker blocks $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -192,13 +197,13 @@ $(printf %-12s $blocker:) blocks
EOF
###############################################################################
# reset login for mojira for voting
# reset login for mothra for voting
###############################################################################
jira="$jira --user mojira"
jira="$jira --user mothra"
RUNS $jira logout
echo "mojira123" | RUNS $jira login
echo "mothra123" | RUNS $jira login
###############################################################################
## vote for main issue, verify it shows when viewing the issue
@@ -206,7 +211,7 @@ echo "mojira123" | RUNS $jira login
RUNS $jira vote $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -233,7 +238,7 @@ EOF
RUNS $jira vote $issue --down
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -255,19 +260,19 @@ description: |
EOF
###############################################################################
## set mojira user as watcher to issue and verify from REST api
## set mothra user as watcher to issue and verify from REST api
###############################################################################
RUNS $jira watch $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
# FIXME we probably need a watchers command to wrap this?
RUNS sh -c "$jira req /rest/api/2/issue/$issue/watchers | jq -r .watchers[].name"
RUNS sh -c "$jira req /rest/api/2/issue/$issue/watchers | jq -r .watchers[].name | sort"
DIFF <<EOF
gojira
mojira
mothra
EOF
###############################################################################
@@ -295,7 +300,7 @@ EOF
RUNS $jira start $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -304,7 +309,7 @@ EOF
RUNS $jira stop $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
@@ -314,7 +319,7 @@ EOF
RUNS $jira reopen $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -345,7 +350,7 @@ EOF
RUNS $jira comment $issue --noedit -m "Yo, Comment"
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -366,7 +371,7 @@ description: |
description
comments:
- | # mojira, a minute ago
- | # mothra, a minute ago
Yo, Comment
EOF
@@ -377,7 +382,7 @@ EOF
RUNS $jira add labels $blocker test-label another-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -405,7 +410,7 @@ EOF
RUNS $jira remove labels $blocker another-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -433,7 +438,7 @@ EOF
RUNS $jira set labels $blocker more-label better-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -456,12 +461,12 @@ description: |
EOF
###############################################################################
## Verify that "mojira" user can take the issue (reassign to self)
## Verify that "mothra" user can take the issue (reassign to self)
###############################################################################
RUNS $jira take $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -472,7 +477,7 @@ status: Open
summary: blocks
project: PROCESS
issuetype: Task
assignee: mojira
assignee: mothra
reporter: gojira
blockers:
depends: $issue[Open]
@@ -489,7 +494,7 @@ EOF
RUNS $jira give $blocker gojira
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
+32 -27
View File
@@ -4,6 +4,11 @@ cd $(dirname $0)
jira="../jira --project TASK"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
PLAN 82
# cleanup from previous failed test executions
@@ -20,7 +25,7 @@ RUNS $jira create -o summary=summary -o description=description --noedit --saveF
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -67,7 +72,7 @@ EOF
RUNS $jira done $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
@@ -85,13 +90,13 @@ EOF
RUNS $jira create -o summary=summary -o description=description --noedit --saveFile issue.props
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira create -o summary=dup -o description=dup --noedit --saveFile issue.props
dup=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $dup http://localhost:8080/browse/$dup
OK $dup $ENDPOINT/browse/$dup
EOF
###############################################################################
@@ -104,8 +109,8 @@ EOF
RUNS $jira $dup dups $issue --noedit
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $dup http://localhost:8080/browse/$dup
OK $issue $ENDPOINT/browse/$issue
OK $dup $ENDPOINT/browse/$dup
EOF
RUNS $jira $issue
@@ -142,7 +147,7 @@ EOF
RUNS $jira create -o summary=blocks -o description=blocks --noedit --saveFile issue.props
blocker=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -151,7 +156,7 @@ EOF
RUNS $jira $blocker blocks $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -183,13 +188,13 @@ $(printf %-12s $blocker:) blocks
EOF
###############################################################################
# reset login for mojira for voting
# reset login for mothra for voting
###############################################################################
jira="$jira --user mojira"
jira="$jira --user mothra"
RUNS $jira logout
echo "mojira123" | RUNS $jira login
echo "mothra123" | RUNS $jira login
###############################################################################
## vote for main issue, verify it shows when viewing the issue
@@ -197,7 +202,7 @@ echo "mojira123" | RUNS $jira login
RUNS $jira vote $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -224,7 +229,7 @@ EOF
RUNS $jira vote $issue --down
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -246,19 +251,19 @@ description: |
EOF
###############################################################################
## set mojira user as watcher to issue and verify from REST api
## set mothra user as watcher to issue and verify from REST api
###############################################################################
RUNS $jira watch $issue
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
# FIXME we probably need a watchers command to wrap this?
RUNS sh -c "$jira req /rest/api/2/issue/$issue/watchers | jq -r .watchers[].name"
RUNS sh -c "$jira req /rest/api/2/issue/$issue/watchers | jq -r .watchers[].name | sort"
DIFF <<EOF
gojira
mojira
mothra
EOF
###############################################################################
@@ -305,7 +310,7 @@ EOF
RUNS $jira done $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
###############################################################################
@@ -336,7 +341,7 @@ EOF
RUNS $jira comment $issue --noedit -m "Yo, Comment"
DIFF <<EOF
OK $issue http://localhost:8080/browse/$issue
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
@@ -357,7 +362,7 @@ description: |
description
comments:
- | # mojira, a minute ago
- | # mothra, a minute ago
Yo, Comment
EOF
@@ -368,7 +373,7 @@ EOF
RUNS $jira add labels $blocker test-label another-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -396,7 +401,7 @@ EOF
RUNS $jira remove labels $blocker another-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -424,7 +429,7 @@ EOF
RUNS $jira set labels $blocker more-label better-label
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -447,12 +452,12 @@ description: |
EOF
###############################################################################
## Verify that "mojira" user can take the issue (reassign to self)
## Verify that "mothra" user can take the issue (reassign to self)
###############################################################################
RUNS $jira take $blocker
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
@@ -463,7 +468,7 @@ status: Done
summary: blocks
project: TASK
issuetype: Task
assignee: mojira
assignee: mothra
reporter: gojira
blockers:
depends: $issue[To Do]
@@ -480,7 +485,7 @@ EOF
RUNS $jira give $blocker gojira
DIFF <<EOF
OK $blocker http://localhost:8080/browse/$blocker
OK $blocker $ENDPOINT/browse/$blocker
EOF
RUNS $jira $blocker
+20
View File
@@ -0,0 +1,20 @@
FROM alpine:latest
RUN apk --update add openjdk8-jre curl screen && \
curl -s -L https://marketplace.atlassian.com/download/plugins/atlassian-plugin-sdk-tgz | tar xzf - && \
ln -s /atlassian* /atlassian
ENV PATH=/bin:/usr/bin:/atlassian/bin
# Copy in the serivce and also the root .m2 settings to force cache everything.
# We also copy in /root/.java settings to prevent the dumb spam prompt from
# the atlas-run command:
# Would you like to subscribe to the Atlassian developer mailing list? (Y/y/N/n) Y: :
COPY dockerroot /
WORKDIR /jiratestservice
EXPOSE 8080
# we wrap the command with screen so that the dumb atlas-run has a tty to watch. Without screen
# there is no tty so atlas-run will immediately read an EOF (aka CTRL-D) and interpret that to
# mean we want the service to begin the "graceful shutdown" and exit
CMD ["screen", "-DmL", "atlas-run", "--http-port", "8080", "--context-path", "ROOT", "--server", "localhost"]
-3
View File
@@ -1,3 +0,0 @@
RUN curl -Ls https://raw.githubusercontent.com/cptactionhank/docker-atlassian-jira-software/master/docker-entrypoint.sh -o /docker-entrypoint.sh \
&& chmod 755 /docker-entrypoint.sh \
&& echo jira.websudo.is.disabled = true >> /var/atlassian/jira/jira-config.properties
-3
View File
@@ -1,3 +0,0 @@
INCLUDE MERGE -VOLUME -COPY \
https://raw.githubusercontent.com/cptactionhank/docker-atlassian-jira-software/master/Dockerfile \
Dockerfile.inc
+16 -33
View File
@@ -2,39 +2,6 @@
The test are written using the `osht` bash testing framework. Please read the [documentation](https://github.com/coryb/osht/blob/master/README.md) for `osht`.
## Setup
These tests assume there is a jira service running at 127.0.0.1:8080 with user "gojira" and password "gojira123".
There should also be a poweruser "admin" with password "admin123"
The test Jira was setup following the instructions [here](https://github.com/cptactionhank/docker-atlassian-jira).
### build base docker image
```
docker run --rm -i -v $(pwd):/root:ro coryb/dfpp:1.0.2 Dockerfile.pre | docker build -t go-jira-base:latest -
```
### Initialize container
```
docker run --detach --name go-jira-test --publish 8080:8080 go-jira-base:latest
```
### create admin user
```
open http://localhost:8080
```
Then follow UI workflow to create "admin" user, skip intro and project creation.
### snapshot docker container
```
docker commit go-jira-test go-jira-test:latest
```
### Destroy base container
```
docker rm -f go-jira-test
```
## Running Test:
From the top level of the project you can run:
@@ -46,8 +13,24 @@ make
prove
```
### Running individual tests
To run a specific test you can run it directly like:
```
./100basic.t
```
There is a useful `-v` option to make the test more verbose and an `-a` option to casue the test to abort after the first failure.
The tests all require the jira service to be running from the docker container, so you will have to manually run the setup script:
```
./000setup.t
```
After than you can run the other tests over and over. The jira service is just a test instance started for local development. It comes with
a temporary license (I think it is 8 hours) so you will have to run the `./000setup.t` script at least once daily.
## API Documentation:
https://docs.atlassian.com/jira/REST/cloud/
https://docs.atlassian.com/jira-software/REST/cloud
## projectTempalteKey missing documentation
https://answers.atlassian.com/questions/36176301/jira-api-7.1.0-create-project
+6
View File
@@ -0,0 +1,6 @@
To avoid future confusion, we recommend that you include a license with your plugin.
This file is simply a reminder.
For a template license you can have a look at: http://www.opensource.org/licenses/
Atlassian releases most of its modules under the Apache2 license: http://opensource.org/licenses/Apache-2.0
+13
View File
@@ -0,0 +1,13 @@
You have successfully created an Atlassian Plugin!
Here are the SDK commands you'll use immediately:
* atlas-run -- installs this plugin into the product and starts it on localhost
* atlas-debug -- same as atlas-run, but allows a debugger to attach at port 5005
* atlas-cli -- after atlas-run or atlas-debug, opens a Maven command line window:
- 'pi' reinstalls the plugin into the running product instance
* atlas-help -- prints description for all commands in the SDK
Full documentation is always available at:
https://developer.atlassian.com/display/DOCS/Introduction+to+the+Atlassian+Plugin+SDK
+185
View File
@@ -0,0 +1,185 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.netflixskunkworks</groupId>
<artifactId>jiratestservice</artifactId>
<version>1.0</version>
<organization>
<name>Example Company</name>
<url>http://www.example.com/</url>
</organization>
<name>jiratestservice</name>
<description>This is the com.netflixskunkworks:jiratestservice plugin for Atlassian JIRA.</description>
<packaging>atlassian-plugin</packaging>
<dependencies>
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-api</artifactId>
<version>${jira.version}</version>
<scope>provided</scope>
</dependency>
<!-- Add dependency on jira-core if you want access to JIRA implementation classes as well as the sanctioned API. -->
<!-- This is not normally recommended, but may be required eg when migrating a plugin originally developed against JIRA 4.x -->
<!--
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-core</artifactId>
<version>${jira.version}</version>
<scope>provided</scope>
</dependency>
-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-annotation</artifactId>
<version>${atlassian.spring.scanner.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-runtime</artifactId>
<version>${atlassian.spring.scanner.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<scope>provided</scope>
</dependency>
<!-- WIRED TEST RUNNER DEPENDENCIES -->
<dependency>
<groupId>com.atlassian.plugins</groupId>
<artifactId>atlassian-plugins-osgi-testrunner</artifactId>
<version>${plugin.testrunner.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.2-atlassian-1</version>
</dependency>
<!-- Uncomment to use TestKit in your project. Details at https://bitbucket.org/atlassian/jira-testkit -->
<!-- You can read more about TestKit at https://developer.atlassian.com/display/JIRADEV/Plugin+Tutorial+-+Smarter+integration+testing+with+TestKit -->
<!--
<dependency>
<groupId>com.atlassian.jira.tests</groupId>
<artifactId>jira-testkit-client</artifactId>
<version>${testkit.version}</version>
<scope>test</scope>
</dependency>
-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-jira-plugin</artifactId>
<version>${amps.version}</version>
<extensions>true</extensions>
<configuration>
<applications>
<application>
<applicationKey>jira-software</applicationKey>
<version>${jira.version}</version>
</application>
</applications>
<productVersion>${jira.version}</productVersion>
<productDataVersion>${jira.version}</productDataVersion>
<!-- Uncomment to install TestKit backdoor in JIRA. -->
<!--
<pluginArtifacts>
<pluginArtifact>
<groupId>com.atlassian.jira.tests</groupId>
<artifactId>jira-testkit-plugin</artifactId>
<version>${testkit.version}</version>
</pluginArtifact>
</pluginArtifacts>
-->
<enableQuickReload>true</enableQuickReload>
<enableFastdev>false</enableFastdev>
<!-- See here for an explanation of default instructions: -->
<!-- https://developer.atlassian.com/docs/advanced-topics/configuration-of-instructions-in-atlassian-plugins -->
<instructions>
<Atlassian-Plugin-Key>${atlassian.plugin.key}</Atlassian-Plugin-Key>
<!-- Add package to export here -->
<Export-Package>
com.netflixskunkworks.api,
</Export-Package>
<!-- Add package import here -->
<Import-Package>
org.springframework.osgi.*;resolution:="optional",
org.eclipse.gemini.blueprint.*;resolution:="optional",
*
</Import-Package>
<!-- Ensure plugin is spring powered -->
<Spring-Context>*</Spring-Context>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
<version>${atlassian.spring.scanner.version}</version>
<executions>
<execution>
<goals>
<goal>atlassian-spring-scanner</goal>
</goals>
<phase>process-classes</phase>
</execution>
</executions>
<configuration>
<scannedDependencies>
<dependency>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-external-jar</artifactId>
</dependency>
</scannedDependencies>
<verbose>false</verbose>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<jira.version>7.2.0</jira.version>
<amps.version>6.2.6</amps.version>
<plugin.testrunner.version>1.2.3</plugin.testrunner.version>
<atlassian.spring.scanner.version>1.2.13</atlassian.spring.scanner.version>
<!-- This key is used to keep the consistency between the key in atlassian-plugin.xml and the key to generate bundle. -->
<atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
<!-- TestKit version 6.x for JIRA 6.x -->
<testkit.version>6.3.11</testkit.version>
</properties>
</project>
@@ -0,0 +1,7 @@
<atlassian-plugin key="${atlassian.plugin.key}" name="${project.name}" plugins-version="2">
<plugin-info>
<description>${project.description}</description>
<version>${project.version}</version>
<vendor name="${project.organization.name}" url="${project.organization.url}" />
</plugin-info>
</atlassian-plugin>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE map SYSTEM "http://java.sun.com/dtd/preferences.dtd">
<map MAP_XML_VERSION="1.0">
<entry key="sdk-email-subscribe" value="true"/>
</map>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE map SYSTEM "http://java.sun.com/dtd/preferences.dtd">
<map MAP_XML_VERSION="1.0">
<entry key="last_update_check" value="2016-08-29"/>
<entry key="sdk-pom-update-check-6.2.6-cbc3c672c37f65828d50132ed303cf7a" value="true"/>
</map>
+77
View File
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<profiles>
<!-- Default profile containing Atlassian servers -->
<profile>
<id>defaultProfile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>atlassian-public</id>
<url>https://maven.atlassian.com/repository/public</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</snapshots>
<releases>
<enabled>true</enabled>
<checksumPolicy>warn</checksumPolicy>
<updatePolicy>never</updatePolicy>
</releases>
</repository>
<repository>
<id>atlassian-plugin-sdk</id>
<url>file://${env.ATLAS_HOME}/repository</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
<releases>
<enabled>true</enabled>
<checksumPolicy>warn</checksumPolicy>
<updatePolicy>never</updatePolicy>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>atlassian-public</id>
<url>https://maven.atlassian.com/repository/public</url>
<releases>
<enabled>true</enabled>
<checksumPolicy>warn</checksumPolicy>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<updatePolicy>never</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>atlassian-plugin-sdk</id>
<url>file://${env.ATLAS_HOME}/repository</url>
<releases>
<enabled>true</enabled>
<checksumPolicy>warn</checksumPolicy>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>
<properties>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</properties>
</profile>
</profiles>
</settings>
+115 -37
View File
@@ -15,6 +15,7 @@ var allTemplates = map[string]string{
"components": defaultComponentsTemplate,
"issuetypes": defaultIssuetypesTemplate,
"create": defaultCreateTemplate,
"subtask": defaultSubtaskTemplate,
"comment": defaultCommentTemplate,
"transition": defaultTransitionTemplate,
"request": defaultDebugTemplate,
@@ -29,34 +30,59 @@ const defaultListTemplate = "{{ range .issues }}{{ .key | append \":\" | printf
const defaultTableTemplate = `+{{ "-" | rep 16 }}+{{ "-" | rep 57 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
| {{ "Issue" | printf "%-14s" }} | {{ "Summary" | printf "%-55s" }} | {{ "Priority" | printf "%-12s" }} | {{ "Status" | printf "%-12s" }} | {{ "Age" | printf "%-10s" }} | {{ "Reporter" | printf "%-12s" }} | {{ "Assignee" | printf "%-12s" }} |
+{{ "-" | rep 16 }}+{{ "-" | rep 57 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
{{ range .issues }}| {{ .key | printf "%-14s"}} | {{ .fields.summary | abbrev 55 | printf "%-55s" }} | {{.fields.priority.name | printf "%-12s" }} | {{.fields.status.name | printf "%-12s" }} | {{.fields.created | age | printf "%-10s" }} | {{if .fields.reporter}}{{ .fields.reporter.name | printf "%-12s"}}{{else}}<unassigned>{{end}} | {{if .fields.assignee }}{{.fields.assignee.name | printf "%-12s" }}{{else}}<unassigned>{{end}} |
{{ end }}+{{ "-" | rep 16 }}+{{ "-" | rep 57 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
{{ range .issues -}}
| {{ .key | printf "%-14s"}} | {{ .fields.summary | abbrev 55 | printf "%-55s" }} | {{.fields.priority.name | printf "%-12s" }} | {{.fields.status.name | printf "%-12s" }} | {{.fields.created | age | printf "%-10s" }} | {{if .fields.reporter}}{{ .fields.reporter.name | printf "%-12s"}}{{else}}<unassigned>{{end}} | {{if .fields.assignee }}{{.fields.assignee.name | printf "%-12s" }}{{else}}<unassigned> {{end}} |
{{ end -}}
+{{ "-" | rep 16 }}+{{ "-" | rep 57 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
`
const defaultViewTemplate = `issue: {{ .key }}{{if .fields.created}}
created: {{ .fields.created | age }} ago{{end}}{{if .fields.status}}
status: {{ .fields.status.name }}{{end}}
const defaultViewTemplate = `{{/* view template */ -}}
issue: {{ .key }}
{{if .fields.created -}}
created: {{ .fields.created | age }} ago
{{end -}}
{{if .fields.status -}}
status: {{ .fields.status.name }}
{{end -}}
summary: {{ .fields.summary }}
project: {{ .fields.project.key }}{{if .fields.components}}
components: {{ range .fields.components }}{{ .name }} {{end}}{{end}}{{if .fields.issuetype}}
issuetype: {{ .fields.issuetype.name }}{{end}}{{if .fields.assignee}}
assignee: {{ .fields.assignee.name }}{{end}}
reporter: {{ if .fields.reporter }}{{ .fields.reporter.name }}{{end}}{{if .fields.customfield_10110}}
watchers: {{ range .fields.customfield_10110 }}{{ .name }} {{end}}{{end}}{{if .fields.issuelinks}}
project: {{ .fields.project.key }}
{{if .fields.components -}}
components: {{ range .fields.components }}{{ .name }} {{end}}
{{end -}}
{{if .fields.issuetype -}}
issuetype: {{ .fields.issuetype.name }}
{{end -}}
{{if .fields.assignee -}}
assignee: {{ .fields.assignee.name }}
{{end -}}
reporter: {{ if .fields.reporter }}{{ .fields.reporter.name }}{{end}}
{{if .fields.customfield_10110 -}}
watchers: {{ range .fields.customfield_10110 }}{{ .name }} {{end}}
{{end -}}
{{if .fields.issuelinks -}}
blockers: {{ range .fields.issuelinks }}{{if .outwardIssue}}{{ .outwardIssue.key }}[{{.outwardIssue.fields.status.name}}]{{end}}{{end}}
depends: {{ range .fields.issuelinks }}{{if .inwardIssue}}{{ .inwardIssue.key }}[{{.inwardIssue.fields.status.name}}]{{end}}{{end}}{{end}}{{if .fields.priority}}
priority: {{ .fields.priority.name }}{{end}}{{if .fields.votes}}
votes: {{ .fields.votes.votes}}{{end}}{{if .fields.labels}}
labels: {{ join ", " .fields.labels }}{{end}}
depends: {{ range .fields.issuelinks }}{{if .inwardIssue}}{{ .inwardIssue.key }}[{{.inwardIssue.fields.status.name}}]{{end}}{{end}}
{{end -}}
{{if .fields.priority -}}
priority: {{ .fields.priority.name }}
{{end -}}
{{if .fields.votes -}}
votes: {{ .fields.votes.votes}}
{{end -}}
{{if .fields.labels -}}
labels: {{ join ", " .fields.labels }}
{{end -}}
description: |
{{ or .fields.description "" | indent 2 }}{{if .fields.comment.comments}}
{{ or .fields.description "" | indent 2 }}
{{if .fields.comment.comments}}
comments:
{{ range .fields.comment.comments }} - | # {{.author.name}}, {{.created | age}} ago
{{ or .body "" | indent 4}}
{{end}}{{end}}
{{end}}
{{end -}}
`
const defaultEditTemplate = `# issue: {{ .key }}
const defaultEditTemplate = `{{/* edit template */ -}}
# issue: {{ .key }}
update:
comment:
- add:
@@ -69,8 +95,8 @@ fields:
- name: {{ .name }}{{end}}{{end}}
assignee:
name: {{ if .overrides.assignee }}{{.overrides.assignee}}{{else}}{{if .fields.assignee }}{{ .fields.assignee.name }}{{end}}{{end}}
# reporter:
# name: {{ if .overrides.reporter }}{{ .overrides.reporter }}{{else if .fields.reporter}}{{ .fields.reporter.name }}{{end}}
reporter:
name: {{ if .overrides.reporter }}{{ .overrides.reporter }}{{else if .fields.reporter}}{{ .fields.reporter.name }}{{end}}
# watchers
customfield_10110: {{ range .fields.customfield_10110 }}
- name: {{ .name }}{{end}}{{if .overrides.watcher}}
@@ -93,7 +119,8 @@ const defaultComponentsTemplate = `{{ range . }}{{.id }}: {{.name}}
const defaultIssuetypesTemplate = `{{ range .projects }}{{ range .issuetypes }}{{color "+bh"}}{{.name | append ":" | printf "%-13s" }}{{color "reset"}} {{.description}}
{{end}}{{end}}`
const defaultCreateTemplate = `fields:
const defaultCreateTemplate = `{{/* create template */ -}}
fields:
project:
key: {{ or .overrides.project "" }}
issuetype:
@@ -114,53 +141,104 @@ const defaultCreateTemplate = `fields:
- name: {{.}}{{end}}
- name:{{end}}`
const defaultSubtaskTemplate = `{{/* create subtask template */ -}}
fields:
project:
key: {{ .parent.fields.project.key }}
summary: {{ or .overrides.summary "" }}{{if .meta.fields.priority.allowedValues}}
priority: # Values: {{ range .meta.fields.priority.allowedValues }}{{.name}}, {{end}}
name: {{ or .overrides.priority ""}}{{end}}{{if .meta.fields.components.allowedValues}}
components: # Values: {{ range .meta.fields.components.allowedValues }}{{.name}}, {{end}}{{ range split "," (or .overrides.components "")}}
- name: {{ . }}{{end}}{{end}}
description: |~
{{ or .overrides.description "" | indent 4 }}{{if .meta.fields.assignee}}
assignee:
name: {{ or .overrides.assignee "" }}{{end}}{{if .meta.fields.reporter}}
reporter:
name: {{ or .overrides.reporter .overrides.user }}{{end}}{{if .meta.fields.customfield_10110}}
# watchers
customfield_10110: {{ range split "," (or .overrides.watchers "")}}
- name: {{.}}{{end}}
- name:{{end}}
issuetype:
name: Sub-task
parent:
key: {{ .parent.key }}`
const defaultCommentTemplate = `body: |~
{{ or .overrides.comment "" | indent 2 }}
`
const defaultTransitionTemplate = `update:
const defaultTransitionTemplate = `{{/* transition template */ -}}
update:
comment:
- add:
body: |~
{{ or .overrides.comment "" | indent 10 }}
fields:{{if .meta.fields.assignee}}
fields:
{{- if .meta.fields.assignee}}
assignee:
name: {{if .overrides.assignee}}{{.overrides.assignee}}{{else}}{{if .fields.assignee}}{{.fields.assignee.name}}{{end}}{{end}}{{end}}{{if .meta.fields.components}}
name: {{if .overrides.assignee}}{{.overrides.assignee}}{{else}}{{if .fields.assignee}}{{.fields.assignee.name}}{{end}}{{end}}
{{- end -}}
{{if .meta.fields.components}}
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}}{{end}}{{if .meta.fields.description}}
description: {{or .overrides.description .fields.description }}{{end}}{{if .meta.fields.fixVersions}}{{if .meta.fields.fixVersions.allowedValues}}
- name: {{ .name }}{{end}}{{end}}
{{- end -}}
{{if .meta.fields.description}}
description: {{or .overrides.description .fields.description }}
{{- end -}}
{{if .meta.fields.fixVersions -}}
{{if .meta.fields.fixVersions.allowedValues}}
fixVersions: # Values: {{ range .meta.fields.fixVersions.allowedValues }}{{.name}}, {{end}}{{if .overrides.fixVersions}}{{ range (split "," .overrides.fixVersions)}}
- name: {{.}}{{end}}{{else}}{{range .fields.fixVersions}}
- name: {{.}}{{end}}{{end}}{{end}}{{end}}{{if .meta.fields.issuetype}}
- name: {{.}}{{end}}{{end}}
{{- end -}}
{{- end -}}
{{if .meta.fields.issuetype}}
issuetype: # Values: {{ range .meta.fields.issuetype.allowedValues }}{{.name}}, {{end}}
name: {{if .overrides.issuetype}}{{.overrides.issuetype}}{{else}}{{if .fields.issuetype}}{{.fields.issuetype.name}}{{end}}{{end}}{{end}}{{if .meta.fields.labels}}
name: {{if .overrides.issuetype}}{{.overrides.issuetype}}{{else}}{{if .fields.issuetype}}{{.fields.issuetype.name}}{{end}}{{end}}
{{- end -}}
{{if .meta.fields.labels}}
labels: {{range .fields.labels}}
- {{.}}{{end}}{{if .overrides.labels}}{{range (split "," .overrides.labels)}}
- {{.}}{{end}}{{end}}{{end}}{{if .meta.fields.priority}}
- {{.}}{{end}}{{end}}
{{- end -}}
{{if .meta.fields.priority}}
priority: # Values: {{ range .meta.fields.priority.allowedValues }}{{.name}}, {{end}}
name: {{ or .overrides.priority "unassigned" }}{{end}}{{if .meta.fields.reporter}}
name: {{ or .overrides.priority "unassigned" }}
{{- end -}}
{{if .meta.fields.reporter}}
reporter:
name: {{if .overrides.reporter}}{{.overrides.reporter}}{{else}}{{if .fields.reporter}}{{.fields.reporter.name}}{{end}}{{end}}{{end}}{{if .meta.fields.resolution}}
name: {{if .overrides.reporter}}{{.overrides.reporter}}{{else}}{{if .fields.reporter}}{{.fields.reporter.name}}{{end}}{{end}}
{{- end -}}
{{if .meta.fields.resolution}}
resolution: # Values: {{ range .meta.fields.resolution.allowedValues }}{{.name}}, {{end}}
name: {{if .overrides.resolution}}{{.overrides.resolution}}{{else if .fields.resolution}}{{.fields.resolution.name}}{{else}}{{or .overrides.defaultResolution "Fixed"}}{{end}}{{end}}{{if .meta.fields.summary}}
summary: {{or .overrides.summary .fields.summary}}{{end}}{{if .meta.fields.versions.allowedValues}}
name: {{if .overrides.resolution}}{{.overrides.resolution}}{{else if .fields.resolution}}{{.fields.resolution.name}}{{else}}{{or .overrides.defaultResolution "Fixed"}}{{end}}
{{- end -}}
{{if .meta.fields.summary}}
summary: {{or .overrides.summary .fields.summary}}
{{- end -}}
{{if .meta.fields.versions.allowedValues}}
versions: # Values: {{ range .meta.fields.versions.allowedValues }}{{.name}}, {{end}}{{if .overrides.versions}}{{ range (split "," .overrides.versions)}}
- name: {{.}}{{end}}{{else}}{{range .fields.versions}}
- name: {{.}}{{end}}{{end}}{{end}}
- name: {{.}}{{end}}{{end}}
{{- end}}
transition:
id: {{ .transition.id }}
name: {{ .transition.name }}
`
const defaultWorklogTemplate = `# issue: {{ .issue }}
const defaultWorklogTemplate = `{{/* worklog template */ -}}
# issue: {{ .issue }}
comment: |~
{{ or .comment "" }}
timeSpent: {{ or .timeSpent "" }}
started:
`
const defaultWorklogsTemplate = `{{ range .worklogs }}- # {{.author.name}}, {{.created | age}} ago
const defaultWorklogsTemplate = `{{/* worklogs template */ -}}
{{ range .worklogs }}- # {{.author.name}}, {{.created | age}} ago
comment: {{ or .comment "" }}
timeSpent: {{ .timeSpent }}
+41
View File
@@ -0,0 +1,41 @@
package jira
import (
"fmt"
"net"
"net/http"
"os"
"time"
)
type Transport struct {
shadow http.Transport
}
func NewUnixProxyTransport(path string) *Transport {
dial := func(network, addr string) (net.Conn, error) {
return net.Dial("unix", path)
}
shadow := http.Transport{
Dial: dial,
DialTLS: dial,
DisableKeepAlives: true,
ResponseHeaderTimeout: 30 * time.Second,
ExpectContinueTimeout: 10 * time.Second,
}
return &Transport{shadow}
}
func UnixProxy(path string) *Transport {
return NewUnixProxyTransport(os.ExpandEnv(path))
}
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
req2 := *req
url2 := *req.URL
req2.URL = &url2
req2.URL.Opaque = fmt.Sprintf("//%s%s", req.URL.Host, req.URL.EscapedPath())
return t.shadow.RoundTrip(&req2)
}