simple command line client for Atlassian's Jira service written in Go
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
jira ls -t table -p GOJIRA # list all unresolved issues in pretty table output
jira view GOJIRA-321 # print Issue using "view" template
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 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." \
-o priority=Major
jira create -p GOJIRA # create new "Bug" type issue for project GOJIRA
jira create -p GOJIRA -i Task # create new Task type issue
jira trans close GOJIRA-321 # close issue, with interactive editor to set fields
jira close GOJIRA-321 --edit # same as above
# close the issue, set the resolution, and skip interactive editor:
jira trans close GOJIRA-321 -o resolution="Won't Fix" --noedit
# same as above
jira close GOJIRA-321 -o resolution="Won't Fix"
jira reopen GOJIRA-321 -m "reopening" # reopen issue
jira watch GOJIRA-321 # add self as watcher to the issue
jira comment GOJIRA-321 -m "done yet?" # add comment to the issue
jira take GOJIRA-321 # assign issue to self
jira give GOJIRA-321 mothra # assign issue to user mothra
# create local project config to set defaults
mkdir .jira.d
echo "project: GOJIRA" > .jira.d/config.yml
jira ls # list all unresolved issues for project GOJRIA
jira ls -a mothra # as above also assigned to user mothra
jira ls -w mothra # lists GOJIRA unresolved issues watched by user mothra
jira ls -r mothra # list GOJIRA unresolved issues reported by user mothra
jira ls -t table # list all unresolved issues in pretty table output
jira create # create new "Bug" type issue for project GOJIRA
jira create -i Task # create new Task type issue
# make the table template your default "list" template:
jira export-templates -t table
mv $HOME/.jira.d/templates/table $HOME/.jira.d/templates/list
You can download one of the pre-built binaries for go-jira here.
-
NOTE You will need
go-1.4.1
minimum -
To build the
jira
binary the current directory just run:
make
- To install the binary to you ~/bin directory you can run:
make install
go-jira uses a configuration hierarchy. When loading the configuration from disk it will recursively look through all parent directories in your current path looking for a .jira.d directory. If your current directory is not a child directory of your homedir, then your homedir will also be inspected for a .jira.d directory. From all of .jira.d directories 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 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:
project: foo
You will need to specify your local jira endpoint first, typically in your homedir like:
mkdir ~/.jira.d
cat <<EOM >~/.jira.d/config.yml
endpoint: https://jira.mycompany.com
EOM
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
If the .jira.d/config.yml file is executable, then go-jira will attempt to execute the file and use the stdout for configuration. You can use this to customize templates or other overrides depending on what type of operation you are running. For example if you would like to use the "table" template when ever you run jira ls
, then you can create a template like this:
#!/bin/sh
echo "endpoint: https://jira.mycompany.com"
echo "editor: emacs -nw"
case $JIRA_OPERATION in
list)
echo "template: table";;
esac
Or if you always set the same overrides when you create an issue for your project you can do something like this:
#!/bin/sh
echo "project: GOJIRA"
case $JIRA_OPERATION in
create)
echo "assignee: $USER"
echo "watchers: mothra"
;;
esac
When you run command like jira edit
it will open up your favorite editor with the templatized output so you can quickly edit. When the editor
closes go-jira will submit the completed form. The order which go-jira attempts to determine your prefered editor is:
- editor property in any config.yml file
- JIRA_EDITOR environment variable
- EDITOR environment variable
- vim
go-jira has the ability to customize most output (and editor input) via templates. There are default templates available for all operations, which may or may not work for your actual jira implementation. Jira is endlessly customizable, so it is hard to provide default templates that will work for all issue types.
When running a command like jira edit
it will look through the current directory hierarchy trying to find a file that matches .jira.d/templates/edit,
if found it will use that file as the template, otherwise it will use the default edit template hard-coded into go-jira. You can export the default
hard-coded templates with jira export-templates
which will write them to ~/.jira.d/templates/.
First the basic templating functionality is defined by the Go language 'text/template' library. The library reference documentation can be found here, and there is a good primer document here. go-jira
also provides a few extra helper functions to make it a bit easlier to format the data, those functions are defined here.
Knowing what data and fields are available to any given template is not obvious. The easiest approach to determine what is available is to use the debug
template on any given operation. For eample to find out what is available to the "view" templates, you can use:
jira view GOJIRA-321 -t debug
This will print out the data in JSON format that is available to the template. You can do this for any other operation, like "list":
jira list -t debug
Figuring out what is available to input templates (like for the create
operation) is a bit more tricky, but similar. To find the data available for a create
template you can run:
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.
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
.
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). To integrate go-jira
with a supported keyring just add this configuration to $HOME/.jira.d/config.yml
:
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.
Note: Version 0.1.9 required.
An alternative to the keyring password source is the pass
tool (documentation here). 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
:
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
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:
jira (ls|list) <Query Options>
jira view ISSUE
jira edit [--noedit] <Edit Options> [ISSUE | <Query Options>]
jira create [--noedit] [-p PROJECT] <Create Options>
jira DUPLICATE dups ISSUE
jira BLOCKER blocks ISSUE
jira watch ISSUE [-w WATCHER]
jira (trans|transition) TRANSITION ISSUE [--noedit] <Edit Options>
jira ack ISSUE [--edit] <Edit Options>
jira close ISSUE [--edit] <Edit Options>
jira resolve ISSUE [--edit] <Edit Options>
jira reopen ISSUE [--edit] <Edit Options>
jira start ISSUE [--edit] <Edit Options>
jira stop ISSUE [--edit] <Edit Options>
jira comment ISSUE [--noedit] <Edit Options>
jira take ISSUE
jira (assign|give) ISSUE ASSIGNEE
jira fields
jira issuelinktypes
jira transmeta ISSUE
jira editmeta ISSUE
jira issuetypes [-p PROJECT]
jira createmeta [-p PROJECT] [-i ISSUETYPE]
jira transitions ISSUE
jira export-templates [-d DIR] [-t template]
jira (b|browse) ISSUE
jira login
jira ISSUE
General Options:
-b --browse Open your browser to the Jira issue
-e --endpoint=URI URI to use for jira
-h --help Show this usage
-t --template=FILE Template file to use for output/editing
-u --user=USER Username to use for authentication (default: $USER)
-v --verbose Increase output logging
Query Options:
-a --assignee=USER Username assigned the issue
-c --component=COMPONENT Component to Search for
-f --queryfields=FIELDS Fields that are used in "list" template: (default: summary,created,updated,priority,status,reporter,assignee)
-i --issuetype=ISSUETYPE The Issue Type
-l --limit=VAL Maximum number of results to return in query (default: 500)
-p --project=PROJECT Project to Search for
-q --query=JQL Jira Query Language expression for the search
-r --reporter=USER Reporter to search for
-s --sort=ORDER For list operations, sort issues (default: priority asc, created)
-w --watcher=USER Watcher to add to issue (default: $USER)
or Watcher to search for
Edit Options:
-m --comment=COMMENT Comment message for transition
-o --override=KEY=VAL Set custom key/value pairs
Create Options:
-i --issuetype=ISSUETYPE Jira Issue Type (default: Bug)
-m --comment=COMMENT Comment message for transition
-o --override=KEY=VAL Set custom key/value pairs
Command Options:
-d --directory=DIR Directory to export templates to (default: $HOME/.jira.d/templates)